X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftal%2Fstr%2Fstr.c;h=059817b6aa7e928b8e9ceeef372e2510b6ebd3f3;hb=f0308b852cda745a74f5135971ad6c0747886df1;hp=09c45447fb6e3e3fa53882f4e4d829cab001aa0b;hpb=f103f73ff040a8700a2bbd47948277e7c484baa2;p=ccan diff --git a/ccan/tal/str/str.c b/ccan/tal/str/str.c index 09c45447..059817b6 100644 --- a/ccan/tal/str/str.c +++ b/ccan/tal/str/str.c @@ -9,12 +9,140 @@ #include #include #include +#include #include -#include #include -char **strsplit(const tal_t *ctx, - const char *string, const char *delims, enum strsplit flags) +char *tal_strdup(const tal_t *ctx, const char *p) +{ + /* We have to let through NULL for take(). */ + return tal_dup_(ctx, p, 1, p ? strlen(p) + 1: 1, 0, false, + TAL_LABEL(char, "[]")); +} + +char *tal_strndup(const tal_t *ctx, const char *p, size_t n) +{ + size_t len; + char *ret; + + /* We have to let through NULL for take(). */ + if (likely(p)) { + len = strlen(p); + if (len > n) + len = n; + } else + len = n; + + ret = tal_dup_(ctx, p, 1, len, 1, false, TAL_LABEL(char, "[]")); + if (ret) + ret[len] = '\0'; + return ret; +} + +char *tal_fmt(const tal_t *ctx, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = tal_vfmt(ctx, fmt, ap); + va_end(ap); + + return ret; +} + +static bool do_vfmt(char **buf, size_t off, const char *fmt, va_list ap) +{ + /* A decent guess to start. */ + size_t max = strlen(fmt) * 2; + bool ok; + + for (;;) { + va_list ap2; + int ret; + + if (!tal_resize(buf, off + max)) { + ok = false; + break; + } + + va_copy(ap2, ap); + ret = vsnprintf(*buf + off, max, fmt, ap2); + va_end(ap2); + + if (ret < max) { + ok = true; + break; + } + max *= 2; + } + + if (taken(fmt)) + tal_free(fmt); + return ok; +} + +char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap) +{ + char *buf; + + if (!fmt && taken(fmt)) + return NULL; + + /* A decent guess to start. */ + buf = tal_arr(ctx, char, strlen(fmt) * 2); + if (!do_vfmt(&buf, 0, fmt, ap)) + buf = tal_free(buf); + return buf; +} + +bool tal_append_vfmt(char **baseptr, const char *fmt, va_list ap) +{ + if (!fmt && taken(fmt)) + return false; + + return do_vfmt(baseptr, strlen(*baseptr), fmt, ap); +} + +bool tal_append_fmt(char **baseptr, const char *fmt, ...) +{ + va_list ap; + bool ret; + + va_start(ap, fmt); + ret = tal_append_vfmt(baseptr, fmt, ap); + va_end(ap); + + return ret; +} + +char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2) +{ + size_t len1, len2; + char *ret; + + if (unlikely(!s2) && taken(s2)) { + if (taken(s1)) + tal_free(s1); + return NULL; + } + /* We have to let through NULL for take(). */ + len1 = s1 ? strlen(s1) : 0; + len2 = strlen(s2); + + /* We use tal_dup_ here to avoid attaching a length property. */ + ret = tal_dup_(ctx, s1, 1, len1, len2 + 1, false, + TAL_LABEL(char, "[]")); + if (likely(ret)) + memcpy(ret + len1, s2, len2 + 1); + + if (taken(s2)) + tal_free(s2); + return ret; +} + +char **tal_strsplit(const tal_t *ctx, + const char *string, const char *delims, enum strsplit flags) { char **parts, *str; size_t max = 64, num = 0; @@ -49,6 +177,11 @@ char **strsplit(const tal_t *ctx, goto fail; } parts[num] = NULL; + + /* Ensure that tal_count() is correct. */ + if (unlikely(!tal_resize(&parts, num+1))) + goto fail; + if (taken(delims)) tal_free(delims); return parts; @@ -60,8 +193,8 @@ fail: return NULL; } -char *strjoin(const tal_t *ctx, - char *strings[], const char *delim, enum strjoin flags) +char *tal_strjoin(const tal_t *ctx, + char *strings[], const char *delim, enum strjoin flags) { unsigned int i; char *ret = NULL; @@ -103,9 +236,31 @@ fail: goto out; } -bool strreg(const tal_t *ctx, const char *string, const char *regex, ...) +static size_t count_open_braces(const char *string) +{ +#if 1 + size_t num = 0, esc = 0; + + while (*string) { + if (*string == '\\') + esc++; + else { + /* An odd number of \ means it's escaped. */ + if (*string == '(' && (esc & 1) == 0) + num++; + esc = 0; + } + string++; + } + return num; +#else + return strcount(string, "("); +#endif +} + +bool tal_strreg(const tal_t *ctx, const char *string, const char *regex, ...) { - size_t nmatch = 1 + strcount(regex, "("); + size_t nmatch = 1 + count_open_braces(regex); regmatch_t matches[nmatch]; regex_t r; bool ret = false;