Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * FRR string processing utilities.
4 : * Copyright (C) 2018 Cumulus Networks, Inc.
5 : * Quentin Young
6 : * Copyright (c) 2023, LabN Consulting, L.L.C.
7 : */
8 :
9 : #include "zebra.h"
10 :
11 : #include <string.h>
12 : #include <ctype.h>
13 : #include <sys/types.h>
14 : #ifdef HAVE_LIBPCRE2_POSIX
15 : #ifndef _FRR_PCRE2_POSIX
16 : #define _FRR_PCRE2_POSIX
17 : #include <pcre2posix.h>
18 : #endif /* _FRR_PCRE2_POSIX */
19 : #elif defined(HAVE_LIBPCREPOSIX)
20 : #include <pcreposix.h>
21 : #else
22 : #include <regex.h>
23 : #endif /* HAVE_LIBPCRE2_POSIX */
24 :
25 : #include "frrstr.h"
26 : #include "memory.h"
27 : #include "vector.h"
28 :
29 79 : void frrstr_split(const char *string, const char *delimiter, char ***result,
30 : int *argc)
31 : {
32 79 : if (!string)
33 0 : return;
34 :
35 79 : unsigned int sz = 4, idx = 0;
36 79 : char *copy, *copystart;
37 79 : *result = XCALLOC(MTYPE_TMP, sizeof(char *) * sz);
38 79 : copystart = copy = XSTRDUP(MTYPE_TMP, string);
39 79 : *argc = 0;
40 :
41 79 : const char *tok = NULL;
42 :
43 338 : while (copy) {
44 259 : tok = strsep(©, delimiter);
45 259 : (*result)[idx] = XSTRDUP(MTYPE_TMP, tok);
46 259 : if (++idx == sz)
47 33 : *result = XREALLOC(MTYPE_TMP, *result,
48 : (sz *= 2) * sizeof(char *));
49 259 : (*argc)++;
50 : }
51 :
52 79 : XFREE(MTYPE_TMP, copystart);
53 : }
54 :
55 79 : vector frrstr_split_vec(const char *string, const char *delimiter)
56 : {
57 79 : char **result;
58 79 : int argc;
59 :
60 79 : if (!string)
61 : return NULL;
62 :
63 79 : frrstr_split(string, delimiter, &result, &argc);
64 :
65 79 : vector v = array_to_vector((void **)result, argc);
66 :
67 79 : XFREE(MTYPE_TMP, result);
68 :
69 79 : return v;
70 : }
71 :
72 0 : char *frrstr_join(const char **parts, int argc, const char *join)
73 : {
74 0 : int i;
75 0 : char *str;
76 0 : char *p;
77 0 : size_t len = 0;
78 0 : size_t joinlen = join ? strlen(join) : 0;
79 :
80 0 : if (!argc)
81 : return NULL;
82 :
83 0 : for (i = 0; i < argc; i++)
84 0 : len += strlen(parts[i]);
85 0 : len += argc * joinlen + 1;
86 :
87 0 : if (!len)
88 : return NULL;
89 :
90 0 : p = str = XMALLOC(MTYPE_TMP, len);
91 :
92 0 : for (i = 0; i < argc; i++) {
93 0 : size_t arglen = strlen(parts[i]);
94 :
95 0 : memcpy(p, parts[i], arglen);
96 0 : p += arglen;
97 0 : if (i + 1 != argc && join) {
98 0 : memcpy(p, join, joinlen);
99 0 : p += joinlen;
100 : }
101 : }
102 :
103 0 : *p = '\0';
104 :
105 0 : return str;
106 : }
107 :
108 0 : char *frrstr_join_vec(vector v, const char *join)
109 : {
110 0 : char **argv;
111 0 : int argc;
112 :
113 0 : vector_to_array(v, (void ***)&argv, &argc);
114 :
115 0 : char *ret = frrstr_join((const char **)argv, argc, join);
116 :
117 0 : XFREE(MTYPE_TMP, argv);
118 :
119 0 : return ret;
120 : }
121 :
122 0 : void frrstr_filter_vec(vector v, regex_t *filter)
123 : {
124 0 : regmatch_t ignored[1];
125 :
126 0 : for (unsigned int i = 0; i < vector_active(v); i++) {
127 0 : if (regexec(filter, vector_slot(v, i), 0, ignored, 0)) {
128 0 : XFREE(MTYPE_TMP, vector_slot(v, i));
129 0 : vector_unset(v, i);
130 : }
131 : }
132 0 : }
133 :
134 79 : void frrstr_strvec_free(vector v)
135 : {
136 79 : unsigned int i;
137 79 : char *cp;
138 :
139 79 : if (!v)
140 : return;
141 :
142 292 : for (i = 0; i < vector_active(v); i++) {
143 213 : cp = vector_slot(v, i);
144 213 : XFREE(MTYPE_TMP, cp);
145 : }
146 :
147 79 : vector_free(v);
148 : }
149 :
150 0 : char *frrstr_replace(const char *str, const char *find, const char *replace)
151 : {
152 0 : char *ch;
153 0 : char *nustr = XSTRDUP(MTYPE_TMP, str);
154 :
155 0 : size_t findlen = strlen(find);
156 0 : size_t repllen = strlen(replace);
157 :
158 0 : while ((ch = strstr(nustr, find))) {
159 0 : if (repllen > findlen) {
160 0 : size_t nusz = strlen(nustr) + repllen - findlen + 1;
161 0 : nustr = XREALLOC(MTYPE_TMP, nustr, nusz);
162 0 : ch = strstr(nustr, find);
163 : }
164 :
165 0 : size_t nustrlen = strlen(nustr);
166 0 : size_t taillen = (nustr + nustrlen) - (ch + findlen);
167 :
168 0 : memmove(ch + findlen + (repllen - findlen), ch + findlen,
169 : taillen + 1);
170 0 : memcpy(ch, replace, repllen);
171 : }
172 :
173 0 : return nustr;
174 : }
175 :
176 0 : bool frrstr_startswith(const char *str, const char *prefix)
177 : {
178 0 : if (!str || !prefix)
179 : return false;
180 :
181 0 : size_t lenstr = strlen(str);
182 0 : size_t lenprefix = strlen(prefix);
183 :
184 0 : if (lenprefix > lenstr)
185 : return false;
186 :
187 0 : return strncmp(str, prefix, lenprefix) == 0;
188 : }
189 :
190 0 : bool frrstr_endswith(const char *str, const char *suffix)
191 : {
192 0 : if (!str || !suffix)
193 : return false;
194 :
195 0 : size_t lenstr = strlen(str);
196 0 : size_t lensuffix = strlen(suffix);
197 :
198 0 : if (lensuffix > lenstr)
199 : return false;
200 :
201 0 : return strncmp(&str[lenstr - lensuffix], suffix, lensuffix) == 0;
202 : }
203 :
204 0 : int all_digit(const char *str)
205 : {
206 0 : for (; *str != '\0'; str++)
207 0 : if (!isdigit((unsigned char)*str))
208 : return 0;
209 : return 1;
210 : }
211 :
212 :
213 0 : char *frrstr_hex(char *buff, size_t bufsiz, const uint8_t *str, size_t num)
214 : {
215 0 : if (bufsiz == 0)
216 : return buff;
217 :
218 0 : char tmp[3];
219 :
220 0 : buff[0] = '\0';
221 :
222 0 : for (size_t i = 0; i < num; i++) {
223 0 : snprintf(tmp, sizeof(tmp), "%02x", (unsigned char)str[i]);
224 0 : strlcat(buff, tmp, bufsiz);
225 : }
226 :
227 : return buff;
228 : }
229 :
230 0 : const char *frrstr_skip_over_char(const char *s, int skipc)
231 : {
232 0 : int c, quote = 0;
233 :
234 0 : while ((c = *s++)) {
235 0 : if (c == '\\') {
236 0 : if (!*s++)
237 : return NULL;
238 0 : continue;
239 : }
240 0 : if (quote) {
241 0 : if (c == quote)
242 0 : quote = 0;
243 0 : continue;
244 : }
245 0 : if (c == skipc)
246 0 : return s;
247 0 : if (c == '"' || c == '\'')
248 0 : quote = c;
249 : }
250 : return NULL;
251 : }
|