Skip to content

Commit 9350756

Browse files
committed
Optimized multy pattern regex search and added test for it
1 parent 8cc0326 commit 9350756

File tree

6 files changed

+120
-86
lines changed

6 files changed

+120
-86
lines changed

.github/workflows/tests.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ jobs:
3131
- name: Run Valgrind Check With tools/xsrc
3232
run: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 xsrc -rvd ./
3333

34+
- name: Run Valgrind Check With tools/xsrc (multy)
35+
run: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 xsrc -rvd ./ -f "*CM*k*.t*;Ma??fil*"
36+
3437
- name: Run Valgrind Check With tools/xhttp
3538
run: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 xhttp -dl github.com -v
3639

examples/strings.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ int main()
242242

243243
// Test pattern matching
244244
char pattern[] = "pattern*";
245-
size_t plen = strlen((char *)pattern);
245+
char pattern2[] = "should*match*this*pattern*";
246246

247247
char matchStr1[] = "pattern";
248248
size_t slen1 = strlen((char *)matchStr1);
@@ -253,20 +253,43 @@ int main()
253253
char matchStr3[] = "not_match.pattern";
254254
size_t slen3 = strlen((char *)matchStr3);
255255

256-
xbool_t match1 = xstrmatch(matchStr1, slen1, pattern, plen);
257-
xbool_t match2 = xstrmatch(matchStr2, slen2, pattern, plen);
258-
xbool_t match3 = xstrmatch(matchStr3, slen3, pattern, plen);
256+
char matchStr4[] = "should match this cool pattern!";
257+
size_t slen4 = strlen((char *)matchStr4);
259258

260-
if (!match1 || !match2 || match3)
259+
xbool_t match1 = xstrmatch(matchStr1, slen1, pattern);
260+
xbool_t match2 = xstrmatch(matchStr2, slen2, pattern);
261+
xbool_t match3 = xstrmatch(matchStr3, slen3, pattern);
262+
xbool_t match4 = xstrmatch(matchStr4, slen4, pattern2);
263+
264+
if (!match1 || !match2 || match3 || !match4)
261265
{
262-
xloge("Pattern matching failed with xstrmatch: %d/%d/%d", match1, match2, match3);
266+
xloge("Pattern matching failed with xstrmatch: %d/%d/%d/%d", match1, match2, match3, match4);
263267
return XSTDERR;
264268
}
265269

266270
printf("Matching \"%s\" with pattern \"%s\": %s\n", matchStr1, pattern, match1 ? "MATCH" : "NO MATCH");
267271
printf("Matching \"%s\" with pattern \"%s\": %s\n", matchStr2, pattern, match2 ? "MATCH" : "NO MATCH");
268272
printf("Matching \"%s\" with pattern \"%s\": %s\n", matchStr3, pattern, match3 ? "MATCH" : "NO MATCH");
273+
printf("Matching \"%s\" with pattern \"%s\": %s\n", matchStr4, pattern2, match4 ? "MATCH" : "NO MATCH");
274+
275+
// Test multy pattern matching
276+
char multiPattern[] = "pa??ern;te*t;string;rand?m*str*ing*her?!";
277+
char multiMatchStr1[] = "pattern";
278+
char multiMatchStr2[] = "random string here!";
279+
char multiMatchStr3[] = "random bad str here";
280+
281+
xbool_t multiMatch1 = xstrmatchm(multiMatchStr1, strlen(multiMatchStr1), multiPattern, ";");
282+
xbool_t multiMatch2 = xstrmatchm(multiMatchStr2, strlen(multiMatchStr2), multiPattern, ";");
283+
xbool_t multiMatch3 = xstrmatchm(multiMatchStr3, strlen(multiMatchStr3), multiPattern, ";");
284+
if (!multiMatch1 || !multiMatch2 || multiMatch3)
285+
{
286+
xloge("Multy pattern matching failed with xstrmatchm: %d/%d/%d", multiMatch1, multiMatch2, multiMatch3);
287+
return XSTDERR;
288+
}
269289

290+
printf("Matching \"%s\" with pattern \"%s\": %s\n", multiMatchStr1, multiPattern, multiMatch1 ? "MATCH" : "NO MATCH");
291+
printf("Matching \"%s\" with pattern \"%s\": %s\n", multiMatchStr2, multiPattern, multiMatch2 ? "MATCH" : "NO MATCH");
292+
printf("Matching \"%s\" with pattern \"%s\": %s\n", multiMatchStr3, multiPattern, multiMatch3 ? "MATCH" : "NO MATCH");
270293

271294
return 0;
272295
}

src/data/str.c

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,11 @@ xbool_t xstrncmpn(const char *pStr, size_t nStrLen, const char *pCmp, size_t nCm
179179

180180
xbool_t xstrcmp(const char *pStr, const char *pCmp)
181181
{
182-
XASSERT_RET((xstrused(pStr) && xstrused(pCmp)), XFALSE);
182+
XASSERT_RET(((pStr != NULL) && (pCmp != NULL)), XFALSE);
183183
return strcmp(pStr, pCmp) ? XFALSE : XTRUE;
184184
}
185185

186-
xbool_t xstrmatch(const char *pStr, size_t nLength, const char *pPattern, size_t nPatternLength)
186+
xbool_t xstrnmatch(const char *pStr, size_t nLength, const char *pPattern, size_t nPatternLength)
187187
{
188188
XASSERT_RET(((pStr != NULL) && (pPattern != NULL)), XFALSE);
189189
if (!nPatternLength) return !nLength ? XTRUE : XFALSE;
@@ -203,7 +203,7 @@ xbool_t xstrmatch(const char *pStr, size_t nLength, const char *pPattern, size_t
203203

204204
for (i = 0; i <= nLength; i++)
205205
{
206-
if (xstrmatch(pStr + i, nLength - i,
206+
if (xstrnmatch(pStr + i, nLength - i,
207207
pPattern + 1, nPatternLength - 1))
208208
return XTRUE;
209209
}
@@ -215,16 +215,82 @@ xbool_t xstrmatch(const char *pStr, size_t nLength, const char *pPattern, size_t
215215

216216
if (pPattern[0] == '?')
217217
{
218-
return xstrmatch(pStr + 1, nLength - 1,
218+
return xstrnmatch(pStr + 1, nLength - 1,
219219
pPattern + 1, nPatternLength - 1);
220220
}
221221

222222
if (pPattern[0] != pStr[0]) return XFALSE;
223223

224-
return xstrmatch(pStr + 1, nLength - 1,
224+
return xstrnmatch(pStr + 1, nLength - 1,
225225
pPattern + 1, nPatternLength - 1);
226226
}
227227

228+
xbool_t xstrmatch(const char *pStr, size_t nLength, const char *pPattern)
229+
{
230+
XASSERT_RET(((pStr != NULL) && (pPattern != NULL)), XFALSE);
231+
if (!nLength) return !xstrused(pPattern) ? XTRUE : XFALSE;
232+
size_t nPatternLength = strnlen(pPattern, nLength);
233+
return xstrnmatch(pStr, nLength, pPattern, nPatternLength);
234+
}
235+
236+
xbool_t xstrmatchm(const char *pStr, size_t nLength, const char *pPattern, const char *pDelimiter)
237+
{
238+
XASSERT_RET(((pStr != NULL) && (pPattern != NULL)), XFALSE);
239+
if (!nLength) return !xstrused(pPattern) ? XTRUE : XFALSE;
240+
241+
const char *pDlmt = pDelimiter == NULL ? ";" : pDelimiter;
242+
if (!xstrsrc(pPattern, pDlmt)) return xstrmatch(pStr, nLength, pPattern);
243+
244+
xarray_t *pTokens = xstrsplitd(pPattern, pDlmt);
245+
size_t i, nUsed = XArray_Used(pTokens);
246+
xbool_t bFound = XFALSE;
247+
248+
for (i = 0; i < nUsed; i++)
249+
{
250+
xarray_data_t *pArrData = XArray_Get(pTokens, i);
251+
if (pArrData == NULL || pArrData->pData == NULL || !pArrData->nSize) continue;
252+
253+
const char *pToken = (const char *)pArrData->pData;
254+
size_t nTokenLength = pArrData->nSize - 1;
255+
256+
bFound = xstrnmatch(pStr, nLength, pToken, nTokenLength);
257+
if (bFound) break;
258+
}
259+
260+
XArray_Destroy(pTokens);
261+
return bFound;
262+
}
263+
264+
xbool_t xstrregex(const char *pStr, size_t nLength, const char *pPattern)
265+
{
266+
XASSERT_RET(((pStr != NULL) && (pPattern != NULL)), XFALSE);
267+
xarray_t *pTokens = xstrsplitd(pPattern, "*");
268+
size_t nUsed = XArray_Used(pTokens);
269+
270+
if (!nUsed) return xstrcmp(pStr, pPattern);
271+
size_t i, nOffset = 0;
272+
273+
for (i = 0; i < nUsed; i++)
274+
{
275+
const char *pTok = (const char*)XArray_GetData(pTokens, i);
276+
if (xstrused(pTok) && !xstrcmp(pTok, "*"))
277+
{
278+
if (!i && !xstrncmp(pTok, pStr, strlen(pTok))) return XFALSE;
279+
int nPosit = xstrnsrc(pStr, nLength, pTok, nOffset);
280+
if (nPosit < 0) return XFALSE;
281+
282+
nOffset += nPosit;
283+
if (nOffset >= nLength) return XFALSE;
284+
285+
const char *pOffset = (const char*)&pStr[nOffset];
286+
if (i && i + 1 == nUsed && !xstrcmp(pTok, pOffset)) return XFALSE;
287+
nOffset += strlen(pTok);
288+
}
289+
}
290+
291+
return XTRUE;
292+
}
293+
228294
size_t xstrnfill(char *pDst, size_t nSize, size_t nLength, char cFill)
229295
{
230296
if (pDst == NULL || !nSize) return XSTDNON;

src/data/str.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,11 @@ size_t xstrarglen(const char *pFmt, va_list args);
112112
size_t xstrxcpyf(char **pDst, const char *pFmt, ...);
113113
char* xstrxcpy(const char *pFmt, ...);
114114

115-
xbool_t xstrmatch(const char *pStr, size_t nLength, const char *pPattern, size_t nPatternLength);
115+
xbool_t xstrmatchm(const char *pStr, size_t nLength, const char *pPattern, const char *pDelimiter);
116+
xbool_t xstrnmatch(const char *pStr, size_t nLength, const char *pPattern, size_t nPatternLength);
117+
xbool_t xstrmatch(const char *pStr, size_t nLength, const char *pPattern);
118+
xbool_t xstrregex(const char *pStr, size_t nLength, const char *pPattern);
119+
116120
xbool_t xstrncmpn(const char *pStr, size_t nStrLen, const char *pCmp, size_t nCmpLen);
117121
xbool_t xstrncmp(const char *pStr, const char *pCmp, size_t nCmpLen);
118122
xbool_t xstrcmp(const char *pStr, const char *pCmp);

src/sys/search.c

Lines changed: 11 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -151,33 +151,6 @@ static int XSearch_Callback(xsearch_t *pSearch, xsearch_entry_t *pEntry)
151151
return XSTDNON;
152152
}
153153

154-
static xbool_t XSearch_Tokens(xarray_t *pTokens, const char *pName, size_t nLength)
155-
{
156-
size_t nUsed = XArray_Used(pTokens);
157-
if (!nUsed) return XFALSE;
158-
size_t i, nOffset = 0;
159-
160-
for (i = 0; i < nUsed; i++)
161-
{
162-
const char *pTok = (const char*)XArray_GetData(pTokens, i);
163-
if (xstrused(pTok) && !xstrcmp(pTok, "*"))
164-
{
165-
if (!i && !xstrncmp(pTok, pName, strlen(pTok))) return XFALSE;
166-
int nPosit = xstrnsrc(pName, nLength, pTok, nOffset);
167-
if (nPosit < 0) return XFALSE;
168-
169-
nOffset += nPosit;
170-
if (nOffset >= nLength) return XFALSE;
171-
172-
const char *pOffset = (const char*)&pName[nOffset];
173-
if (i && i + 1 == nUsed && !xstrcmp(pTok, pOffset)) return XFALSE;
174-
nOffset += strlen(pTok);
175-
}
176-
}
177-
178-
return XTRUE;
179-
}
180-
181154
static xbool_t XSearch_Multy(xarray_t *pTokens, const char *pName, size_t nLength)
182155
{
183156
size_t i, nCount = XArray_Used(pTokens);
@@ -186,12 +159,12 @@ static xbool_t XSearch_Multy(xarray_t *pTokens, const char *pName, size_t nLengt
186159
for (i = 0; i < nCount; i++)
187160
{
188161
xarray_data_t *pArrData = XArray_Get(pTokens, i);
189-
if (pArrData == NULL || pArrData->pData == NULL) continue;
162+
if (pArrData == NULL || pArrData->pData == NULL || !pArrData->nSize) continue;
190163

191-
bFound = pArrData->nKey != XSTDOK ?
192-
xstrncmp((const char *)pArrData->pData, pName, nLength) :
193-
XSearch_Tokens((xarray_t*)pArrData->pData, pName, nLength);
164+
const char *pToken = (const char *)pArrData->pData;
165+
size_t nTokenLength = pArrData->nSize - 1;
194166

167+
bFound = xstrnmatch(pName, nLength, pToken, nTokenLength);
195168
if (bFound) break;
196169
}
197170

@@ -201,11 +174,9 @@ static xbool_t XSearch_Multy(xarray_t *pTokens, const char *pName, size_t nLengt
201174
static xbool_t XSearch_Name(xsearch_t *pSearch, const char *pFileName)
202175
{
203176
size_t nLength = strlen(pFileName);
204-
xbool_t bFound = pSearch->bMulty ?
205-
XSearch_Multy(&pSearch->nameTokens, pFileName, nLength) :
206-
XSearch_Tokens(&pSearch->nameTokens, pFileName, nLength);
207-
208-
return bFound;
177+
xarray_t *pNames = &pSearch->nameTokens;
178+
if (!pNames->nUsed) return xstrmatch(pFileName, nLength, pSearch->sName);
179+
return XSearch_Multy(&pSearch->nameTokens, pFileName, nLength);
209180
}
210181

211182
static XSTATUS XSearch_Lines(xsearch_t *pSearch, xsearch_context_t *pCtx)
@@ -401,10 +372,7 @@ static XSTATUS XSearch_CheckCriteria(xsearch_t *pSearch, const char *pPath, cons
401372
if (pSearch->bInsensitive) xstrncase(sName, sizeof(sName), XSTR_LOWER, pName);
402373
const char *pSearchName = pSearch->bInsensitive ? (const char *)sName : pName;
403374

404-
xbool_t bFound = pSearch->nameTokens.nUsed ?
405-
XSearch_Name(pSearch, pSearchName) :
406-
xstrcmp(pSearch->sName, pSearchName);
407-
375+
xbool_t bFound = XSearch_Name(pSearch, pSearchName);
408376
if (!bFound) return XSTDNON;
409377
}
410378

@@ -427,37 +395,6 @@ void XSearch_ClearCb(xarray_data_t *pArrData)
427395
else XArray_Destroy((xarray_t*)pArrData->pData);
428396
}
429397

430-
static size_t XSearch_TokenizeName(xsearch_t *pSrcCtx, const char *pFileName)
431-
{
432-
xarray_t *pTokens = &pSrcCtx->nameTokens;
433-
if (xstrsrc(pFileName, ";") >= 0) xstrsplita(pFileName, ";", pTokens, XFALSE, XFALSE);
434-
else if (xstrsrc(pFileName, "*") >= 0) return xstrsplita(pFileName, "*", pTokens, XTRUE, XFALSE);
435-
436-
if (!pTokens->nUsed) return XSTDNON;
437-
pSrcCtx->bMulty = XTRUE;
438-
size_t i;
439-
440-
for (i = 0; i < pTokens->nUsed; i++)
441-
{
442-
char *pToken = XArray_GetData(pTokens, i);
443-
if (xstrsrc(pToken, "*") >= 0)
444-
{
445-
xarray_t *pSubTokens = xstrsplitd(pToken, "*");
446-
if (pSubTokens != NULL)
447-
{
448-
xarray_data_t *pArrData = XArray_Get(pTokens, i);
449-
pArrData->pData = pSubTokens;
450-
pArrData->nKey = XSTDOK;
451-
452-
pTokens->clearCb = XSearch_ClearCb;
453-
xfree(pTokens->pPool, pToken);
454-
}
455-
}
456-
}
457-
458-
return pTokens->nUsed;
459-
}
460-
461398
void XSearch_Init(xsearch_t *pSrcCtx, const char *pFileName)
462399
{
463400
pSrcCtx->pInterrupted = &pSrcCtx->nInterrupted;
@@ -466,7 +403,6 @@ void XSearch_Init(xsearch_t *pSrcCtx, const char *pFileName)
466403
pSrcCtx->bMatchOnly = XFALSE;
467404
pSrcCtx->bRecursive = XFALSE;
468405
pSrcCtx->bReadStdin = XFALSE;
469-
pSrcCtx->bMulty = XFALSE;
470406
pSrcCtx->callback = NULL;
471407
pSrcCtx->pUserCtx = NULL;
472408

@@ -479,7 +415,9 @@ void XSearch_Init(xsearch_t *pSrcCtx, const char *pFileName)
479415
pSrcCtx->sName[0] = XSTR_NUL;
480416
pSrcCtx->sText[0] = XSTR_NUL;
481417

482-
XSearch_TokenizeName(pSrcCtx, pFileName);
418+
if (xstrsrc(pFileName, ";") >= 0) // Tokenize the file name for multy search
419+
xstrsplita(pFileName, ";", &pSrcCtx->nameTokens, XFALSE, XFALSE);
420+
483421
xstrncpy(pSrcCtx->sName, sizeof(pSrcCtx->sName), pFileName);
484422

485423
pSrcCtx->nBufferSize = 0;

src/xver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
#define XUTILS_VERSION_MAX 2
1414
#define XUTILS_VERSION_MIN 6
15-
#define XUTILS_BUILD_NUMBER 42
15+
#define XUTILS_BUILD_NUMBER 43
1616

1717
#ifdef __cplusplus
1818
extern "C" {

0 commit comments

Comments
 (0)