1 /* Licensed under BSD-MIT - see LICENSE file for details */
13 #include <ccan/str/str.h>
15 char *tal_strdup(const tal_t *ctx, const char *p)
17 /* We have to let through NULL for take(). */
18 return tal_dup_(ctx, p, 1, p ? strlen(p) + 1: 1, 0, false,
19 TAL_LABEL(char, "[]"));
22 char *tal_strndup(const tal_t *ctx, const char *p, size_t n)
27 /* We have to let through NULL for take(). */
33 ret = tal_dup_(ctx, p, 1, len, 1, false, TAL_LABEL(char, "[]"));
39 char *tal_fmt(const tal_t *ctx, const char *fmt, ...)
45 ret = tal_vfmt(ctx, fmt, ap);
51 static bool do_vfmt(char **buf, size_t off, const char *fmt, va_list ap)
53 /* A decent guess to start. */
54 size_t max = strlen(fmt) * 2 + 1;
61 if (!tal_resize(buf, off + max)) {
67 ret = vsnprintf(*buf + off, max, fmt, ap2);
82 char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap)
86 if (!fmt && taken(fmt))
89 /* A decent guess to start. */
90 buf = tal_arr(ctx, char, strlen(fmt) * 2);
91 if (!do_vfmt(&buf, 0, fmt, ap))
96 bool tal_append_vfmt(char **baseptr, const char *fmt, va_list ap)
98 if (!fmt && taken(fmt))
101 return do_vfmt(baseptr, strlen(*baseptr), fmt, ap);
104 bool tal_append_fmt(char **baseptr, const char *fmt, ...)
110 ret = tal_append_vfmt(baseptr, fmt, ap);
116 char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2)
121 if (unlikely(!s2) && taken(s2)) {
126 /* We have to let through NULL for take(). */
127 len1 = s1 ? strlen(s1) : 0;
130 /* We use tal_dup_ here to avoid attaching a length property. */
131 ret = tal_dup_(ctx, s1, 1, len1, len2 + 1, false,
132 TAL_LABEL(char, "[]"));
134 memcpy(ret + len1, s2, len2 + 1);
141 char **tal_strsplit(const tal_t *ctx,
142 const char *string, const char *delims, enum strsplit flags)
145 size_t max = 64, num = 0;
147 parts = tal_arr(ctx, char *, max + 1);
148 if (unlikely(!parts)) {
155 str = tal_strdup(parts, string);
158 if (unlikely(!delims) && is_taken(delims))
161 if (flags == STR_NO_EMPTY)
162 str += strspn(str, delims);
164 while (*str != '\0') {
165 size_t len = strcspn(str, delims), dlen;
168 dlen = strspn(str + len, delims);
169 parts[num][len] = '\0';
170 if (flags == STR_EMPTY_OK && dlen)
173 if (++num == max && !tal_resize(&parts, max*=2 + 1))
178 /* Ensure that tal_count() is correct. */
179 if (unlikely(!tal_resize(&parts, num+1)))
193 char *tal_strjoin(const tal_t *ctx,
194 char *strings[], const char *delim, enum strjoin flags)
198 size_t totlen = 0, dlen;
200 if (unlikely(!strings) && is_taken(strings))
203 if (unlikely(!delim) && is_taken(delim))
206 dlen = strlen(delim);
207 ret = tal_arr(ctx, char, dlen*2+1);
212 for (i = 0; strings[i]; i++) {
213 size_t len = strlen(strings[i]);
215 if (flags == STR_NO_TRAIL && !strings[i+1])
217 if (!tal_resize(&ret, totlen + len + dlen + 1))
219 memcpy(ret + totlen, strings[i], len);
221 memcpy(ret + totlen, delim, dlen);
236 static size_t count_open_braces(const char *string)
239 size_t num = 0, esc = 0;
245 /* An odd number of \ means it's escaped. */
246 if (*string == '(' && (esc & 1) == 0)
254 return strcount(string, "(");
258 bool tal_strreg(const tal_t *ctx, const char *string, const char *regex, ...)
260 size_t nmatch = 1 + count_open_braces(regex);
261 regmatch_t matches[nmatch];
267 if (unlikely(!regex) && is_taken(regex))
270 if (regcomp(&r, regex, REG_EXTENDED) != 0)
273 if (unlikely(!string) && is_taken(string))
276 if (regexec(&r, string, nmatch, matches, 0) != 0)
281 for (i = 1; i < nmatch; i++) {
282 char **arg = va_arg(ap, char **);
284 /* eg. ([a-z])? can give "no match". */
285 if (matches[i].rm_so == -1)
288 *arg = tal_strndup(ctx,
289 string + matches[i].rm_so,
292 /* FIXME: If we fail, we set some and leak! */