Coverage Report

Created: 2025-07-14 06:48

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