tdb2: copy tdb1's changed expansion logic.
[ccan] / ccan / str_talloc / str_talloc.c
1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #include <unistd.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <limits.h>
6 #include <stdlib.h>
7 #include "str_talloc.h"
8 #include <sys/types.h>
9 #include <regex.h>
10 #include <stdarg.h>
11 #include <unistd.h>
12 #include <ccan/talloc/talloc.h>
13 #include <ccan/str/str.h>
14
15 char **strsplit(const void *ctx, const char *string, const char *delims)
16 {
17         char **lines = NULL;
18         unsigned int max = 64, num = 0;
19
20         lines = talloc_array(ctx, char *, max+1);
21
22         while (*string != '\0') {
23                 unsigned int len = strcspn(string, delims);
24                 lines[num] = talloc_array(lines, char, len + 1);
25                 memcpy(lines[num], string, len);
26                 lines[num][len] = '\0';
27                 string += len;
28                 string += strspn(string, delims) ? 1 : 0;
29                 if (++num == max)
30                         lines = talloc_realloc(ctx, lines, char *, max*=2 + 1);
31         }
32         lines[num] = NULL;
33
34         /* Shrink, so talloc_get_size works */
35         return talloc_realloc(ctx, lines, char *, num+1);
36 }
37
38 char *strjoin(const void *ctx, char *strings[], const char *delim)
39 {
40         unsigned int i;
41         char *ret = talloc_strdup(ctx, "");
42         size_t totlen = 0, dlen = strlen(delim);
43
44         for (i = 0; strings[i]; i++) {
45                 size_t len = strlen(strings[i]);
46                 ret = talloc_realloc(ctx, ret, char, totlen + len + dlen + 1);
47                 memcpy(ret + totlen, strings[i], len);
48                 totlen += len;
49                 memcpy(ret + totlen, delim, dlen);
50                 totlen += dlen;
51         }
52         ret[totlen] = '\0';
53         return ret;
54 }
55
56 bool strreg(const void *ctx, const char *string, const char *regex, ...)
57 {
58         size_t nmatch = 1 + strcount(regex, "(");
59         regmatch_t *matches = talloc_array(ctx, regmatch_t, nmatch);
60         regex_t r;
61         bool ret;
62
63         if (!matches || regcomp(&r, regex, REG_EXTENDED) != 0)
64                 return false;
65
66         if (regexec(&r, string, nmatch, matches, 0) == 0) {
67                 unsigned int i;
68                 va_list ap;
69
70                 ret = true;
71                 va_start(ap, regex);
72                 for (i = 1; i < nmatch; i++) {
73                         char **arg;
74                         arg = va_arg(ap, char **);
75                         if (arg) {
76                                 /* eg. ([a-z])? can give "no match". */
77                                 if (matches[i].rm_so == -1)
78                                         *arg = NULL;
79                                 else {
80                                         *arg = talloc_strndup(ctx,
81                                                       string + matches[i].rm_so,
82                                                       matches[i].rm_eo
83                                                       - matches[i].rm_so);
84                                         if (!*arg) {
85                                                 ret = false;
86                                                 break;
87                                         }
88                                 }
89                         }
90                 }
91                 va_end(ap);
92         } else
93                 ret = false;
94         talloc_free(matches);
95         regfree(&r);
96         return ret;
97 }