Skip to content

Commit 48ce01a

Browse files
lauxinwNanlinXie
authored andcommitted
tools: acrn-crashlog: new api in strutils
This patch provides an new api to split string by extended regexp(ere). Tracked-On: #1254 Signed-off-by: Liu, Xinwu <xinwu.liu@intel.com> Reviewed-by: Yonghua Huang <yonghua.huang@intel.com> Acked-by: Chen Gang <gang.c.chen@intel.com>
1 parent 6a9a46a commit 48ce01a

File tree

2 files changed

+176
-1
lines changed

2 files changed

+176
-1
lines changed

tools/acrn-crashlog/common/include/strutils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ char *strrstr(const char *s, const char *str);
1313
char *next_line(char *buf);
1414
char *strtrim(char *str);
1515
int strcnt(char *str, char c);
16-
16+
int str_split_ere(const char *str, size_t slen,
17+
const char *fmt, size_t flen, ...);
1718
#endif

tools/acrn-crashlog/common/strutils.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55

66
#include <string.h>
77
#include <errno.h>
8+
#include <regex.h>
9+
#include <stdarg.h>
10+
#include <stdlib.h>
11+
#include "log_sys.h"
12+
#include "fsutils.h"
813

914
/**
1015
* Get the length of line.
@@ -115,3 +120,172 @@ int strcnt(char *str, char c)
115120

116121
return cnt;
117122
}
123+
124+
static int reg_match(const char *str, const char *pattern,
125+
char *matched_sub, size_t matched_space,
126+
size_t *end_off)
127+
{
128+
int err;
129+
regex_t reg;
130+
char err_msg[128];
131+
regmatch_t pm[1];
132+
size_t matched_len;
133+
134+
LOGD("reg: %s\n", pattern);
135+
err = regcomp(&reg, pattern, REG_EXTENDED);
136+
if (err) {
137+
regerror(err, &reg, err_msg, sizeof(err_msg));
138+
LOGE("failed to regcomp - %s\n", err_msg);
139+
return -1;
140+
}
141+
142+
err = regexec(&reg, str, sizeof(pm)/sizeof(regmatch_t), pm, 0);
143+
regfree(&reg);
144+
if (err == REG_NOMATCH) {
145+
LOGE("failed to match with reg (%s) str (%s)\n", pattern, str);
146+
return -1;
147+
}
148+
if (pm[0].rm_so == -1)
149+
return -1;
150+
151+
*end_off = pm[0].rm_eo;
152+
if (matched_space == 0 || matched_sub == NULL)
153+
/* get offset only */
154+
return 0;
155+
156+
matched_len = pm[0].rm_eo - pm[0].rm_so;
157+
*(char *)mempcpy(matched_sub, str + pm[0].rm_so,
158+
MIN(matched_len, matched_space - 1)) = '\0';
159+
return 0;
160+
}
161+
162+
static char *exp_end(const char *fmt, size_t flen, const char *exp_s)
163+
{
164+
/* supports %[regex..] and %*[regex..] */
165+
int flag = 0;
166+
const char *p;
167+
168+
if (exp_s < fmt || exp_s >= fmt + flen)
169+
return NULL;
170+
171+
for (p = exp_s; p < fmt + flen; p++) {
172+
if (*p == '[')
173+
flag++;
174+
175+
if (*p == ']') {
176+
flag--;
177+
if (flag == 0)
178+
return (char *)(p + 1);
179+
else if (flag < 0)
180+
return NULL;
181+
}
182+
}
183+
return NULL;
184+
}
185+
186+
static int exp2reg(const char *s, const char *e, int *ignore_flag, char **reg)
187+
{
188+
const char *oreg_s;
189+
int flag_tmp;
190+
char *buf;
191+
192+
if (memcmp(s, "%*[", 3) == 0) {
193+
flag_tmp = 1;
194+
oreg_s = s + 3;
195+
} else if (memcmp(s, "%[", 2) == 0) {
196+
flag_tmp = 0;
197+
oreg_s = s + 2;
198+
} else {
199+
LOGE("invalid exp - exp must start with \"%%[\" or \"%%*[\"\n");
200+
return -1;
201+
}
202+
203+
if (oreg_s >= e) {
204+
LOGE("invalid exp - exp empty\n");
205+
return -1;
206+
}
207+
208+
buf = malloc(e - oreg_s + 1);
209+
if (!buf) {
210+
LOGE("out-of-mem\n");
211+
return -1;
212+
}
213+
214+
buf[0] = '^';
215+
memcpy(&buf[1], oreg_s, e - oreg_s - 1);
216+
buf[e - oreg_s] = '\0';
217+
218+
*reg = buf;
219+
*ignore_flag = flag_tmp;
220+
return 0;
221+
}
222+
223+
int str_split_ere(const char *str, size_t slen,
224+
const char *fmt, size_t flen, ...)
225+
{
226+
va_list v;
227+
char *_str, *_fmt;
228+
const char *exp_s, *exp_e;
229+
int ignore_flag;
230+
char *reg;
231+
size_t str_off = 0;
232+
size_t off;
233+
char *sreq;
234+
size_t sreqsize;
235+
int ret = 0;
236+
237+
if (!str || !slen || !fmt || !flen)
238+
return ret;
239+
240+
_str = strndup(str, slen);
241+
if (!_str)
242+
return ret;
243+
_fmt = strndup(fmt, flen);
244+
if (!_fmt) {
245+
free(_str);
246+
return ret;
247+
}
248+
249+
va_start(v, flen);
250+
/* supports %[regex..] and %*[regex..] */
251+
exp_s = fmt;
252+
while (str_off < flen && *exp_s) {
253+
exp_e = exp_end(fmt, flen, exp_s);
254+
if (!exp_e) {
255+
LOGE("invalid exp - failed to find the end of exp\n");
256+
goto out;
257+
}
258+
259+
if (exp2reg(exp_s, exp_e, &ignore_flag, &reg) == -1) {
260+
LOGE("failed to translate exp to reg\n");
261+
goto out;
262+
}
263+
264+
if (ignore_flag == 1) {
265+
sreq = NULL;
266+
sreqsize = 0;
267+
} else {
268+
sreq = va_arg(v, char *);
269+
sreqsize = va_arg(v, size_t);
270+
}
271+
272+
if (reg_match(str + str_off, reg, sreq, sreqsize, &off) == -1) {
273+
LOGE("failed to match reg\n");
274+
free(reg);
275+
goto out;
276+
} else {
277+
if (ignore_flag == 0)
278+
ret++;
279+
}
280+
281+
exp_s = exp_e;
282+
str_off += off;
283+
free(reg);
284+
}
285+
286+
out:
287+
va_end(v);
288+
free(_str);
289+
free(_fmt);
290+
return ret;
291+
}

0 commit comments

Comments
 (0)