0c07002b157404d4bf87e517a2de166802fb0216
[ccan] / ccan / tal / str / str.c
1 /* Licensed under BSD-MIT - 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.h"
8 #include <sys/types.h>
9 #include <regex.h>
10 #include <stdarg.h>
11 #include <unistd.h>
12 #include <ccan/tal/tal.h>
13 #include <ccan/str/str.h>
14
15 char **strsplit(const void *ctx, const char *string, const char *delims,
16                 enum strsplit flags)
17 {
18         char **lines = NULL;
19         size_t max = 64, num = 0;
20
21         lines = tal_arr(ctx, char *, max+1);
22
23         if (flags == STR_NO_EMPTY)
24                 string += strspn(string, delims);
25
26         while (*string != '\0') {
27                 size_t len = strcspn(string, delims), dlen;
28
29                 lines[num] = tal_arr(lines, char, len + 1);
30                 memcpy(lines[num], string, len);
31                 lines[num][len] = '\0';
32                 string += len;
33                 dlen = strspn(string, delims);
34                 if (flags == STR_EMPTY_OK && dlen)
35                         dlen = 1;
36                 string += dlen;
37                 if (++num == max)
38                         tal_resize(&lines, max*=2 + 1);
39         }
40         lines[num] = NULL;
41         return lines;
42 }
43
44 char *strjoin(const void *ctx, char *strings[], const char *delim,
45               enum strjoin flags)
46 {
47         unsigned int i;
48         char *ret = tal_strdup(ctx, "");
49         size_t totlen = 0, dlen = strlen(delim);
50
51         for (i = 0; strings[i]; i++) {
52                 size_t len = strlen(strings[i]);
53                 if (flags == STR_NO_TRAIL && !strings[i+1])
54                         dlen = 0;
55                 tal_resize(&ret, totlen + len + dlen + 1);
56                 memcpy(ret + totlen, strings[i], len);
57                 totlen += len;
58                 memcpy(ret + totlen, delim, dlen);
59                 totlen += dlen;
60         }
61         ret[totlen] = '\0';
62         return ret;
63 }
64
65 bool strreg(const void *ctx, const char *string, const char *regex, ...)
66 {
67         size_t nmatch = 1 + strcount(regex, "(");
68         regmatch_t *matches = tal_arr(ctx, regmatch_t, nmatch);
69         regex_t r;
70         bool ret;
71
72         if (!matches || regcomp(&r, regex, REG_EXTENDED) != 0)
73                 return false;
74
75         if (regexec(&r, string, nmatch, matches, 0) == 0) {
76                 unsigned int i;
77                 va_list ap;
78
79                 ret = true;
80                 va_start(ap, regex);
81                 for (i = 1; i < nmatch; i++) {
82                         char **arg;
83                         arg = va_arg(ap, char **);
84                         if (arg) {
85                                 /* eg. ([a-z])? can give "no match". */
86                                 if (matches[i].rm_so == -1)
87                                         *arg = NULL;
88                                 else {
89                                         *arg = tal_strndup(ctx,
90                                                       string + matches[i].rm_so,
91                                                       matches[i].rm_eo
92                                                       - matches[i].rm_so);
93                                         if (!*arg) {
94                                                 ret = false;
95                                                 break;
96                                         }
97                                 }
98                         }
99                 }
100                 va_end(ap);
101         } else
102                 ret = false;
103         tal_free(matches);
104         regfree(&r);
105         return ret;
106 }