You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1227 lines
34 KiB
1227 lines
34 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// File: strings.cpp
|
|
//
|
|
// Module: CMUTIL.DLL
|
|
//
|
|
// Synopsis: Basic string manipulation routines
|
|
//
|
|
// Copyright (c) 1997-1999 Microsoft Corporation
|
|
//
|
|
// Author: henryt Created 03/01/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
#include "cmmaster.h"
|
|
|
|
//
|
|
// Include the locale-safe replacement for lstrcmpi
|
|
//
|
|
#define _CMUTIL_STRINGS_CPP_
|
|
#include "CompareString.cpp"
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: WzToSz
|
|
//
|
|
// Synopsis: Standard conversion function for converting Wide Characters to
|
|
// Ansi Characters
|
|
//
|
|
// Arguments: IN LPCWSTR pszwStrIn - Input Unicode string
|
|
// OUT LPSTR pszStrOut - Ansi Ouput Buffer
|
|
// IN int nOutBufferSize - number of Chars in pszStrOut
|
|
//
|
|
// Returns: int - 0 on failure, if return Value is > nOutBufferSize then the
|
|
// buffer is too small. Otherwise the number of chars copied
|
|
// to pszStrOut.
|
|
//
|
|
// History: Created Header 4/22/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI int WzToSz(IN LPCWSTR pszwStrIn, OUT LPSTR pszStrOut, IN int nOutBufferSize)
|
|
{
|
|
int nReturn = 0;
|
|
|
|
//
|
|
// nOutBufferSize could be 0 and pszStrOut could be NULL (passing zero size and a NULL out
|
|
// buffer causes WideCharToMultiByte to return the number of chars needed to convert the
|
|
// input string. It is used as a sizing technique). Only check pszwStrIn
|
|
//
|
|
|
|
if (pszwStrIn)
|
|
{
|
|
nReturn = WideCharToMultiByte(CP_ACP, 0, pszwStrIn, -1, pszStrOut, nOutBufferSize, NULL, NULL);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return nReturn;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: SzToWz
|
|
//
|
|
// Synopsis: Standard Wrapper for converting from an Ansi string to a Wide String
|
|
//
|
|
// Arguments: IN LPCSTR pszInput - Ansi String to Convert
|
|
// OUT LPWSTR pszwOutput - Wide string output buffer
|
|
// IN int nBufferSize - number of chars in Wide String buffer
|
|
//
|
|
// Returns: int - 0 on failure, otherwise if return is < nBufferSize then insufficient
|
|
// buffer space. Otherwise the number of chars copied to the buffer.
|
|
//
|
|
// History: quintinb Created 4/22/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI int SzToWz(IN LPCSTR pszInput, OUT LPWSTR pszwOutput, IN int nBufferSize)
|
|
{
|
|
int nReturn = 0;
|
|
|
|
if (pszInput)
|
|
{
|
|
return MultiByteToWideChar(CP_ACP, 0, pszInput, -1, pszwOutput, nBufferSize);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return nReturn;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: SzToWzWithAlloc
|
|
//
|
|
// Synopsis: Simple wrapper to encapsulate converting a string from
|
|
// MultiByte To Wide Char that Allocates memory using the sizing
|
|
// capabilities of the MultiByteToWideChar Api.
|
|
//
|
|
// Arguments: LPCSTR pszAnsiString - Source string to be converted.
|
|
//
|
|
// Returns: LPWSTR - returns NULL on failure, otherwise the converted string.
|
|
// The caller is responsible for freeing the Alloc-ed Memory.
|
|
//
|
|
// History: quintinb Created 4/8/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPWSTR SzToWzWithAlloc(LPCSTR pszAnsiString)
|
|
{
|
|
LPWSTR pszwString = NULL;
|
|
DWORD dwSize = 0;
|
|
|
|
//
|
|
// Find out how large the string is by calling MultiByteToWideChar with
|
|
// Zero for the size field.
|
|
//
|
|
if (NULL != pszAnsiString)
|
|
{
|
|
dwSize = SzToWz(pszAnsiString, NULL, 0);
|
|
|
|
CMASSERTMSG((dwSize != 0), TEXT("SzToWzWithAlloc -- First MultiByteToWideChar Failed."));
|
|
|
|
if (0 != dwSize)
|
|
{
|
|
pszwString = (LPWSTR)CmMalloc(dwSize*sizeof(WCHAR));
|
|
|
|
CMASSERTMSG(pszwString, TEXT("SzToWzWithAlloc -- CmMalloc of pszwString Failed."));
|
|
|
|
if (pszwString)
|
|
{
|
|
if (!SzToWz(pszAnsiString, pszwString, dwSize))
|
|
{
|
|
//
|
|
// Make sure to return a NULL string if we fail.
|
|
//
|
|
CMASSERTMSG(FALSE, TEXT("SzToWzWithAlloc -- Second MultiByteToWideChar Failed."));
|
|
CmFree(pszwString);
|
|
pszwString = NULL;
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
//
|
|
// If this is a debug build then we want to take the Wide string that we are going to
|
|
// return, convert it to Ansi and compare it to the original ansi string passed in.
|
|
//
|
|
LPSTR pszString;
|
|
|
|
dwSize = WzToSz(pszwString, NULL, 0);
|
|
|
|
if (0 != dwSize)
|
|
{
|
|
pszString = (LPSTR)CmMalloc(dwSize*sizeof(CHAR));
|
|
CMASSERTMSG(pszString, TEXT("SzToWzWithAlloc -- conversion of return value back to original Ansi string failed. Unable to allocate memory."));
|
|
|
|
if (pszString)
|
|
{
|
|
if (WzToSz(pszwString, pszString, dwSize))
|
|
{
|
|
MYDBGASSERT(0 == lstrcmpA(pszString, pszAnsiString));
|
|
}
|
|
else
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("SzToWzWithAlloc -- conversion of return value back to original Ansi string failed."));
|
|
}
|
|
CmFree(pszString);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("SzToWzWithAlloc -- conversion of return value back to original Ansi string failed. Unable to properly size the string."));
|
|
}
|
|
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
return pszwString;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: WzToSzWithAlloc
|
|
//
|
|
// Synopsis: Simple wrapper to encapsulate converting a string from
|
|
// Unicode to MBCS that allocates memory using the sizing
|
|
// capabilities of the WideCharToMultiByte Api.
|
|
//
|
|
// Arguments: LPCWSTR pszwWideString - Source string to be converted.
|
|
//
|
|
// Returns: LPSTR - returns NULL on failure, otherwise the converted string.
|
|
// The caller is responsible for freeing the Alloc-ed Memory.
|
|
//
|
|
// History: quintinb Created 4/8/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPSTR WzToSzWithAlloc(LPCWSTR pszwWideString)
|
|
{
|
|
LPSTR pszString = NULL;
|
|
DWORD dwSize = 0;
|
|
|
|
//
|
|
// Find out how large the string is by calling WideCharToMultiByte with
|
|
// Zero for the size field.
|
|
//
|
|
if (NULL != pszwWideString)
|
|
{
|
|
dwSize = WzToSz(pszwWideString, NULL, 0);
|
|
|
|
CMASSERTMSG((0 != dwSize), TEXT("WzToSzWithAlloc -- First WzToSz Failed."));
|
|
|
|
if (0 != dwSize)
|
|
{
|
|
pszString = (LPSTR)CmMalloc(dwSize*sizeof(CHAR));
|
|
|
|
CMASSERTMSG(pszString, TEXT("WzToSzWithAlloc -- CmMalloc failed to alloc pszString."));
|
|
|
|
if (pszString)
|
|
{
|
|
if (!WzToSz(pszwWideString, pszString, dwSize))
|
|
{
|
|
//
|
|
// Make sure to return a NULL string if we fail.
|
|
//
|
|
CMASSERTMSG(FALSE, TEXT("WzToSzWithAlloc -- Second WzToSz Failed."));
|
|
CmFree(pszString);
|
|
pszString = NULL;
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
//
|
|
// If this is a debug build then we want to take the Ansi string that we are
|
|
// going to return, convert it to Unicode and compare it to the original Unicode
|
|
// string passed in.
|
|
//
|
|
LPWSTR pszwString;
|
|
dwSize = SzToWz(pszString, NULL, 0);
|
|
|
|
if (0 != dwSize)
|
|
{
|
|
pszwString = (LPWSTR)CmMalloc(dwSize*sizeof(WCHAR));
|
|
|
|
CMASSERTMSG(pszwString, TEXT("WzToSzWithAlloc -- conversion of return value back to original Ansi string failed. Unable to allocate memory."));
|
|
|
|
if (pszwString)
|
|
{
|
|
if (SzToWz(pszString, pszwString, dwSize))
|
|
{
|
|
MYDBGASSERT(0 == lstrcmpU(pszwString, pszwWideString));
|
|
}
|
|
else
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("WzToSzWithAlloc -- conversion of return value back to original Ansi string failed."));
|
|
}
|
|
CmFree(pszwString);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("WzToSzWithAlloc -- conversion of return value back to original Ansi string failed. Unable to properly size the string."));
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
return pszString;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrTrimA
|
|
//
|
|
// Synopsis: Helper function to trim leading and trailing blanks from a
|
|
// string
|
|
//
|
|
// Arguments: LPTSTR pszStr - The string to be trimmed
|
|
//
|
|
// Returns: void WINAPI - Nothing
|
|
//
|
|
// History: nickball Created Header 3/11/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI void WINAPI CmStrTrimA(LPSTR pszStr)
|
|
{
|
|
//
|
|
// first, skip all the spaces at the begining of the string
|
|
//
|
|
MYDBGASSERT(pszStr);
|
|
|
|
if (pszStr)
|
|
{
|
|
LPSTR pszTmp = pszStr;
|
|
|
|
while (CmIsSpaceA(pszTmp))
|
|
{
|
|
pszTmp = CharNextA(pszTmp);
|
|
}
|
|
|
|
if (pszTmp != pszStr)
|
|
{
|
|
CmMoveMemory(pszStr, pszTmp, lstrlenA(pszTmp)+1);
|
|
}
|
|
|
|
//
|
|
// secondly, delete all the spaces at the end of the string
|
|
//
|
|
|
|
pszTmp = CmEndOfStrA(pszStr);
|
|
while (pszTmp != pszStr)
|
|
{
|
|
pszTmp = CharPrevA(pszStr, pszTmp);
|
|
if (!CmIsSpaceA(pszTmp))
|
|
{
|
|
break;
|
|
}
|
|
*pszTmp = TEXT('\0');
|
|
}
|
|
}
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrTrimW
|
|
//
|
|
// Synopsis: Helper function to trim leading and trailing blanks from a
|
|
// string.
|
|
//
|
|
// Arguments: LPTSTR pszStr - The string to be trimmed
|
|
//
|
|
// Returns: void WINAPI - Nothing
|
|
//
|
|
// History: quintinb Created 2/27/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI void WINAPI CmStrTrimW(LPWSTR pszStr)
|
|
{
|
|
//
|
|
// first, skip all the spaces at the begining of the string
|
|
//
|
|
|
|
MYDBGASSERT(pszStr);
|
|
|
|
if (pszStr)
|
|
{
|
|
LPWSTR pszTmp = pszStr;
|
|
|
|
while (CmIsSpaceW(pszTmp))
|
|
{
|
|
pszTmp = CharNextU(pszTmp);
|
|
}
|
|
|
|
if (pszTmp != pszStr)
|
|
{
|
|
CmMoveMemory(pszStr, pszTmp, (lstrlenU(pszTmp)+1)*sizeof(WCHAR));
|
|
}
|
|
|
|
//
|
|
// secondly, delete all the spaces at the end of the string
|
|
//
|
|
|
|
pszTmp = CmEndOfStrW(pszStr);
|
|
|
|
while (pszTmp != pszStr)
|
|
{
|
|
pszTmp = CharPrevU(pszStr, pszTmp);
|
|
|
|
if (!CmIsSpaceW(pszTmp))
|
|
{
|
|
break;
|
|
}
|
|
|
|
*pszTmp = TEXT('\0');
|
|
}
|
|
}
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmIsSpaceA
|
|
//
|
|
// Synopsis: Checks to see if the char is a space. Note that spaces, new line chars,
|
|
// line feed chars, tabs, and most other forms of whitespace are considered
|
|
// spaces.
|
|
//
|
|
// Arguments: psz - an ansi or dbcs char
|
|
//
|
|
// Returns: TRUE or FALSE
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI BOOL WINAPI CmIsSpaceA(LPSTR psz)
|
|
{
|
|
WORD wType = 0;
|
|
|
|
MYDBGASSERT(psz);
|
|
|
|
if (psz)
|
|
{
|
|
if (IsDBCSLeadByte(*psz))
|
|
{
|
|
MYVERIFY(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
}
|
|
else
|
|
{
|
|
MYVERIFY(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
}
|
|
}
|
|
|
|
return (wType & C1_SPACE);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmIsSpaceW
|
|
//
|
|
// Synopsis: Checks to see if the char is a space. Note that spaces, new line chars,
|
|
// line feed chars, tabs, and most other forms of whitespace are considered
|
|
// spaces.
|
|
//
|
|
// Arguments: psz - pointer to a string
|
|
//
|
|
// Returns: TRUE or FALSE
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI BOOL WINAPI CmIsSpaceW(LPWSTR pszwStr)
|
|
{
|
|
WORD wType = 0;
|
|
LPWSTR pszwNextChar;
|
|
int iCharCount;
|
|
|
|
MYDBGASSERT(pszwStr);
|
|
|
|
if (pszwStr)
|
|
{
|
|
pszwNextChar = CharNextU(pszwStr);
|
|
|
|
iCharCount = (INT)(pszwNextChar - pszwStr);
|
|
|
|
if (0 == GetStringTypeExU(LOCALE_USER_DEFAULT, CT_CTYPE1, pszwStr, iCharCount, &wType))
|
|
{
|
|
CMTRACE3(TEXT("CmIsSpaceW -- GetStringTypeExW failed on %s, iCharCount is %d, GLE=%u"), pszwStr, iCharCount, GetLastError());
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return (wType & C1_SPACE);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmIsDigitA
|
|
//
|
|
// Synopsis: Checks to see if the char is a digit.
|
|
//
|
|
// Arguments: psz - an ansi or dbcs char
|
|
//
|
|
// Returns: TRUE or FALSE
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI BOOL WINAPI CmIsDigitA(LPSTR psz)
|
|
{
|
|
WORD wType = 0;
|
|
|
|
MYDBGASSERT(psz);
|
|
|
|
if (psz)
|
|
{
|
|
if (IsDBCSLeadByte(*psz))
|
|
{
|
|
MYVERIFY(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
|
|
}
|
|
else
|
|
{
|
|
MYVERIFY(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
|
|
}
|
|
}
|
|
|
|
return (wType & C1_DIGIT);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmIsDigitW
|
|
//
|
|
// Synopsis: Checks to see if the WCHAR is a digit.
|
|
//
|
|
// Arguments: pszwStr -- WCHAR string
|
|
//
|
|
// Returns: TRUE or FALSE
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI BOOL WINAPI CmIsDigitW(LPWSTR pszwStr)
|
|
{
|
|
WORD wType = 0;
|
|
LPWSTR pszwNextChar;
|
|
int iCharCount;
|
|
|
|
MYDBGASSERT(pszwStr);
|
|
|
|
if (pszwStr)
|
|
{
|
|
pszwNextChar = CharNextU(pszwStr);
|
|
|
|
iCharCount = (INT)(pszwNextChar - pszwStr);
|
|
|
|
if (0 == GetStringTypeExU(LOCALE_USER_DEFAULT, CT_CTYPE1, pszwStr, iCharCount, &wType))
|
|
{
|
|
CMTRACE1(TEXT("CmIsDigitW -- GetStringTypeExU failed, GLE=%u"), GetLastError());
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return (wType & C1_DIGIT);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmEndOfStrA
|
|
//
|
|
// Synopsis: Given a string, returns the ptr to the end of the string(null char).
|
|
//
|
|
// Arguments: psz - an ansi or dbcs char
|
|
//
|
|
// Returns: LPSTR ptr to null char
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPSTR WINAPI CmEndOfStrA(LPSTR psz)
|
|
{
|
|
MYDBGASSERT(psz);
|
|
|
|
if (psz)
|
|
{
|
|
while (*psz)
|
|
{
|
|
psz = CharNextA(psz);
|
|
}
|
|
}
|
|
|
|
return psz;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmEndOfStrW
|
|
//
|
|
// Synopsis: Given a string, returns the ptr to the end of the string(null char).
|
|
//
|
|
// Arguments: pszwStr - a WCHAR
|
|
//
|
|
// Returns: LPWSTR ptr to null char
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPWSTR WINAPI CmEndOfStrW(LPWSTR pszwStr)
|
|
{
|
|
MYDBGASSERT(pszwStr);
|
|
|
|
if (pszwStr)
|
|
{
|
|
while (*pszwStr)
|
|
{
|
|
pszwStr = CharNextU(pszwStr);
|
|
}
|
|
}
|
|
|
|
return pszwStr;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrCpyAllocA
|
|
//
|
|
// Synopsis: Copies pszSrc into a newly allocated buffer (using CmMalloc) and
|
|
// returns the buffer to its caller who is responsible for freeing
|
|
// the buffer.
|
|
//
|
|
// Arguments: LPCSTR pszSrc - source string
|
|
//
|
|
// Returns: LPSTR - returns NULL if pszSrc is NULL or the Alloc fails,
|
|
// otherwise it returns the newly allocated buffer with
|
|
// a copy of pszSrc in it.
|
|
//
|
|
// History: quintinb Created Header and changed name to include Alloc 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPSTR CmStrCpyAllocA(LPCSTR pszSrc)
|
|
{
|
|
LPSTR pszBuffer = NULL;
|
|
|
|
if (pszSrc)
|
|
{
|
|
pszBuffer = (LPSTR) CmMalloc(lstrlenA(pszSrc) + 1);
|
|
|
|
if (pszBuffer)
|
|
{
|
|
lstrcpyA(pszBuffer, pszSrc);
|
|
}
|
|
}
|
|
|
|
return (pszBuffer);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrCpyAllocW
|
|
//
|
|
// Synopsis: Copies pszSrc into a newly allocated buffer (using CmMalloc) and
|
|
// returns the buffer to its caller who is responsible for freeing
|
|
// the buffer.
|
|
//
|
|
// Arguments: LPCSTR pszSrc - source string
|
|
//
|
|
// Returns: LPSTR - returns NULL if pszSrc is NULL or the Alloc fails,
|
|
// otherwise it returns the newly allocated buffer with
|
|
// a copy of pszSrc in it.
|
|
//
|
|
// History: quintinb Created Header and changed name to include Alloc 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPWSTR CmStrCpyAllocW(LPCWSTR pszSrc)
|
|
{
|
|
LPWSTR pszBuffer = NULL;
|
|
|
|
if (pszSrc)
|
|
{
|
|
size_t nLen = lstrlenU(pszSrc) + 1;
|
|
|
|
pszBuffer = (LPWSTR) CmMalloc(nLen*sizeof(WCHAR));
|
|
|
|
if (pszBuffer)
|
|
{
|
|
lstrcpyU(pszBuffer, pszSrc);
|
|
}
|
|
}
|
|
|
|
return (pszBuffer);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrCatAllocA
|
|
//
|
|
// Synopsis: This function reallocs the passed in string to a size large enough
|
|
// to hold the original data and the concatenates the new string onto
|
|
// the original string.
|
|
//
|
|
// Arguments: LPSTR *ppszDst - original string
|
|
// LPCSTR pszSrc - new piece of string to concatenate
|
|
//
|
|
// Returns: LPSTR - pointer to the concatenated string
|
|
//
|
|
// History: quintinb Created Header 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPSTR CmStrCatAllocA(LPSTR *ppszDst, LPCSTR pszSrc)
|
|
{
|
|
if (!ppszDst)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (pszSrc && *pszSrc)
|
|
{
|
|
DWORD dwSize = (lstrlenA(*ppszDst) + lstrlenA(pszSrc) + 1);
|
|
LPSTR pszTmp = (LPSTR)CmRealloc((LPVOID)*ppszDst, dwSize);
|
|
|
|
if (NULL != pszTmp)
|
|
{
|
|
lstrcatA(pszTmp, pszSrc);
|
|
*ppszDst = pszTmp;
|
|
}
|
|
}
|
|
|
|
return (*ppszDst);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrCatAllocW
|
|
//
|
|
// Synopsis: This function reallocs the passed in string to a size large enough
|
|
// to hold the original data and the concatenates the new string onto
|
|
// the original string.
|
|
//
|
|
// Arguments: LPWSTR *ppszDst - original string
|
|
// LPCWSTR pszSrc - new piece of string to concatenate
|
|
//
|
|
// Returns: LPWSTR - pointer to the concatenated string
|
|
//
|
|
// History: quintinb Created Header 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPWSTR CmStrCatAllocW(LPWSTR *ppszDst, LPCWSTR pszSrc)
|
|
{
|
|
if (!ppszDst)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (pszSrc && *pszSrc)
|
|
{
|
|
DWORD dwSize = (lstrlenU(*ppszDst) + lstrlenU(pszSrc) + 1)*sizeof(WCHAR);
|
|
LPWSTR pszTmp = (LPWSTR)CmRealloc((LPVOID)*ppszDst, dwSize);
|
|
|
|
if (NULL != pszTmp)
|
|
{
|
|
lstrcatU(pszTmp, pszSrc);
|
|
*ppszDst = pszTmp;
|
|
}
|
|
}
|
|
|
|
return (*ppszDst);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrchrA
|
|
//
|
|
// Synopsis: This function returns the first occurence of ch in the string pszString.
|
|
//
|
|
// Arguments: LPCSTR pszString - String to search in
|
|
// CHAR ch - character to look for
|
|
//
|
|
// Returns: LPSTR - pointer to the first occurence of the Character ch in pszString
|
|
//
|
|
// History: quintinb Created Header 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPSTR WINAPI CmStrchrA(LPCSTR pszString, const char ch)
|
|
{
|
|
LPSTR pszTmp = (LPSTR)pszString;
|
|
|
|
if (NULL == pszTmp)
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("CmStrchr - NULL pointer passed"));
|
|
return NULL;
|
|
}
|
|
|
|
while (*pszTmp && (*pszTmp != ch))
|
|
{
|
|
pszTmp = CharNextA(pszTmp);
|
|
}
|
|
|
|
if (*pszTmp == ch)
|
|
{
|
|
return pszTmp;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrchrW
|
|
//
|
|
// Synopsis: This function returns the first occurence of ch in the string pszString.
|
|
//
|
|
// Arguments: LPCWSTR pszString - String to search in
|
|
// WCHAR ch - character to look for
|
|
//
|
|
// Returns: LPWSTR - pointer to the first occurence of the Character ch in pszString
|
|
//
|
|
// History: quintinb Created Header 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPWSTR WINAPI CmStrchrW(LPCWSTR pszString, const WCHAR ch)
|
|
{
|
|
LPWSTR pszTmp = (LPWSTR)pszString;
|
|
|
|
if (NULL == pszTmp)
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("CmStrchr - NULL pointer passed"));
|
|
return NULL;
|
|
}
|
|
|
|
while (*pszTmp && (*pszTmp != ch))
|
|
{
|
|
pszTmp = CharNextU(pszTmp);
|
|
}
|
|
|
|
if (*pszTmp == ch)
|
|
{
|
|
return pszTmp;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrrchrA
|
|
//
|
|
// Synopsis: Find the last occurence of a character in a string
|
|
//
|
|
// Arguments: LPCSTR pszString - string to search in
|
|
// CHAR ch - character to look for
|
|
//
|
|
// Returns: LPSTR - NULL if the char is not found, a pointer to the char in
|
|
// the string otherwise
|
|
//
|
|
// History: quintinb Created Header and cleaned up 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPSTR CmStrrchrA (LPCSTR pszString, const char ch)
|
|
{
|
|
LPSTR pszTmp = NULL;
|
|
LPSTR pszCurrent = (LPSTR)pszString;
|
|
|
|
if (NULL == pszString)
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("CmStrrchr - NULL pointer passed"));
|
|
}
|
|
else
|
|
{
|
|
while (TEXT('\0') != *pszCurrent)
|
|
{
|
|
if (ch == (*pszCurrent))
|
|
{
|
|
pszTmp = pszCurrent;
|
|
}
|
|
pszCurrent = CharNextA(pszCurrent);
|
|
}
|
|
}
|
|
|
|
return pszTmp;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrrchrW
|
|
//
|
|
// Synopsis: Find the last occurence of a character in a string
|
|
//
|
|
// Arguments: LPCWSTR pszString - string to search in
|
|
// WCHAR ch - character to look for
|
|
//
|
|
// Returns: LPWSTR - NULL if the char is not found, a pointer to the char in
|
|
// the string otherwise
|
|
//
|
|
// History: quintinb Created Header and cleaned up 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPWSTR CmStrrchrW (LPCWSTR pszString, const WCHAR ch)
|
|
{
|
|
LPWSTR pszTmp = NULL;
|
|
LPWSTR pszCurrent = (LPWSTR)pszString;
|
|
|
|
if (NULL == pszString)
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("CmStrrchr - NULL pointer passed"));
|
|
}
|
|
else
|
|
{
|
|
while (TEXT('\0') != *pszCurrent)
|
|
{
|
|
if (ch == (*pszCurrent))
|
|
{
|
|
pszTmp = pszCurrent;
|
|
}
|
|
pszCurrent = CharNextU(pszCurrent);
|
|
}
|
|
}
|
|
|
|
return pszTmp;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrtokA
|
|
//
|
|
// Synopsis: CM implementation of strtok
|
|
//
|
|
// Arguments: LPSTR pszStr - string to tokenize or NULL if getting a second token
|
|
// LPCSTR pszControl - set of token chars
|
|
//
|
|
// Returns: LPSTR - NULL if no token could be found or a pointer to a token string.
|
|
//
|
|
// History: quintinb Created Header and cleaned up for UNICODE conversion 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPSTR CmStrtokA(LPSTR pszStr, LPCSTR pszControl)
|
|
{
|
|
LPSTR pszToken;
|
|
LPSTR pszTmpStr;
|
|
LPCSTR pszTmpCtl;
|
|
LPSTR pszTmpDelim;
|
|
|
|
|
|
//
|
|
// If the pszStr param is NULL, then we need to retrieve the stored string
|
|
//
|
|
if (NULL != pszStr)
|
|
{
|
|
pszTmpStr = pszStr;
|
|
}
|
|
else
|
|
{
|
|
pszTmpStr = (LPSTR)TlsGetValue(g_dwTlsIndex);
|
|
}
|
|
|
|
//
|
|
// Find beginning of token (skip over leading delimiters). Note that
|
|
// there is no token if this loop sets string to point to the terminal
|
|
// null (*string == '\0')
|
|
//
|
|
while (*pszTmpStr)
|
|
{
|
|
for (pszTmpCtl = pszControl; *pszTmpCtl && *pszTmpCtl != *pszTmpStr;
|
|
pszTmpCtl = CharNextA(pszTmpCtl))
|
|
{
|
|
; // do nothing
|
|
}
|
|
|
|
if (!*pszTmpCtl)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pszTmpStr = CharNextA(pszTmpStr);
|
|
}
|
|
|
|
pszToken = pszTmpStr;
|
|
|
|
//
|
|
// Find the end of the token. If it is not the end of the string,
|
|
// put a null there.
|
|
//
|
|
for ( ; *pszTmpStr ; pszTmpStr = CharNextA(pszTmpStr))
|
|
{
|
|
for (pszTmpCtl = pszControl; *pszTmpCtl && *pszTmpCtl != *pszTmpStr;
|
|
pszTmpCtl = CharNextA(pszTmpCtl))
|
|
{
|
|
; // Do nothing
|
|
}
|
|
|
|
if (*pszTmpCtl)
|
|
{
|
|
pszTmpDelim = pszTmpStr;
|
|
pszTmpStr = CharNextA(pszTmpStr);
|
|
*pszTmpDelim = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update nextoken (or the corresponding field in the per-thread data structure
|
|
//
|
|
TlsSetValue(g_dwTlsIndex, (LPVOID)pszTmpStr);
|
|
|
|
//
|
|
// Determine if a token has been found.
|
|
//
|
|
if (pszToken == pszTmpStr)
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return pszToken;
|
|
}
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrtokW
|
|
//
|
|
// Synopsis: CM implementation of strtok
|
|
//
|
|
// Arguments: LPWSTR pszStr - string to tokenize or NULL if getting a second tokey
|
|
// LPCWSTR pszControl - set of token chars
|
|
//
|
|
// Returns: LPWSTR - NULL if no token could be found or a pointer to a token string.
|
|
//
|
|
// History: quintinb Created Header and cleaned up for UNICODE conversion 4/9/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPWSTR CmStrtokW(LPWSTR pszStr, LPCWSTR pszControl)
|
|
{
|
|
LPWSTR pszToken;
|
|
LPWSTR pszTmpStr;
|
|
LPWSTR pszTmpCtl;
|
|
LPWSTR pszTmpDelim;
|
|
|
|
//
|
|
// If the pszStr param is NULL, then we need to retrieve the stored string
|
|
//
|
|
if (NULL != pszStr)
|
|
{
|
|
pszTmpStr = pszStr;
|
|
}
|
|
else
|
|
{
|
|
pszTmpStr = (LPWSTR)TlsGetValue(g_dwTlsIndex);
|
|
}
|
|
|
|
//
|
|
// Find beginning of token (skip over leading delimiters). Note that
|
|
// there is no token iff this loop sets string to point to the terminal
|
|
// null (*string == '\0')
|
|
//
|
|
while (*pszTmpStr)
|
|
{
|
|
for (pszTmpCtl = (LPWSTR)pszControl; *pszTmpCtl && *pszTmpCtl != *pszTmpStr;
|
|
pszTmpCtl = CharNextU(pszTmpCtl))
|
|
{
|
|
; // do nothing
|
|
}
|
|
|
|
if (!*pszTmpCtl)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pszTmpStr = CharNextU(pszTmpStr);
|
|
}
|
|
|
|
pszToken = pszTmpStr;
|
|
|
|
//
|
|
// Find the end of the token. If it is not the end of the string,
|
|
// put a null there.
|
|
//
|
|
for ( ; *pszTmpStr ; pszTmpStr = CharNextU(pszTmpStr))
|
|
{
|
|
for (pszTmpCtl = (LPWSTR)pszControl; *pszTmpCtl && *pszTmpCtl != *pszTmpStr;
|
|
pszTmpCtl = CharNextU(pszTmpCtl))
|
|
{
|
|
; // Do nothing
|
|
}
|
|
|
|
if (*pszTmpCtl)
|
|
{
|
|
pszTmpDelim = pszTmpStr;
|
|
pszTmpStr = CharNextU(pszTmpStr);
|
|
*pszTmpDelim = L'\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update nextoken (or the corresponding field in the per-thread data structure
|
|
//
|
|
TlsSetValue(g_dwTlsIndex, (LPVOID)pszTmpStr);
|
|
|
|
//
|
|
// Determine if a token has been found.
|
|
//
|
|
if (pszToken == pszTmpStr)
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return pszToken;
|
|
}
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrStrA
|
|
//
|
|
// Synopsis: Simple replacement for StrStr from C runtime
|
|
//
|
|
// Arguments: LPCTSTR pszString - The string to search in
|
|
// LPCTSTR pszSubString - The string to search for
|
|
//
|
|
// Returns: LPTSTR - Ptr to the first occurence of pszSubString in pszString.
|
|
// NULL if pszSubString does not occur in pszString
|
|
//
|
|
//
|
|
// History: nickball Created Header 04/01/98
|
|
// nickball Added ptr check 02/21/99
|
|
// quintinb rewrote for unicode conversion 04/08/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPSTR CmStrStrA(LPCSTR pszString, LPCSTR pszSubString)
|
|
{
|
|
//
|
|
// Check the inputs
|
|
//
|
|
MYDBGASSERT(pszString);
|
|
MYDBGASSERT(pszSubString);
|
|
|
|
if (NULL == pszSubString || NULL == pszString)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Check to make sure we have something to look for
|
|
//
|
|
if (TEXT('\0') == pszSubString[0])
|
|
{
|
|
return((LPSTR)pszString);
|
|
}
|
|
|
|
//
|
|
// Okay, start looking for the string
|
|
//
|
|
LPSTR pszCurrent = (LPSTR)pszString;
|
|
LPSTR pszTmp1;
|
|
LPSTR pszTmp2;
|
|
|
|
while (*pszCurrent)
|
|
{
|
|
pszTmp1 = pszCurrent;
|
|
pszTmp2 = (LPSTR) pszSubString;
|
|
|
|
while (*pszTmp1 && *pszTmp2 && ((*pszTmp1) == (*pszTmp2)))
|
|
{
|
|
pszTmp1 = CharNextA(pszTmp1);
|
|
pszTmp2 = CharNextA(pszTmp2);
|
|
}
|
|
|
|
if (TEXT('\0') == *pszTmp2)
|
|
{
|
|
return pszCurrent;
|
|
}
|
|
|
|
pszCurrent = CharNextA(pszCurrent);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmStrStrW
|
|
//
|
|
// Synopsis: Simple replacement for StrStr from C runtime
|
|
//
|
|
// Arguments: LPCTSTR pszString - The string to search in
|
|
// LPCTSTR pszSubString - The string to search for
|
|
//
|
|
// Returns: LPTSTR - Ptr to the first occurence of pszSubString in pszString.
|
|
// NULL if pszSubString does not occur in pszString
|
|
//
|
|
//
|
|
// History: nickball Created Header 04/01/98
|
|
// nickball Added ptr check 02/21/99
|
|
// quintinb rewrote for unicode conversion 04/08/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI LPWSTR CmStrStrW(LPCWSTR pszString, LPCWSTR pszSubString)
|
|
{
|
|
|
|
//
|
|
// Check the inputs
|
|
//
|
|
MYDBGASSERT(pszString);
|
|
MYDBGASSERT(pszSubString);
|
|
|
|
if (NULL == pszSubString || NULL == pszString)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Check to make sure we have something to look for
|
|
//
|
|
if (TEXT('\0') == pszSubString[0])
|
|
{
|
|
return((LPWSTR)pszString);
|
|
}
|
|
|
|
//
|
|
// Okay, start looking for the string
|
|
//
|
|
LPWSTR pszCurrent = (LPWSTR)pszString;
|
|
LPWSTR pszTmp1;
|
|
LPWSTR pszTmp2;
|
|
|
|
while (*pszCurrent)
|
|
{
|
|
pszTmp1 = pszCurrent;
|
|
pszTmp2 = (LPWSTR) pszSubString;
|
|
|
|
while (*pszTmp1 && *pszTmp2 && ((*pszTmp1) == (*pszTmp2)))
|
|
{
|
|
pszTmp1 = CharNextU(pszTmp1);
|
|
pszTmp2 = CharNextU(pszTmp2);
|
|
}
|
|
|
|
if (TEXT('\0') == *pszTmp2)
|
|
{
|
|
return pszCurrent;
|
|
}
|
|
|
|
pszCurrent = CharNextU(pszCurrent);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmCompareStringA
|
|
//
|
|
// Synopsis: redirected to function in CompareString.cpp
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI int CmCompareStringA(LPCSTR lpString1, LPCSTR lpString2)
|
|
{
|
|
return SafeCompareStringA(lpString1, lpString2);
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: CmCompareStringW
|
|
//
|
|
// Synopsis: redirected to function in CompareString.cpp
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
CMUTILAPI int CmCompareStringW(LPCWSTR lpString1, LPCWSTR lpString2)
|
|
{
|
|
return SafeCompareStringW(lpString1, lpString2);
|
|
}
|