524 lines
10 KiB
C
524 lines
10 KiB
C
|
/*** strlib.c - string functions
|
||
|
*
|
||
|
* Copyright (c) 1996,1997 Microsoft Corporation
|
||
|
* Author: Michael Tsang (MikeTs)
|
||
|
* Created 09/09/96
|
||
|
*
|
||
|
* MODIFICATION HISTORY
|
||
|
*/
|
||
|
|
||
|
#include "pch.h"
|
||
|
|
||
|
#ifdef LOCKABLE_PRAGMA
|
||
|
#pragma ACPI_LOCKABLE_DATA
|
||
|
#pragma ACPI_LOCKABLE_CODE
|
||
|
#endif
|
||
|
|
||
|
/***EP StrLen - determine string length
|
||
|
*
|
||
|
* ENTRY
|
||
|
* psz -> string
|
||
|
* n - limiting length
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns string length
|
||
|
*/
|
||
|
|
||
|
ULONG EXPORT StrLen(PSZ psz, ULONG n)
|
||
|
{
|
||
|
TRACENAME("STRLEN")
|
||
|
ULONG dwLen;
|
||
|
|
||
|
ENTER(5, ("StrLen(str=%s,n=%d)\n", psz, n));
|
||
|
|
||
|
ASSERT(psz != NULL);
|
||
|
if (n != (ULONG)-1)
|
||
|
n++;
|
||
|
for (dwLen = 0; (dwLen <= n) && (*psz != '\0'); psz++)
|
||
|
dwLen++;
|
||
|
|
||
|
EXIT(5, ("StrLen=%u\n", dwLen));
|
||
|
return dwLen;
|
||
|
} //StrLen
|
||
|
|
||
|
/***EP StrCpy - copy string
|
||
|
*
|
||
|
* ENTRY
|
||
|
* pszDst -> destination string
|
||
|
* pszSrc -> source string
|
||
|
* n - number of bytes to copy
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns pszDst
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT StrCpy(PSZ pszDst, PSZ pszSrc, ULONG n)
|
||
|
{
|
||
|
TRACENAME("STRCPY")
|
||
|
ULONG dwSrcLen;
|
||
|
|
||
|
ENTER(5, ("StrCpy(Dst=%s,Src=%s,n=%d)\n", pszDst, pszSrc, n));
|
||
|
|
||
|
ASSERT(pszDst != NULL);
|
||
|
ASSERT(pszSrc != NULL);
|
||
|
|
||
|
dwSrcLen = StrLen(pszSrc, n);
|
||
|
if ((n == (ULONG)(-1)) || (n > dwSrcLen))
|
||
|
n = dwSrcLen;
|
||
|
|
||
|
MEMCPY(pszDst, pszSrc, n);
|
||
|
pszDst[n] = '\0';
|
||
|
|
||
|
EXIT(5, ("StrCpy=%s\n", pszDst));
|
||
|
return pszDst;
|
||
|
} //StrCpy
|
||
|
|
||
|
/***EP StrCat - concatenate strings
|
||
|
*
|
||
|
* ENTRY
|
||
|
* pszDst -> destination string
|
||
|
* pszSrc -> source string
|
||
|
* n - number of bytes to concatenate
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns pszDst
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT StrCat(PSZ pszDst, PSZ pszSrc, ULONG n)
|
||
|
{
|
||
|
TRACENAME("STRCAT")
|
||
|
ULONG dwSrcLen, dwDstLen;
|
||
|
|
||
|
ENTER(5, ("StrCat(Dst=%s,Src=%s,n=%d)\n", pszDst, pszSrc, n));
|
||
|
|
||
|
ASSERT(pszDst != NULL);
|
||
|
ASSERT(pszSrc != NULL);
|
||
|
|
||
|
dwSrcLen = StrLen(pszSrc, n);
|
||
|
if ((n == (ULONG)(-1)) || (n > dwSrcLen))
|
||
|
n = dwSrcLen;
|
||
|
|
||
|
dwDstLen = StrLen(pszDst, (ULONG)(-1));
|
||
|
MEMCPY(&pszDst[dwDstLen], pszSrc, n);
|
||
|
pszDst[dwDstLen + n] = '\0';
|
||
|
|
||
|
EXIT(5, ("StrCat=%s\n", pszDst));
|
||
|
return pszDst;
|
||
|
} //StrCat
|
||
|
|
||
|
/***EP StrCmp - compare strings
|
||
|
*
|
||
|
* ENTRY
|
||
|
* psz1 -> string 1
|
||
|
* psz2 -> string 2
|
||
|
* n - number of bytes to compare
|
||
|
* fMatchCase - TRUE if case sensitive
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns 0 if string 1 == string 2
|
||
|
* <0 if string 1 < string 2
|
||
|
* >0 if string 1 > string 2
|
||
|
*/
|
||
|
|
||
|
LONG EXPORT StrCmp(PSZ psz1, PSZ psz2, ULONG n, BOOLEAN fMatchCase)
|
||
|
{
|
||
|
TRACENAME("STRCMP")
|
||
|
LONG rc;
|
||
|
ULONG dwLen1, dwLen2;
|
||
|
ULONG i;
|
||
|
|
||
|
ENTER(5, ("StrCmp(s1=%s,s2=%s,n=%d,fMatchCase=%d)\n",
|
||
|
psz1, psz2, n, fMatchCase));
|
||
|
|
||
|
ASSERT(psz1 != NULL);
|
||
|
ASSERT(psz2 != NULL);
|
||
|
|
||
|
dwLen1 = StrLen(psz1, n);
|
||
|
dwLen2 = StrLen(psz2, n);
|
||
|
if (n == (ULONG)(-1))
|
||
|
n = (dwLen1 > dwLen2)? dwLen1: dwLen2;
|
||
|
|
||
|
if (fMatchCase)
|
||
|
{
|
||
|
for (i = 0, rc = 0;
|
||
|
(rc == 0) && (i < n) && (i < dwLen1) && (i < dwLen2);
|
||
|
++i)
|
||
|
{
|
||
|
rc = (LONG)(psz1[i] - psz2[i]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (i = 0, rc = 0;
|
||
|
(rc == 0) && (i < n) && (i < dwLen1) && (i < dwLen2);
|
||
|
++i)
|
||
|
{
|
||
|
rc = (LONG)(TOUPPER(psz1[i]) - TOUPPER(psz2[i]));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((rc == 0) && (i < n))
|
||
|
{
|
||
|
if (i < dwLen1)
|
||
|
rc = (LONG)psz1[i];
|
||
|
else if (i < dwLen2)
|
||
|
rc = (LONG)(-psz2[i]);
|
||
|
}
|
||
|
|
||
|
EXIT(5, ("StrCmp=%d\n", rc));
|
||
|
return rc;
|
||
|
} //StrCmp
|
||
|
|
||
|
/***EP StrChr - look for a character in a string
|
||
|
*
|
||
|
* ENTRY
|
||
|
* psz -> string
|
||
|
* c - character to look for
|
||
|
*
|
||
|
* EXIT-SUCCESS
|
||
|
* returns a pointer to the character found
|
||
|
* EXIT-FAILURE
|
||
|
* returns NULL
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT StrChr(PSZ pszStr, CHAR c)
|
||
|
{
|
||
|
TRACENAME("STRCHR")
|
||
|
PSZ psz;
|
||
|
|
||
|
ENTER(5, ("StrChr(s=%s,c=%c)\n", pszStr, c));
|
||
|
|
||
|
ASSERT(pszStr != NULL);
|
||
|
for (psz = pszStr; (*psz != c) && (*psz != '\0'); psz++)
|
||
|
;
|
||
|
|
||
|
if (*psz != c)
|
||
|
psz = NULL;
|
||
|
|
||
|
EXIT(5, ("StrChr=%x\n", psz));
|
||
|
return psz;
|
||
|
} //StrChr
|
||
|
|
||
|
/***EP StrRChr - look for a character in a string in reverse direction
|
||
|
*
|
||
|
* ENTRY
|
||
|
* psz -> string
|
||
|
* c - character to look for
|
||
|
*
|
||
|
* EXIT-SUCCESS
|
||
|
* returns a pointer to the character found
|
||
|
* EXIT-FAILURE
|
||
|
* returns NULL
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT StrRChr(PSZ pszStr, CHAR c)
|
||
|
{
|
||
|
TRACENAME("STRRCHR")
|
||
|
PSZ psz;
|
||
|
|
||
|
ENTER(5, ("StrChr(s=%s,c=%c)\n", pszStr, c));
|
||
|
|
||
|
ASSERT(pszStr != NULL);
|
||
|
for (psz = &pszStr[StrLen(pszStr, (ULONG)-1)];
|
||
|
(*psz != c) && (psz > pszStr);
|
||
|
psz--)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
if (*psz != c)
|
||
|
psz = NULL;
|
||
|
|
||
|
EXIT(5, ("StrRChr=%x\n", psz));
|
||
|
return psz;
|
||
|
} //StrRChr
|
||
|
|
||
|
/***EP StrTok - find the next token in string
|
||
|
*
|
||
|
* ENTRY
|
||
|
* pszStr -> string containing tokens
|
||
|
* pszSep -> string containing delimiters
|
||
|
*
|
||
|
* EXIT-SUCCESS
|
||
|
* returns the pointer to the beginning of the token
|
||
|
* EXIT-FAILURE
|
||
|
* returns NULL
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT StrTok(PSZ pszStr, PSZ pszSep)
|
||
|
{
|
||
|
TRACENAME("STRTOK")
|
||
|
static PSZ pszNext = NULL;
|
||
|
|
||
|
|
||
|
ENTER(5, ("StrTok(Str=%s,Sep=%s)\n", pszStr, pszSep));
|
||
|
|
||
|
ASSERT(pszSep != NULL);
|
||
|
|
||
|
if (pszStr == NULL)
|
||
|
pszStr = pszNext;
|
||
|
|
||
|
if (pszStr != NULL)
|
||
|
{
|
||
|
//
|
||
|
// Skip leading delimiter characters
|
||
|
//
|
||
|
while ((*pszStr != '\0') && (StrChr(pszSep, *pszStr) != NULL))
|
||
|
pszStr++;
|
||
|
|
||
|
for (pszNext = pszStr;
|
||
|
(*pszNext != '\0') && (StrChr(pszSep, *pszNext) == NULL);
|
||
|
pszNext++)
|
||
|
;
|
||
|
|
||
|
if (*pszStr == '\0')
|
||
|
pszStr = NULL;
|
||
|
else if (*pszNext != '\0')
|
||
|
{
|
||
|
*pszNext = '\0';
|
||
|
pszNext++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EXIT(5, ("StrTok=%s (Next=%s)\n",
|
||
|
pszStr? pszStr: "(null)", pszNext? pszNext: "(null)"));
|
||
|
return pszStr;
|
||
|
} //StrTok
|
||
|
|
||
|
/***EP StrToUL - convert the number in a string to a unsigned long integer
|
||
|
*
|
||
|
* ENTRY
|
||
|
* psz -> string
|
||
|
* ppszEnd -> string pointer to the end of the number (can be NULL)
|
||
|
* dwBase - the base of the number (if 0, auto-detect base)
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns the converted number
|
||
|
*/
|
||
|
|
||
|
ULONG EXPORT StrToUL(PSZ psz, PSZ *ppszEnd, ULONG dwBase)
|
||
|
{
|
||
|
TRACENAME("STRTOUL")
|
||
|
ULONG n = 0;
|
||
|
ULONG m;
|
||
|
|
||
|
ENTER(5, ("StrToUL(Str=%s,ppszEnd=%x,Base=%x)\n", psz, ppszEnd, dwBase));
|
||
|
|
||
|
if (dwBase == 0)
|
||
|
{
|
||
|
if (psz[0] == '0')
|
||
|
{
|
||
|
if ((psz[1] == 'x') || (psz[1] == 'X'))
|
||
|
{
|
||
|
dwBase = 16;
|
||
|
psz += 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwBase = 8;
|
||
|
psz++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
dwBase = 10;
|
||
|
}
|
||
|
|
||
|
while (*psz != '\0')
|
||
|
{
|
||
|
if ((*psz >= '0') && (*psz <= '9'))
|
||
|
m = *psz - '0';
|
||
|
else if ((*psz >= 'A') && (*psz <= 'Z'))
|
||
|
m = *psz - 'A' + 10;
|
||
|
else if ((*psz >= 'a') && (*psz <= 'z'))
|
||
|
m = *psz - 'a' + 10;
|
||
|
else
|
||
|
break;
|
||
|
|
||
|
if (m < dwBase)
|
||
|
{
|
||
|
n = (n*dwBase) + m;
|
||
|
psz++;
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (ppszEnd != NULL)
|
||
|
*ppszEnd = psz;
|
||
|
|
||
|
EXIT(5, ("StrToUL=%x (pszEnd=%x)\n", n, ppszEnd? *ppszEnd: 0));
|
||
|
return n;
|
||
|
} //StrToUL
|
||
|
|
||
|
/***EP StrToL - convert the number in a string to a long integer
|
||
|
*
|
||
|
* ENTRY
|
||
|
* psz -> string
|
||
|
* ppszEnd -> string pointer to the end of the number (can be NULL)
|
||
|
* dwBase - the base of the number (if 0, auto-detect base)
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns the converted number
|
||
|
*/
|
||
|
|
||
|
LONG EXPORT StrToL(PSZ psz, PSZ *ppszEnd, ULONG dwBase)
|
||
|
{
|
||
|
TRACENAME("STRTOL")
|
||
|
LONG n = 0;
|
||
|
BOOLEAN fMinus;
|
||
|
|
||
|
ENTER(5, ("StrToL(Str=%s,ppszEnd=%x,Base=%x)\n", psz, ppszEnd, dwBase));
|
||
|
|
||
|
if (*psz == '-')
|
||
|
{
|
||
|
fMinus = TRUE;
|
||
|
psz++;
|
||
|
}
|
||
|
else
|
||
|
fMinus = FALSE;
|
||
|
|
||
|
n = (LONG)StrToUL(psz, ppszEnd, dwBase);
|
||
|
|
||
|
if (fMinus)
|
||
|
n = -n;
|
||
|
|
||
|
EXIT(5, ("StrToL=%x (pszEnd=%x)\n", n, ppszEnd? *ppszEnd: 0));
|
||
|
return n;
|
||
|
} //StrToL
|
||
|
|
||
|
/***EP StrStr - find a substring in a given string
|
||
|
*
|
||
|
* ENTRY
|
||
|
* psz1 -> string to be searched
|
||
|
* psz2 -> substring to find
|
||
|
*
|
||
|
* EXIT-SUCCESS
|
||
|
* returns pointer to psz1 where the substring is found
|
||
|
* EXIT-FAILURE
|
||
|
* returns NULL
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT StrStr(PSZ psz1, PSZ psz2)
|
||
|
{
|
||
|
TRACENAME("STRSTR")
|
||
|
PSZ psz = psz1;
|
||
|
ULONG dwLen;
|
||
|
|
||
|
ENTER(5, ("StrStr(psz1=%s,psz2=%s)\n", psz1, psz2));
|
||
|
|
||
|
dwLen = StrLen(psz2, (ULONG)-1);
|
||
|
while ((psz = StrChr(psz, *psz2)) != NULL)
|
||
|
{
|
||
|
if (StrCmp(psz, psz2, dwLen, TRUE) == 0)
|
||
|
break;
|
||
|
else
|
||
|
psz++;
|
||
|
}
|
||
|
|
||
|
EXIT(5, ("StrStr=%s\n", psz));
|
||
|
return psz;
|
||
|
} //StrStr
|
||
|
|
||
|
/***EP StrUpr - convert string to upper case
|
||
|
*
|
||
|
* ENTRY
|
||
|
* pszStr -> string
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns pszStr
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT StrUpr(PSZ pszStr)
|
||
|
{
|
||
|
TRACENAME("STRUPR")
|
||
|
PSZ psz;
|
||
|
|
||
|
ENTER(5, ("StrUpr(Str=%s)\n", pszStr));
|
||
|
|
||
|
for (psz = pszStr; *psz != '\0'; psz++)
|
||
|
{
|
||
|
*psz = TOUPPER(*psz);
|
||
|
}
|
||
|
|
||
|
EXIT(5, ("StrUpr=%s\n", pszStr));
|
||
|
return pszStr;
|
||
|
} //StrUpr
|
||
|
|
||
|
/***EP StrLwr - convert string to lower case
|
||
|
*
|
||
|
* ENTRY
|
||
|
* pszStr -> string
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns pszStr
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT StrLwr(PSZ pszStr)
|
||
|
{
|
||
|
TRACENAME("STRLWR")
|
||
|
PSZ psz;
|
||
|
|
||
|
ENTER(5, ("StrLwr(Str=%s)\n", pszStr));
|
||
|
|
||
|
for (psz = pszStr; *psz != '\0'; psz++)
|
||
|
{
|
||
|
*psz = TOLOWER(*psz);
|
||
|
}
|
||
|
|
||
|
EXIT(5, ("StrLwr=%s\n", pszStr));
|
||
|
return pszStr;
|
||
|
} //StrLwr
|
||
|
|
||
|
/***EP UlToA - convert an unsigned long value to a string
|
||
|
*
|
||
|
* ENTRY
|
||
|
* dwValue - data
|
||
|
* pszStr -> string
|
||
|
* dwRadix - radix
|
||
|
*
|
||
|
* EXIT
|
||
|
* returns pszStr
|
||
|
*/
|
||
|
|
||
|
PSZ EXPORT UlToA(ULONG dwValue, PSZ pszStr, ULONG dwRadix)
|
||
|
{
|
||
|
TRACENAME("ULTOA")
|
||
|
PSZ psz;
|
||
|
char ch;
|
||
|
|
||
|
ENTER(5, ("UlToA(Value=%x,pszStr=%x,Radix=%d\n", dwValue, pszStr, dwRadix));
|
||
|
|
||
|
for (psz = pszStr; dwValue != 0; dwValue/=dwRadix, psz++)
|
||
|
{
|
||
|
ch = (char)(dwValue%dwRadix);
|
||
|
if (ch <= 9)
|
||
|
{
|
||
|
*psz = (char)(ch + '0');
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*psz = (char)(ch - 10 + 'A');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (psz == pszStr)
|
||
|
{
|
||
|
pszStr[0] = '0';
|
||
|
pszStr[1] = '\0';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PSZ psz2;
|
||
|
|
||
|
*psz = '\0';
|
||
|
for (psz2 = pszStr, psz--; psz2 < psz; psz2++, psz--)
|
||
|
{
|
||
|
ch = *psz2;
|
||
|
*psz2 = *psz;
|
||
|
*psz = ch;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EXIT(5, ("UlToA=%s\n", pszStr));
|
||
|
return pszStr;
|
||
|
} //UlToA
|