X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftal%2Fstr%2Fstr.c;h=09c45447fb6e3e3fa53882f4e4d829cab001aa0b;hp=0c07002b157404d4bf87e517a2de166802fb0216;hb=f103f73ff040a8700a2bbd47948277e7c484baa2;hpb=d873aaec1339baf45c37db7cbaa2d687656343ba diff --git a/ccan/tal/str/str.c b/ccan/tal/str/str.c index 0c07002b..09c45447 100644 --- a/ccan/tal/str/str.c +++ b/ccan/tal/str/str.c @@ -9,98 +9,149 @@ #include #include #include -#include #include +#include +#include -char **strsplit(const void *ctx, const char *string, const char *delims, - enum strsplit flags) +char **strsplit(const tal_t *ctx, + const char *string, const char *delims, enum strsplit flags) { - char **lines = NULL; + char **parts, *str; size_t max = 64, num = 0; - lines = tal_arr(ctx, char *, max+1); + parts = tal_arr(ctx, char *, max + 1); + if (unlikely(!parts)) { + if (taken(string)) + tal_free(string); + if (taken(delims)) + tal_free(delims); + return NULL; + } + str = tal_strdup(parts, string); + if (unlikely(!str)) + goto fail; + if (unlikely(!delims) && is_taken(delims)) + goto fail; if (flags == STR_NO_EMPTY) - string += strspn(string, delims); + str += strspn(str, delims); - while (*string != '\0') { - size_t len = strcspn(string, delims), dlen; + while (*str != '\0') { + size_t len = strcspn(str, delims), dlen; - lines[num] = tal_arr(lines, char, len + 1); - memcpy(lines[num], string, len); - lines[num][len] = '\0'; - string += len; - dlen = strspn(string, delims); + parts[num] = str; + dlen = strspn(str + len, delims); + parts[num][len] = '\0'; if (flags == STR_EMPTY_OK && dlen) dlen = 1; - string += dlen; - if (++num == max) - tal_resize(&lines, max*=2 + 1); + str += len + dlen; + if (++num == max && !tal_resize(&parts, max*=2 + 1)) + goto fail; } - lines[num] = NULL; - return lines; + parts[num] = NULL; + if (taken(delims)) + tal_free(delims); + return parts; + +fail: + tal_free(parts); + if (taken(delims)) + tal_free(delims); + return NULL; } -char *strjoin(const void *ctx, char *strings[], const char *delim, - enum strjoin flags) +char *strjoin(const tal_t *ctx, + char *strings[], const char *delim, enum strjoin flags) { unsigned int i; - char *ret = tal_strdup(ctx, ""); - size_t totlen = 0, dlen = strlen(delim); + char *ret = NULL; + size_t totlen = 0, dlen; + if (unlikely(!strings) && is_taken(strings)) + goto fail; + + if (unlikely(!delim) && is_taken(delim)) + goto fail; + + dlen = strlen(delim); + ret = tal_arr(ctx, char, dlen*2+1); + if (!ret) + goto fail; + + ret[0] = '\0'; for (i = 0; strings[i]; i++) { size_t len = strlen(strings[i]); + if (flags == STR_NO_TRAIL && !strings[i+1]) dlen = 0; - tal_resize(&ret, totlen + len + dlen + 1); + if (!tal_resize(&ret, totlen + len + dlen + 1)) + goto fail; memcpy(ret + totlen, strings[i], len); totlen += len; memcpy(ret + totlen, delim, dlen); totlen += dlen; } ret[totlen] = '\0'; +out: + if (taken(strings)) + tal_free(strings); + if (taken(delim)) + tal_free(delim); return ret; +fail: + ret = tal_free(ret); + goto out; } -bool strreg(const void *ctx, const char *string, const char *regex, ...) +bool strreg(const tal_t *ctx, const char *string, const char *regex, ...) { size_t nmatch = 1 + strcount(regex, "("); - regmatch_t *matches = tal_arr(ctx, regmatch_t, nmatch); + regmatch_t matches[nmatch]; regex_t r; - bool ret; - - if (!matches || regcomp(&r, regex, REG_EXTENDED) != 0) - return false; - - if (regexec(&r, string, nmatch, matches, 0) == 0) { - unsigned int i; - va_list ap; - - ret = true; - va_start(ap, regex); - for (i = 1; i < nmatch; i++) { - char **arg; - arg = va_arg(ap, char **); - if (arg) { - /* eg. ([a-z])? can give "no match". */ - if (matches[i].rm_so == -1) - *arg = NULL; - else { - *arg = tal_strndup(ctx, - string + matches[i].rm_so, - matches[i].rm_eo - - matches[i].rm_so); - if (!*arg) { - ret = false; - break; - } + bool ret = false; + unsigned int i; + va_list ap; + + if (unlikely(!regex) && is_taken(regex)) + goto fail_no_re; + + if (regcomp(&r, regex, REG_EXTENDED) != 0) + goto fail_no_re; + + if (unlikely(!string) && is_taken(string)) + goto fail; + + if (regexec(&r, string, nmatch, matches, 0) != 0) + goto fail; + + ret = true; + va_start(ap, regex); + for (i = 1; i < nmatch; i++) { + char **arg = va_arg(ap, char **); + if (arg) { + /* eg. ([a-z])? can give "no match". */ + if (matches[i].rm_so == -1) + *arg = NULL; + else { + *arg = tal_strndup(ctx, + string + matches[i].rm_so, + matches[i].rm_eo + - matches[i].rm_so); + /* FIXME: If we fail, we set some and leak! */ + if (!*arg) { + ret = false; + break; } } } - va_end(ap); - } else - ret = false; - tal_free(matches); + } + va_end(ap); +fail: regfree(&r); +fail_no_re: + if (taken(regex)) + tal_free(regex); + if (taken(string)) + tal_free(string); return ret; }