cis_config
regex_posix.h
1 #include <regex.h>
2 #include <stdint.h>
3 
5 #ifndef REGEX_POSIX_H_
6 #define REGEX_POSIX_H_
7 
16 static inline
17 int compile_regex (regex_t * r, const char * regex_text)
18 {
19  int status = regcomp (r, regex_text, REG_EXTENDED);//|REG_NEWLINE);
20  if (status != 0) {
21  char error_message[2048];
22  regerror (status, r, error_message, 2048);
23  printf ("Regex error compiling '%s': %s\n",
24  regex_text, error_message);
25  return 1;
26  }
27  return 0;
28 };
29 
39 static inline
40 int count_matches(const char *regex_text, const char *to_match) {
41  int ret;
42  int n_match = 0;
43  regex_t r;
44  // Compile
45  ret = compile_regex(&r, regex_text);
46  if (ret)
47  return -1;
48  // Loop until string done
49  const char * p = to_match;
50  const size_t n_sub_matches = 10;
51  regmatch_t m[n_sub_matches];
52  while (1) {
53  int nomatch = regexec(&r, p, n_sub_matches, m, 0);
54  if (nomatch)
55  break;
56  n_match++;
57  p += m[0].rm_eo;
58  }
59  regfree(&r);
60  return n_match;
61 };
62 
63 
75 static inline
76 int find_match(const char *regex_text, const char *to_match,
77  size_t *sind, size_t *eind) {
78  int ret;
79  int n_match = 0;
80  regex_t r;
81  // Compile
82  ret = compile_regex(&r, regex_text);
83  if (ret)
84  return -1;
85  // Loop until string done
86  const char * p = to_match;
87  const size_t n_sub_matches = 10;
88  regmatch_t m[n_sub_matches];
89  int nomatch = regexec(&r, p, n_sub_matches, m, 0);
90  if (!(nomatch)) {
91  *sind = m[0].rm_so;
92  *eind = m[0].rm_eo;
93  n_match++;
94  }
95  regfree(&r);
96  return n_match;
97 };
98 
99 
111 static inline
112 int find_matches(const char *regex_text, const char *to_match,
113  size_t **sind, size_t **eind) {
114  int ret;
115  int n_match = 0;
116  regex_t r;
117  // Compile
118  ret = compile_regex(&r, regex_text);
119  if (ret)
120  return -1;
121  // Loop until string done
122  const size_t n_sub_matches = 10;
123  regmatch_t m[n_sub_matches];
124  int nomatch = regexec(&r, to_match, n_sub_matches, m, 0);
125  if (!(nomatch)) {
126  // Count
127  while (1) {
128  if ((m[n_match].rm_so == -1) && (m[n_match].rm_eo == -1)) {
129  break;
130  }
131  n_match++;
132  }
133  // Realloc
134  *sind = (size_t*)realloc(*sind, n_match*sizeof(size_t));
135  *eind = (size_t*)realloc(*eind, n_match*sizeof(size_t));
136  // Record
137  int i;
138  for (i = 0; i < n_match; i++) {
139  (*sind)[i] = m[i].rm_so;
140  (*eind)[i] = m[i].rm_eo;
141  }
142  }
143  regfree(&r);
144  return n_match;
145 };
146 
147 
161 static inline
162 int regex_replace_nosub(char *buf, const size_t len_buf,
163  const char *re, const char *rp,
164  const size_t nreplace) {
165  /* printf("regex_replace_nosub(%s, %s, %s)\n", buf, re, rp); */
166  // Compile
167  regex_t r;
168  int ret = compile_regex(&r, re);
169  if (ret)
170  return -1;
171  // Loop making replacements
172  size_t len_rp = strlen(rp);
173  char * p = buf;
174  const size_t ngroups = r.re_nsub + 1;
175  regmatch_t *m = (regmatch_t*)malloc(ngroups * sizeof(regmatch_t));
176  size_t len_m, rem_s, rem_l, delta_siz;
177  size_t cur_pos = 0;
178  size_t cur_siz = strlen(buf);
179  size_t creplace = 0;
180  while (1) {
181  if ((nreplace > 0) && (creplace >= nreplace)) {
182  printf("regex_replace_nosub: Maximum of %d replacements reached\n",
183  (int)creplace);
184  break;
185  }
186  int nomatch = regexec(&r, p, ngroups, m, 0);
187  if (nomatch) {
188  /* printf("regex_replace_nosub: nomatch for %s in %s\n", re, p); */
189  break;
190  }
191  // Ensure replacement will not exceed buffer
192  len_m = m[0].rm_eo - m[0].rm_so;
193  delta_siz = len_rp - len_m;
194  if ((cur_siz + delta_siz + 1) > len_buf) {
195  printf("regex_replace_nosub: Relacement will exceed buffer.\n");
196  cur_siz = -1;
197  break;
198  }
199  // Move trailing
200  rem_l = cur_siz - (cur_pos + m[0].rm_eo);
201  rem_s = m[0].rm_so + len_rp;
202  memmove(p + rem_s, p + m[0].rm_eo, rem_l + 1);
203  // Copy replacement
204  strncpy(p + m[0].rm_so, rp, len_rp);
205  // Advance
206  p += rem_s;
207  cur_pos += rem_s;
208  cur_siz += delta_siz;
209  creplace += 1;
210  }
211  /* printf("regex_replace_nosub() = %s\n", buf); */
212  free(m);
213  regfree(&r);
214  return cur_siz;
215 };
216 
217 
227 static inline
228 int get_subrefs(const char *buf, size_t **refs) {
229  // Compile
230  regex_t r;
231  int ret = compile_regex(&r, "\\$([[:digit:]])");
232  if (ret)
233  return -1;
234  // Allocate;
235  const size_t ngroups = r.re_nsub + 1;
236  if (ngroups != 2) {
237  printf("ERROR: regex could not find subgroup\n");
238  regfree(&r);
239  return -1;
240  }
241  regmatch_t *m = (regmatch_t*)malloc(ngroups * sizeof(regmatch_t));
242  // Prepare "bitmap"
243  const size_t max_ref = 10; //99;
244  size_t i;
245  uint8_t *ref_bytes = (uint8_t*)malloc((max_ref + 1)*sizeof(uint8_t));
246  for (i = 0; i <= max_ref; i++)
247  ref_bytes[i] = 0;
248  // Locate matches
249  const char *p = buf;
250  const size_t max_grp = 2; // Digits in max_ref
251  size_t igrp_len;
252  char igrp[max_grp];
253  size_t iref;
254  while (1) {
255  int nomatch = regexec(&r, p, ngroups, m, 0);
256  if (nomatch) {
257  break;
258  }
259  // Lone $ without digit
260  /* printf("so = %d, eo = %d\n", m[1].rm_so, m[1].rm_eo); */
261  if ((m[1].rm_so == -1) && (m[1].rm_eo == -1)) {
262  p += m[0].rm_eo;
263  continue;
264  }
265  // Substring
266  igrp_len = m[1].rm_eo - m[1].rm_so;
267  if (igrp_len > max_grp) {
268  printf("Number longer than %d digits unlikely.\n", (int)max_grp);
269  free(m);
270  free(ref_bytes);
271  regfree(&r);
272  return -1;
273  }
274  strncpy(igrp, p + m[1].rm_so, igrp_len);
275  igrp[igrp_len] = 0;
276  // Extract ref number
277  iref = atoi(igrp);
278  if (iref > max_ref) {
279  printf("Reference to substr %d exceeds limit (%d)\n",
280  (int)iref, (int)max_ref);
281  free(m);
282  free(ref_bytes);
283  regfree(&r);
284  return -1;
285  }
286  ref_bytes[iref] = 1;
287  p += m[0].rm_eo;
288  }
289  // Get unique refs
290  int nref = 0;
291  for (i = 0; i <= max_ref; i++) {
292  if (ref_bytes[i])
293  nref++;
294  }
295  *refs = (size_t*)realloc(*refs, nref*sizeof(size_t));
296  size_t ir;
297  for (i = 0, ir = 0; i <= max_ref; i++) {
298  if (ref_bytes[i]) {
299  (*refs)[ir] = i;
300  ir++;
301  }
302  }
303  free(m);
304  free(ref_bytes);
305  regfree(&r);
306  // printf("%d refs in %s\n", nref, buf);
307  return nref;
308 };
309 
310 
324 static inline
325 int regex_replace_sub(char *buf, const size_t len_buf,
326  const char *re, const char *rp,
327  const size_t nreplace) {
328  // Compile
329  regex_t r;
330  int ret = compile_regex(&r, re);
331  if (ret)
332  return -1;
333  // Loop making replacements
334  char * p = buf;
335  const size_t ngroups = r.re_nsub + 1;
336  regmatch_t *m = (regmatch_t*)malloc(ngroups * sizeof(regmatch_t));
337  char rp_sub[2*len_buf];
338  char re_sub[len_buf];
339  char igrp[len_buf];
340  size_t len_m, rem_s, rem_l, delta_siz, len_rp;
341  size_t cur_pos = 0;
342  size_t cur_siz = strlen(buf);
343  size_t creplace = 0;
344  size_t i;
345  int j;
346  while (1) {
347  if ((nreplace > 0) && (creplace >= nreplace)) {
348  printf("regex_replace_nosub: Maximum of %d replacements reached\n",
349  (int)creplace);
350  break;
351  }
352  int nomatch = regexec(&r, p, ngroups, m, 0);
353  if (nomatch) {
354  /* printf("regex_replace_sub: nomatch for %s in %s\n", re, p); */
355  break;
356  }
357  // Get list of subrefs
358  size_t *refs = NULL;
359  int nref = get_subrefs(rp, &refs);
360  if (nref < 0) {
361  printf("Error gettings subrefs\n");
362  free(m);
363  regfree(&r);
364  return -1;
365  }
366  // For each subref complete replacements
367  strcpy(rp_sub, rp);
368  for (j = 0; j < nref; j++) {
369  i = refs[j];
370  strcpy(igrp, p + m[i].rm_so);
371  igrp[m[i].rm_eo - m[i].rm_so] = 0; // terminate
372  sprintf(re_sub, "\\$%d", (int)i);
373  ret = regex_replace_nosub(rp_sub, 2*len_buf, re_sub, igrp, 0);
374  if (ret < 0) {
375  printf("regex_replace_sub: Error replacing substring $%d.\n", (int)i);
376  free(m);
377  regfree(&r);
378  return -1;
379  }
380  }
381  // Ensure replacement will not exceed buffer
382  len_rp = ret;
383  len_m = m[0].rm_eo - m[0].rm_so;
384  delta_siz = len_rp - len_m;
385  if ((cur_siz + delta_siz + 1) > len_buf) {
386  printf("regex_replace_sub: Relacement will exceed buffer.\n");
387  free(m);
388  regfree(&r);
389  return -1;
390  }
391  // Move trailing
392  rem_l = cur_siz - (cur_pos + m[0].rm_eo);
393  rem_s = m[0].rm_so + len_rp;
394  memmove(p + rem_s, p + m[0].rm_eo, rem_l + 1);
395  // Copy replacement
396  strncpy(p + m[0].rm_so, rp_sub, len_rp);
397  // Advance
398  p += m[0].rm_so + len_rp;
399  cur_pos += m[0].rm_so + len_rp;
400  cur_siz += delta_siz;
401  creplace += 1;
402  }
403  free(m);
404  regfree(&r);
405  return (int)cur_siz;
406 };
407 
408 #endif /*REGEX_POSIX_H_*/