812 lines
13 KiB
C++
812 lines
13 KiB
C++
|
|
#include "stringex.h"
|
|
|
|
#include "Common.h" // for debug
|
|
#include "Logger.h" // for debug
|
|
|
|
#ifdef _WIN32
|
|
|
|
#else
|
|
|
|
//#ifndef __CYGWIN__
|
|
int stricmp(const char * first, const char * last)
|
|
{
|
|
int f, l;
|
|
|
|
do
|
|
{
|
|
f = tolower(*first);
|
|
l = tolower(*last);
|
|
first++;
|
|
last++;
|
|
} while (f && l && f == l);
|
|
|
|
//return(f - l);
|
|
return f == l ? 0 : f > l ? 1 : -1;
|
|
}
|
|
|
|
int strnicmp(const char * first, const char * last, unsigned int count)
|
|
{
|
|
int f, l;
|
|
|
|
if (count)
|
|
{
|
|
do
|
|
{
|
|
f = tolower(*first);
|
|
l = tolower(*last);
|
|
first++;
|
|
last++;
|
|
} while (--count && f && l && f == l);
|
|
|
|
//return(f - l);
|
|
return f == l ? 0 : f > l ? 1 : -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char * strlwr(char * str)
|
|
{
|
|
char * p = str;
|
|
|
|
do
|
|
{
|
|
*p = tolower(*p);
|
|
p++;
|
|
} while (*p);
|
|
|
|
return(str);
|
|
}
|
|
|
|
char * strupr(char * str)
|
|
{
|
|
char * p = str;
|
|
|
|
do
|
|
{
|
|
*p = toupper(*p);
|
|
p++;
|
|
} while (*p);
|
|
|
|
return(str);
|
|
}
|
|
//#endif // __CYGWIN__
|
|
|
|
#endif
|
|
|
|
char * gets_hus(char * s, int n)
|
|
{
|
|
char * ch = s;
|
|
int k;
|
|
|
|
while ((k = getchar ()) != '\n')
|
|
{
|
|
if (k == EOF)
|
|
{
|
|
if (ch == s || !feof(stdin))
|
|
return NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
*ch++ = k;
|
|
if (--n <= 1)
|
|
break;
|
|
}
|
|
|
|
*ch = '\0';
|
|
|
|
return s;
|
|
}
|
|
|
|
char * stristr(char * pszStr, char * pszSearch)
|
|
{
|
|
if (pszStr == NULL)
|
|
{
|
|
//HLOG(15, "[TRACE], stristr string is NULL\n");
|
|
return NULL;
|
|
}
|
|
|
|
char *cp = pszStr;
|
|
char *s1, *s2;
|
|
int f, l;
|
|
|
|
if (!*pszSearch)
|
|
return pszStr;
|
|
|
|
while (*cp)
|
|
{
|
|
s1 = cp;
|
|
s2 = (char *)pszSearch;
|
|
|
|
f = tolower(*s1);
|
|
l = tolower(*s2);
|
|
|
|
while (f && l && !(f-l))
|
|
{
|
|
s1++, s2++;
|
|
f = tolower(*s1);
|
|
l = tolower(*s2);
|
|
}
|
|
|
|
if (!*s2)
|
|
return cp;
|
|
|
|
cp++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
char * StrIKeyword(char * string, char * strSearch)
|
|
{
|
|
char *cp = string;
|
|
char *s1, *s2;
|
|
int f, l;
|
|
|
|
if (!*strSearch)
|
|
return string;
|
|
|
|
while (*cp)
|
|
{
|
|
s1 = cp;
|
|
s2 = (char *)strSearch;
|
|
|
|
f = tolower(*s1);
|
|
l = tolower(*s2);
|
|
|
|
while (f && l && !(f-l))
|
|
{
|
|
s1++, s2++;
|
|
f = tolower(*s1);
|
|
l = tolower(*s2);
|
|
}
|
|
|
|
if (*s1 < 0)
|
|
{
|
|
cp++;
|
|
continue;
|
|
}
|
|
|
|
|
|
//if (!*s2) // stristr
|
|
if (!*s2 && !isalnum(*s1) && *s1 != '.') // for com, com.cn
|
|
return cp;
|
|
|
|
cp++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const char * StrNStr(const char * string, const char * strSearch, int nCount)
|
|
{
|
|
char *cp = (char *)string;
|
|
char *s1, *s2;
|
|
int f, l, nRemain = nCount, nr2 = nCount;
|
|
|
|
if (nCount == 0)
|
|
return NULL;
|
|
|
|
if (!*strSearch)
|
|
return((char *)string);
|
|
|
|
while (*cp)
|
|
{
|
|
s1 = cp;
|
|
s2 = (char *)strSearch;
|
|
|
|
f = *s1;
|
|
l = *s2;
|
|
|
|
if (nCount > 0)
|
|
nr2 = nRemain;
|
|
|
|
while (f && l && !(f-l))
|
|
{
|
|
s1++, s2++;
|
|
f = *s1;
|
|
l = *s2;
|
|
|
|
if (nCount > 0 && --nr2 < 0)
|
|
return NULL;
|
|
}
|
|
|
|
if (!*s2)
|
|
return cp;
|
|
|
|
cp++;
|
|
if (nCount > 0 && --nRemain <= 0)
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const char * StrNIStr(const char * string, const char * strSearch, int nCount)
|
|
{
|
|
char *cp = (char *)string;
|
|
char *s1, *s2;
|
|
int f, l, nRemain = nCount, nr2 = nCount;
|
|
|
|
if (nCount == 0)
|
|
return NULL;
|
|
|
|
if (!*strSearch)
|
|
return((char *)string);
|
|
|
|
while (*cp)
|
|
{
|
|
s1 = cp;
|
|
s2 = (char *)strSearch;
|
|
|
|
f = tolower(*s1);
|
|
l = tolower(*s2);
|
|
|
|
if (nCount > 0)
|
|
nr2 = nRemain;
|
|
|
|
while (f && l && !(f-l))
|
|
{
|
|
s1++, s2++;
|
|
f = tolower(*s1);
|
|
l = tolower(*s2);
|
|
|
|
if (nCount > 0 && --nr2 < 0)
|
|
return NULL;
|
|
}
|
|
|
|
if (!*s2)
|
|
return cp;
|
|
|
|
cp++;
|
|
if (nCount > 0 && --nRemain <= 0)
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const char * StrRChr(const char * string, const char * strStart, char ch)
|
|
{
|
|
const char * s = strStart;
|
|
|
|
if (strStart == NULL || string > s)
|
|
return NULL;
|
|
|
|
while (s != string)
|
|
{
|
|
if (*s == ch)
|
|
return s;
|
|
|
|
s--;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#if 0
|
|
const char * StrNIKeyword(const char * string, const char * strSearch, int nCount)
|
|
{
|
|
char *cp = (char *)string;
|
|
char *s1, *s2;
|
|
int f, l, nRemain = nCount, nr2 = nCount;
|
|
|
|
if (nCount == 0)
|
|
return NULL;
|
|
|
|
if (!*strSearch)
|
|
return((char *)string);
|
|
|
|
while (*cp)
|
|
{
|
|
s1 = cp;
|
|
s2 = (char *)strSearch;
|
|
|
|
f = tolower(*s1);
|
|
l = tolower(*s2);
|
|
|
|
if (nCount > 0)
|
|
nr2 = nRemain;
|
|
|
|
while (f && l && !(f-l))
|
|
{
|
|
s1++, s2++;
|
|
f = tolower(*s1);
|
|
l = tolower(*s2);
|
|
|
|
if (nCount > 0 && --nr2 < 0)
|
|
return NULL;
|
|
}
|
|
|
|
//if (!*s2) // StrNIStr
|
|
if (!*s2 && !isalnum(*s1) && *s1 != '.')
|
|
return cp;
|
|
|
|
cp++;
|
|
if (nCount > 0 && --nRemain <= 0)
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
const char * StrStrUntilChr(const char * string, const char * strSearch, char chUntil)
|
|
{
|
|
char *cp = (char *)string;
|
|
char *s1, *s2;
|
|
|
|
if (!*strSearch)
|
|
return ((char *)string);
|
|
|
|
while (*cp)
|
|
{
|
|
s1 = cp;
|
|
s2 = (char *)strSearch;
|
|
|
|
if (*s1 == chUntil)
|
|
return NULL;
|
|
|
|
while (*s1 && *s2 && !(*s1-*s2))
|
|
{
|
|
s1++, s2++;
|
|
}
|
|
|
|
if (!*s2)
|
|
return cp;
|
|
|
|
cp++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const char * StrStrUntilStr(const char * string, const char * strSearch, const char * strUntil)
|
|
{
|
|
char *cp = (char *)string;
|
|
char *s1, *s2, *s3;
|
|
|
|
if (!*strSearch)
|
|
return ((char *)string);
|
|
|
|
while (*cp)
|
|
{
|
|
s1 = cp;
|
|
s2 = (char *)strSearch;
|
|
s3 = (char *)strUntil;
|
|
|
|
while (*s1 && *s3 && !(*s1-*s3))
|
|
{
|
|
s1++, s3++;
|
|
}
|
|
|
|
if (!*s3)
|
|
return NULL;
|
|
|
|
while (*s1 && *s2 && !(*s1-*s2))
|
|
{
|
|
s1++, s2++;
|
|
}
|
|
|
|
if (!*s2)
|
|
return cp;
|
|
|
|
cp++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const char * StrBetweenCpy(const char * pSrc, const char * pszFront, const char * pszRear, char * pDst)
|
|
{
|
|
char * pszStart, * pszEnd;
|
|
|
|
if ((pszStart = (char *)strstr(pSrc, pszFront)) == NULL)
|
|
return NULL;
|
|
|
|
pszStart += strlen(pszFront);
|
|
|
|
if ((pszEnd = strstr(pszStart, pszRear)) == NULL)
|
|
return NULL;
|
|
|
|
strncpy(pDst, pszStart, pszEnd - pszStart);
|
|
pDst[pszEnd - pszStart] = '\0';
|
|
|
|
return pszEnd + strlen(pszRear);
|
|
}
|
|
|
|
size_t StrRemoveBetween(char * pszDst, const char * pszSrc, const char * pszFront, const char * pszRear)
|
|
{
|
|
char * pszStart, * pszEnd;
|
|
|
|
if ((pszStart = (char *)strstr(pszSrc, pszFront)) == NULL)
|
|
return 0;
|
|
|
|
pszStart += strlen(pszFront);
|
|
|
|
if ((pszEnd = strstr(pszStart, pszRear)) == NULL)
|
|
return 0;
|
|
|
|
size_t nFrontSize = pszStart - pszSrc;
|
|
strncpy(pszDst, pszSrc, nFrontSize);
|
|
strcpy(pszDst + nFrontSize, pszEnd);
|
|
|
|
return nFrontSize + strlen(pszEnd);
|
|
}
|
|
|
|
int StrCountChar(const char * string, char ch)
|
|
{
|
|
int n = 0;
|
|
while (*string)
|
|
{
|
|
if (*string++ == ch)
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
int StrCountStr(const char * string, const char * strSearch)
|
|
{
|
|
int nCount = 0;
|
|
size_t nSrcLength = strlen(string);
|
|
size_t nFindLength = strlen(strSearch);
|
|
|
|
char * pszStart = (char *)string;
|
|
char * pszEnd = (char *)string + nSrcLength;
|
|
char * pszTarget;
|
|
while (pszStart < pszEnd)
|
|
{
|
|
while ((pszTarget = strstr(pszStart, strSearch)) != NULL)
|
|
{
|
|
nCount++;
|
|
pszStart = pszTarget + nFindLength;
|
|
}
|
|
pszStart += strlen(pszStart) + 1;
|
|
}
|
|
|
|
return nCount;
|
|
}
|
|
|
|
int StrCountRow(const char * string)
|
|
{
|
|
int nCount = 0;
|
|
const char * p = string;
|
|
while (*p)
|
|
{
|
|
if (*p++ == '\n')
|
|
nCount++;
|
|
}
|
|
|
|
if (nCount == 0)
|
|
{
|
|
p = string;
|
|
while (*p)
|
|
{
|
|
if (*p++ == '\r')
|
|
nCount++;
|
|
}
|
|
}
|
|
|
|
if (nCount == 0 && *string != '\0')
|
|
return 1;
|
|
|
|
return nCount;
|
|
}
|
|
|
|
char * StrTok(const char * pszSrc, const char * pszDelimit, char * pszTokenBuff)
|
|
{
|
|
char * pNext, * pSrcOffset = (char *)pszSrc;
|
|
|
|
for (;;)
|
|
{
|
|
pNext = strstr(pSrcOffset, pszDelimit);
|
|
if (pNext == NULL)
|
|
{
|
|
strcpy(pszTokenBuff, pSrcOffset);
|
|
return NULL;
|
|
}
|
|
else if (pNext != pSrcOffset)
|
|
break;
|
|
|
|
pSrcOffset += strlen(pszDelimit);
|
|
}
|
|
|
|
strncpy(pszTokenBuff, pSrcOffset, pNext - pSrcOffset);
|
|
pszTokenBuff[pNext - pSrcOffset] = '\0';
|
|
|
|
return pNext + strlen(pszDelimit);
|
|
}
|
|
|
|
// const char pszTest[] = " 123456 ";
|
|
// char * psz = (char *)pszTest;
|
|
// StrTrim(&psz, strlen(psz), true, true);
|
|
// psz --> "123456"
|
|
void StrTrim(char ** ppsz, size_t nLength, bool bRemoveFront, bool bRemoveRear)
|
|
{
|
|
if (bRemoveFront)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < nLength; i++)
|
|
{
|
|
if ((*ppsz)[i] == ' ' || (*ppsz)[i] == '\t')
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
nLength -= i;
|
|
*ppsz = *ppsz + i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == nLength)
|
|
{
|
|
nLength = 0;
|
|
(*ppsz)[0] = '\0';
|
|
}
|
|
}
|
|
|
|
if (bRemoveRear)
|
|
{
|
|
for (int i = int(nLength - 1); i >= 0; i--)
|
|
{
|
|
if ((*ppsz)[i] == ' ' || (*ppsz)[i] == '\t')
|
|
{
|
|
(*ppsz)[i] = '\0';
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const char * StrNTrimPtr(const char * pszSrc, int nSrcCount)
|
|
{
|
|
int nRemain = nSrcCount;
|
|
for (;;)
|
|
{
|
|
if (*pszSrc == '\0')
|
|
break;
|
|
else if (*pszSrc == ' ' || *pszSrc == '\t')
|
|
pszSrc++;
|
|
else
|
|
break;
|
|
|
|
if (nSrcCount > 0 && --nRemain <= 0)
|
|
break;
|
|
}
|
|
|
|
return pszSrc;
|
|
}
|
|
|
|
void StrNTrimCpy(char * pszDst, const char * pszSrc, int nSrcCount)
|
|
{
|
|
if (nSrcCount == 0)
|
|
return;
|
|
|
|
int nRemain = nSrcCount;
|
|
for (;;)
|
|
{
|
|
if (*pszSrc == '\0')
|
|
break;
|
|
else if (*pszSrc == ' ' || *pszSrc == '\t')
|
|
pszSrc++;
|
|
else
|
|
*pszDst++ = *pszSrc++;
|
|
|
|
if (nSrcCount > 0 && --nRemain <= 0)
|
|
break;
|
|
}
|
|
|
|
*pszDst = '\0';
|
|
}
|
|
|
|
char * StrReadLine(char * pszDst, const char * pszSrc, int nCount)
|
|
{
|
|
int i = 0;
|
|
for (; ; i++)
|
|
{
|
|
if (nCount > 0 && i >= nCount)
|
|
break;
|
|
|
|
if (pszSrc[i] == '\r' ||
|
|
pszSrc[i] == '\n')
|
|
{
|
|
pszDst[i] = '\0';
|
|
break;
|
|
}
|
|
else if (pszSrc[i] == '\0')
|
|
{
|
|
pszDst[i] = '\0';
|
|
return NULL;
|
|
}
|
|
else
|
|
pszDst[i] = pszSrc[i];
|
|
}
|
|
|
|
for (; ; i++)
|
|
{
|
|
if (nCount > 0 && i >= nCount)
|
|
break;
|
|
|
|
if (pszSrc[i] != '\r' && pszSrc[i] != '\n' && pszSrc[i] != 0x09)
|
|
break;
|
|
}
|
|
|
|
return (char *)pszSrc + i;
|
|
}
|
|
|
|
// return new memory
|
|
const char * StrReplace(const char * pszText, const char * pszKeyword, const char * pszReplace, int nMode, int nCount)
|
|
{
|
|
if (nCount == 0)
|
|
return NULL;
|
|
|
|
const char * (*fnStrStr)(const char *, const char *);
|
|
if (nMode == 0)
|
|
fnStrStr = (const char*(*)(const char*, const char*))strstr;
|
|
else if (nMode == 1)
|
|
fnStrStr = stristr;
|
|
else
|
|
fnStrStr = StrIKeyword;
|
|
|
|
int nRepeatCount = nCount;
|
|
size_t nKeywordLength = strlen(pszKeyword);
|
|
const char * pszNext = (const char *)pszText;
|
|
int nKeywordCount = 0;
|
|
for (;;)
|
|
{
|
|
if ((pszNext = fnStrStr(pszNext, pszKeyword)) == NULL)
|
|
break;
|
|
|
|
nKeywordCount++;
|
|
|
|
if (nRepeatCount > -1 && --nRepeatCount == 0)
|
|
break;
|
|
|
|
pszNext += nKeywordLength;
|
|
}
|
|
|
|
if (nKeywordCount == 0)
|
|
return NULL;
|
|
|
|
size_t nReplaceLength = strlen(pszReplace);
|
|
size_t nTextLength = strlen(pszText);
|
|
size_t nNewTextLength = nTextLength + (nReplaceLength - nKeywordLength) * nKeywordCount;
|
|
char * pszNewText = (char *)malloc(nNewTextLength + 1);
|
|
|
|
size_t nCopySize;
|
|
size_t nRemainSize = nTextLength;
|
|
char * pszNewTextOffset = pszNewText;
|
|
const char * pszTextOffset = pszText;
|
|
|
|
nRepeatCount = nCount;
|
|
for (;;)
|
|
{
|
|
if ((pszNext = fnStrStr(pszTextOffset, pszKeyword)) == NULL)
|
|
break;
|
|
|
|
nCopySize = pszNext - pszTextOffset;
|
|
|
|
memcpy(pszNewTextOffset, pszTextOffset, nCopySize);
|
|
memcpy(pszNewTextOffset + nCopySize, pszReplace, nReplaceLength);
|
|
|
|
pszTextOffset += nCopySize + nKeywordLength;
|
|
pszNewTextOffset += nCopySize + nReplaceLength;
|
|
|
|
nRemainSize -= nCopySize + nKeywordLength;
|
|
|
|
if (nRepeatCount > -1 && --nRepeatCount == 0)
|
|
break;
|
|
}
|
|
|
|
if (nRemainSize > 0)
|
|
memcpy(pszNewTextOffset, pszTextOffset, nRemainSize);
|
|
|
|
pszNewText[nNewTextLength] = '\0';
|
|
return pszNewText;
|
|
}
|
|
|
|
size_t StrReplace2(char * pszDst, const char * pszText, const char * pszKeyword, const char * pszReplace, int nMode, int nCount)
|
|
{
|
|
if (nCount == 0)
|
|
return 0;
|
|
|
|
const char * (*fnStrStr)(const char *, const char *);
|
|
if (nMode == 0)
|
|
fnStrStr = (const char*(*)(const char*, const char*))strstr;
|
|
else if (nMode == 1)
|
|
fnStrStr = stristr;
|
|
else
|
|
fnStrStr = StrIKeyword;
|
|
|
|
size_t nKeywordLength = strlen(pszKeyword);
|
|
size_t nReplaceLength = strlen(pszReplace);
|
|
size_t nRemainSize = strlen(pszText);
|
|
char * pszNewTextOffset = pszDst;
|
|
const char * pszTextOffset = pszText;
|
|
|
|
size_t nNewTextLength = 0;
|
|
size_t nCopySize;
|
|
const char * pszNext;
|
|
|
|
int nRepeatCount = nCount;
|
|
for (;;)
|
|
{
|
|
if ((pszNext = fnStrStr(pszTextOffset, pszKeyword)) == NULL)
|
|
break;
|
|
|
|
nCopySize = pszNext - pszTextOffset;
|
|
|
|
memcpy(pszNewTextOffset, pszTextOffset, nCopySize);
|
|
memcpy(pszNewTextOffset + nCopySize, pszReplace, nReplaceLength);
|
|
|
|
pszTextOffset += nCopySize + nKeywordLength;
|
|
pszNewTextOffset += nCopySize + nReplaceLength;
|
|
|
|
nNewTextLength += nCopySize + nReplaceLength;
|
|
nRemainSize -= nCopySize + nKeywordLength;
|
|
|
|
if (nRepeatCount > -1 && --nRepeatCount == 0)
|
|
break;
|
|
}
|
|
|
|
if (nNewTextLength == 0)
|
|
return 0;
|
|
|
|
if (nRemainSize > 0)
|
|
{
|
|
memcpy(pszNewTextOffset, pszTextOffset, nRemainSize);
|
|
nNewTextLength += nRemainSize;
|
|
}
|
|
|
|
pszDst[nNewTextLength] = '\0';
|
|
return nNewTextLength;
|
|
}
|
|
|
|
const void * memmem_hus(const void * pMem, size_t nMemSize, const void * pKeymem, size_t nKeymemSize)
|
|
{
|
|
const char * p1 = (const char *)pMem;
|
|
const char * p2;
|
|
const void * p3;
|
|
size_t nP2;
|
|
|
|
do
|
|
{
|
|
p2 = (const char *)pKeymem;
|
|
nP2 = nKeymemSize;
|
|
|
|
while (*p1 != *p2)
|
|
{
|
|
p1++;
|
|
nMemSize--;
|
|
|
|
if (nMemSize <= 0)
|
|
return NULL;
|
|
}
|
|
|
|
p3 = p1;
|
|
do
|
|
{
|
|
p1++;
|
|
nMemSize--;
|
|
|
|
p2++;
|
|
nP2--;
|
|
|
|
if (nP2 <= 0)
|
|
return p3;
|
|
else if (*p1 != *p2)
|
|
break;
|
|
} while (nMemSize);
|
|
} while (nMemSize);
|
|
|
|
return NULL;
|
|
}
|