Skip to content

Commit 485d202

Browse files
committed
Optimized text search functionality in files
1 parent 383b83f commit 485d202

File tree

6 files changed

+285
-50
lines changed

6 files changed

+285
-50
lines changed

src/data/str.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,42 @@ xarray_t* xstrsplit(const char *pString, const char *pDlmt)
926926
return pArray;
927927
}
928928

929+
xarray_t* xstrsplite(const char *pString, const char *pDlmt)
930+
{
931+
if (!xstrused(pString) || !xstrused(pDlmt)) return NULL;
932+
933+
char sDlmt[XSTR_MID];
934+
size_t nDlmtLen = xstrncpy(sDlmt, sizeof(sDlmt), pDlmt);
935+
if (!nDlmtLen) return NULL;
936+
937+
xarray_t *pArray = XArray_NewPool(XSTDNON, XSTDNON, XFALSE);
938+
if (pArray == NULL) return NULL;
939+
940+
char sToken[XSTR_MAX];
941+
int nNext = 0;
942+
943+
while((nNext = xstrntok(sToken, sizeof(sToken), pString, nNext, sDlmt)) >= 0)
944+
{
945+
size_t nLength = strlen(sToken);
946+
if (!nLength)
947+
{
948+
XArray_AddData(pArray, XSTR_EMPTY, 1);
949+
continue;
950+
}
951+
952+
XArray_AddData(pArray, sToken, nLength+1);
953+
if (!nNext) break;
954+
}
955+
956+
if (!pArray->nUsed)
957+
{
958+
XArray_Destroy(pArray);
959+
return NULL;
960+
}
961+
962+
return pArray;
963+
}
964+
929965
char* xstrtoge(char *pBuffer, size_t nSize, const char *pStr)
930966
{
931967
if (pStr == NULL) return NULL;

src/data/str.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#define XSTR_INIT { XSTR_NUL }
7575

7676
#define XSTR_AVAIL(arr)((int)sizeof(arr)-(int)strlen(arr))
77+
#define XSTR_NAVAIL(arr,n)((int)n-(int)strlen(arr))
7778

7879
#ifdef __cplusplus
7980
extern "C" {
@@ -89,6 +90,8 @@ typedef enum {
8990
/////////////////////////////////////////////////////////////////////////
9091

9192
xarray_t* xstrsplit(const char *pString, const char *pDlmt);
93+
xarray_t* xstrsplite(const char *pString, const char *pDlmt);
94+
9295
char* xstrrep(const char *pOrig, const char *pRep, const char *pWith);
9396
int xstrnrep(char *pDst, size_t nSize, const char *pOrig, const char *pRep, const char *pWith);
9497
char *xstrpdup(xpool_t *pPool, const char *pStr);

src/sys/xfs.c

Lines changed: 123 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -272,23 +272,29 @@ int XFile_GetStats(xfile_t *pFile)
272272
return pFile->nSize ? XSTDOK : XSTDNON;
273273
}
274274

275-
uint8_t* XFile_Load(xfile_t *pFile, size_t *pSize)
275+
uint8_t* XFile_LoadSize(xfile_t *pFile, size_t nMaxSize, size_t *pSize)
276276
{
277277
if (pSize) *pSize = 0;
278278
if (XFile_GetStats(pFile) <= 0 || !S_ISREG(pFile->nMode)) return NULL;
279279

280-
uint8_t *pBuffer = (uint8_t*)malloc(pFile->nSize + 1);
280+
size_t nAllowedToRead = XSTD_MIN(nMaxSize, pFile->nSize);
281+
nAllowedToRead = nAllowedToRead ? nAllowedToRead : pFile->nSize;
282+
283+
uint8_t *pBuffer = (uint8_t*)malloc(nAllowedToRead + 1);
281284
if (pBuffer == NULL) return NULL;
282285

283286
size_t nOffset = 0;
284287
int nBytes = 0;
285288

286289
do
287290
{
288-
size_t nFreeSpace = pFile->nSize - nOffset;
291+
size_t nFreeSpace = nAllowedToRead - nOffset;
289292
size_t nReadSize = pFile->nBlockSize < nFreeSpace ?
290293
pFile->nBlockSize : nFreeSpace;
291294

295+
nReadSize = nReadSize < nMaxSize ? nReadSize : nMaxSize;
296+
if (nReadSize == 0) break;
297+
292298
nBytes = XFile_Read(pFile, &pBuffer[nOffset], nReadSize);
293299
if (nBytes > 0) nOffset += nBytes;
294300

@@ -306,6 +312,12 @@ uint8_t* XFile_Load(xfile_t *pFile, size_t *pSize)
306312
return pBuffer;
307313
}
308314

315+
uint8_t* XFile_Load(xfile_t *pFile, size_t *pSize)
316+
{
317+
// Use XSTDNON as MaxSize to read all file
318+
return XFile_LoadSize(pFile, XSTDNON, pSize);
319+
}
320+
309321
int XFile_Copy(xfile_t *pIn, xfile_t *pOut)
310322
{
311323
XASSERT((XFile_GetStats(pIn) > 0), XSTDERR);
@@ -668,6 +680,18 @@ uint8_t* XPath_Load(const char *pPath, size_t* pSize)
668680
return pData;
669681
}
670682

683+
uint8_t* XPath_LoadSize(const char *pPath, size_t nMaxSize, size_t* pSize)
684+
{
685+
if (pSize) *pSize = 0;
686+
xfile_t file;
687+
688+
if (XFile_Open(&file, pPath, NULL, NULL) < 0) return NULL;
689+
uint8_t *pData = XFile_LoadSize(&file, nMaxSize, pSize);
690+
691+
XFile_Close(&file);
692+
return pData;
693+
}
694+
671695
size_t XPath_LoadBuffer(const char *pPath, xbyte_buffer_t *pBuffer)
672696
{
673697
if (pPath == NULL || pBuffer == NULL) return 0;
@@ -685,6 +709,23 @@ size_t XPath_LoadBuffer(const char *pPath, xbyte_buffer_t *pBuffer)
685709
return nSize;
686710
}
687711

712+
size_t XPath_LoadBufferSize(const char *pPath, xbyte_buffer_t *pBuffer, size_t nMaxSize)
713+
{
714+
if (pPath == NULL || pBuffer == NULL) return 0;
715+
XByteBuffer_Init(pBuffer, XSTDNON, XFALSE);
716+
size_t nSize = 0;
717+
718+
uint8_t* pData = XPath_LoadSize(pPath, nMaxSize, &nSize);
719+
if (pData != NULL)
720+
{
721+
pBuffer->nSize = nSize + 1;
722+
pBuffer->nUsed = nSize;
723+
pBuffer->pData = pData;
724+
}
725+
726+
return nSize;
727+
}
728+
688729
int XPath_Write(const char *pPath, const char *pFlags, const uint8_t *pData, size_t nSize)
689730
{
690731
if (pPath == NULL || pData == NULL || !nSize) return XSTDERR;
@@ -908,9 +949,11 @@ void XFile_InitEntry(xfile_entry_t *pEntry)
908949
pEntry->sPath[0] = XSTR_NUL;
909950
pEntry->sName[0] = XSTR_NUL;
910951
pEntry->sLink[0] = XSTR_NUL;
952+
pEntry->sLine[0] = XSTR_NUL;
911953
pEntry->eType = XF_UNKNOWN;
912954
pEntry->pRealPath = NULL;
913955
pEntry->nLinkCount = 0;
956+
pEntry->nLineNum = 0;
914957
pEntry->nTime = 0;
915958
pEntry->nSize = 0;
916959
pEntry->nGID = 0;
@@ -1081,22 +1124,23 @@ static xbool_t XFile_SearchName(xfile_search_t *pSearch, const char *pFileName)
10811124
return bFound;
10821125
}
10831126

1084-
static xbool_t XFile_CheckCriteria(xfile_search_t *pSearch, const char *pPath, const char *pName, xstat_t *pStat)
1127+
static int XFile_CheckCriteria(xfile_search_t *pSearch, const char *pPath, const char *pName, xstat_t *pStat)
10851128
{
1086-
if (pSearch->nLinkCount >= 0 && pSearch->nLinkCount != pStat->st_nlink) return XFALSE;
1087-
if (pSearch->nFileSize >= 0 && pSearch->nFileSize != pStat->st_size) return XFALSE;
1129+
if (pSearch->nLinkCount >= 0 && pSearch->nLinkCount != pStat->st_nlink) return XSTDNON;
1130+
if (pSearch->nFileSize >= 0 && pSearch->nFileSize != pStat->st_size) return XSTDNON;
1131+
if (pSearch->nMaxSize > 0 && pSearch->nMaxSize < pStat->st_size) return XSTDNON;
10881132

10891133
if (pSearch->nPermissions)
10901134
{
10911135
char buff[XPERM_MAX];
10921136
XPath_ModeToChmod(buff, sizeof(buff), pStat->st_mode);
1093-
if (atoi(buff) != pSearch->nPermissions) return XFALSE;
1137+
if (atoi(buff) != pSearch->nPermissions) return XSTDNON;
10941138
}
10951139

10961140
if (pSearch->nFileTypes)
10971141
{
10981142
xfile_type_t eType = XFile_GetType(pStat->st_mode);
1099-
if (!XFILE_CHECK_FL(pSearch->nFileTypes, eType)) return XFALSE;
1143+
if (!XFILE_CHECK_FL(pSearch->nFileTypes, eType)) return XSTDNON;
11001144
}
11011145

11021146
if (xstrused(pSearch->pFileName))
@@ -1109,30 +1153,69 @@ static xbool_t XFile_CheckCriteria(xfile_search_t *pSearch, const char *pPath, c
11091153
XFile_SearchName(pSearch, pSearchName) :
11101154
!strcmp(pSearch->pFileName, pSearchName);
11111155

1112-
if (!bFound) return XFALSE;
1156+
if (!bFound && !xstrused(pSearch->sText)) return XSTDNON;
11131157
}
11141158

11151159
if (xstrused(pSearch->sText))
11161160
{
11171161
xfile_type_t eType = XFile_GetType(pStat->st_mode);
1118-
if (eType != XF_REGULAR) return XFALSE;
1162+
if (eType != XF_REGULAR) return XSTDNON;
11191163

11201164
char sPath[XPATH_MAX];
11211165
xstrncpyf(sPath, sizeof(sPath), "%s%s", pPath, pName);
11221166

11231167
xbyte_buffer_t buffer;
1124-
XPath_LoadBuffer(sPath, &buffer);
1125-
if (buffer.pData == NULL) return XFALSE;
1168+
XPath_LoadBufferSize(sPath, &buffer, pSearch->nMaxRead);
1169+
if (buffer.pData == NULL) return XSTDNON;
11261170

11271171
char *pBuffer = (char*)buffer.pData;
11281172
if (pSearch->bInsensitive) xstrcase((char*)pBuffer, XSTR_LOWER);
11291173
int nPosit = xstrsrc(pBuffer, pSearch->sText);
11301174

1175+
if (nPosit >= 0 && pSearch->bSearchLines)
1176+
{
1177+
xarray_t *pArr = xstrsplite(pBuffer, "\n");
1178+
if (pArr != NULL)
1179+
{
1180+
size_t i = 0;
1181+
for (i = 0; i < pArr->nUsed; i++)
1182+
{
1183+
char *pLine = (char*)XArray_GetData(pArr, i);
1184+
if (xstrsrc(pLine, pSearch->sText) >= 0)
1185+
{
1186+
xfile_entry_t *pEntry = XFile_NewEntry(pName, pPath, pStat);
1187+
if (pEntry == NULL)
1188+
{
1189+
XFile_ErrorCallback(pSearch, "Failed to alloc entry: %s", pPath);
1190+
XByteBuffer_Clear(&buffer);
1191+
XArray_Destroy(pArr);
1192+
return XSTDERR;
1193+
}
1194+
1195+
while (*pLine && isspace((unsigned char)*pLine)) pLine++;
1196+
xstrncpy(pEntry->sLine, sizeof(pEntry->sLine), pLine);
1197+
pEntry->nLineNum = i + 1;
1198+
1199+
if (XFile_SearchCallback(pSearch, pEntry) < 0)
1200+
{
1201+
XByteBuffer_Clear(&buffer);
1202+
XArray_Destroy(pArr);
1203+
return XSTDERR;
1204+
}
1205+
}
1206+
}
1207+
}
1208+
1209+
XByteBuffer_Clear(&buffer);
1210+
XArray_Destroy(pArr);
1211+
return XSTDNON;
1212+
}
1213+
11311214
XByteBuffer_Clear(&buffer);
1132-
if (nPosit < 0) return XFALSE;
1215+
if (nPosit < 0) return XSTDNON;
11331216
}
11341217

1135-
return XTRUE;
1218+
return XSTDOK;
11361219
}
11371220

11381221
void XFile_SearchClearCb(xarray_data_t *pArrData)
@@ -1145,11 +1228,8 @@ void XFile_SearchClearCb(xarray_data_t *pArrData)
11451228
static xarray_t* XFile_TokenizeName(xfile_search_t *pSrcCtx, const char *pFileName)
11461229
{
11471230
xarray_t *pTokens = NULL;
1148-
1149-
if (xstrsrc(pFileName, ";") >= 0)
1150-
pTokens = xstrsplit(pFileName, ";");
1151-
else if (xstrsrc(pFileName, "*") >= 0)
1152-
return xstrsplit(pFileName, "*");
1231+
if (xstrsrc(pFileName, "*") >= 0) return xstrsplit(pFileName, "*");
1232+
if (xstrsrc(pFileName, ";") >= 0) pTokens = xstrsplit(pFileName, ";");
11531233

11541234
if (pTokens == NULL) return NULL;
11551235
size_t i, nUsed = XArray_Used(pTokens);
@@ -1179,6 +1259,7 @@ static xarray_t* XFile_TokenizeName(xfile_search_t *pSrcCtx, const char *pFileNa
11791259
void XFile_SearchInit(xfile_search_t *pSrcCtx, const char *pFileName)
11801260
{
11811261
pSrcCtx->bInsensitive = XFALSE;
1262+
pSrcCtx->bSearchLines = XFALSE;
11821263
pSrcCtx->bRecursive = XFALSE;
11831264
pSrcCtx->bMulty = XFALSE;
11841265
pSrcCtx->callback = NULL;
@@ -1194,6 +1275,8 @@ void XFile_SearchInit(xfile_search_t *pSrcCtx, const char *pFileName)
11941275
pSrcCtx->nFileTypes = 0;
11951276
pSrcCtx->nLinkCount = -1;
11961277
pSrcCtx->nFileSize = -1;
1278+
pSrcCtx->nMaxRead = 0;
1279+
pSrcCtx->nMaxSize = 0;
11971280

11981281
XArray_InitPool(&pSrcCtx->fileArray, XSTDNON, XSTDNON, XFALSE);
11991282
pSrcCtx->fileArray.clearCb = XFile_ArrayClearCb;
@@ -1222,27 +1305,32 @@ xfile_entry_t* XFile_GetEntry(xfile_search_t *pSearch, int nIndex)
12221305

12231306
int XFile_Search(xfile_search_t *pSearch, const char *pDirectory)
12241307
{
1225-
if (pDirectory == NULL || XSYNC_ATOMIC_GET(pSearch->pInterrupted)) return XSTDERR;
1226-
size_t nDirLen = strlen(pDirectory);
1308+
if (XSYNC_ATOMIC_GET(pSearch->pInterrupted) ||
1309+
pDirectory == NULL) return XSTDERR;
12271310

12281311
xdir_t dirHandle;
1229-
if (XDir_Open(&dirHandle, pDirectory) < 0)
1312+
char sDirPath[XPATH_MAX];
1313+
1314+
size_t nDirLen = strlen(pDirectory);
1315+
while (nDirLen && pDirectory[nDirLen--] == XSTR_SPACE_CHAR);
1316+
const char *pSlash = pDirectory[nDirLen] == '/' ? XSTR_EMPTY : "/";
1317+
xstrncpyf(sDirPath, sizeof(sDirPath), "%s%s", pDirectory, pSlash);
1318+
1319+
if (XDir_Open(&dirHandle, sDirPath) < 0)
12301320
{
1231-
XFile_ErrorCallback(pSearch, "Failed to open directory: %s", pDirectory);
1321+
XFile_ErrorCallback(pSearch, "Failed to open directory: %s", sDirPath);
12321322
return XSYNC_ATOMIC_GET(pSearch->pInterrupted) ? XSTDERR : XSTDOK;
12331323
}
12341324

1325+
if (xstrused(pSearch->sText) && pSearch->bInsensitive)
1326+
xstrcase(pSearch->sText, XSTR_LOWER);
1327+
12351328
while (XDir_Read(&dirHandle, NULL, 0) > 0 && !XSYNC_ATOMIC_GET(pSearch->pInterrupted))
12361329
{
12371330
char sFullPath[XPATH_MAX];
1238-
char sDirPath[XPATH_MAX];
12391331
xstat_t statbuf;
12401332

1241-
/* Don't add slash twice if directory already contains slash character at the end */
1242-
const char *pSlash = (pDirectory[nDirLen - 1] != '/') ? "/" : XSTR_EMPTY;
12431333
const char *pEntryName = dirHandle.pCurrEntry;
1244-
1245-
xstrncpyf(sDirPath, sizeof(sDirPath), "%s%s", pDirectory, pSlash);
12461334
xstrncpyf(sFullPath, sizeof(sFullPath), "%s%s", sDirPath, pEntryName);
12471335

12481336
if (xstat(sFullPath, &statbuf) < 0)
@@ -1252,7 +1340,8 @@ int XFile_Search(xfile_search_t *pSearch, const char *pDirectory)
12521340
continue;
12531341
}
12541342

1255-
if (XFile_CheckCriteria(pSearch, sDirPath, pEntryName, &statbuf))
1343+
int nMatch = XFile_CheckCriteria(pSearch, sDirPath, pEntryName, &statbuf);
1344+
if (nMatch > 0)
12561345
{
12571346
xfile_entry_t *pEntry = XFile_NewEntry(pEntryName, sDirPath, &statbuf);
12581347
if (pEntry == NULL)
@@ -1268,6 +1357,11 @@ int XFile_Search(xfile_search_t *pSearch, const char *pDirectory)
12681357
return XSTDERR;
12691358
}
12701359
}
1360+
else if (nMatch < 0)
1361+
{
1362+
XDir_Close(&dirHandle);
1363+
return XSTDERR;
1364+
}
12711365

12721366
/* Recursive search */
12731367
if (pSearch->bRecursive &&

0 commit comments

Comments
 (0)