windows-nt/Source/XPSP1/NT/enduser/windows.com/lib/util/stringutil.cpp
2020-09-26 16:20:57 +08:00

396 lines
9 KiB
C++

//=======================================================================
//
// Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
//
// File: StringUtil.CPP
//
// Description:
//
// IU string utility library
//
//=======================================================================
#include <windows.h>
#include <tchar.h>
#include <stringutil.h>
#include <memutil.h>
#include <shlwapi.h>
#include<iucommon.h>
#include<MISTSAFE.h>
#define IfNullReturnNull(ptr) if (NULL == ptr) return NULL;
// ----------------------------------------------------------------------
//
// Public function StrChr() - same as shlwapi StrChr()
// Searches a string for the first occurrence of a character that
// matches the specified character. The comparison is case sensitive.
//
// Input:
// lpStart - Address of the string to be searched
// wMatch - Character to be used for comparison
//
// Return:
// Returns the address of the first occurrence of the character in
// the string if successful, or NULL otherwise.
//
// ----------------------------------------------------------------------
LPCTSTR MyStrChr(LPCTSTR lpStart, const TCHAR wMatch)
{
LPCTSTR lpPtr = lpStart;
IfNullReturnNull(lpStart);
while (_T('\0') != *lpPtr && wMatch != *lpPtr)
{
lpPtr = CharNext(lpPtr);
}
return (_T('\0') != *lpPtr) ? lpPtr : NULL;
}
// ----------------------------------------------------------------------
//
// Public function StrRChr() - same as shlwapi StrRChr()
// Searches a string for the last occurrence of a character that
// matches the specified character. The comparison is case sensitive.
//
// Input:
// lpStart - Address of the string to be searched
// lpEnd - Address of the end of the string (NOT included in the search)
// wMatch - Character to be used for comparison
//
// Return:
// Returns the address of the last occurrence of the character in
// the string if successful, or NULL otherwise.
//
// ----------------------------------------------------------------------
LPCTSTR MyStrRChr(LPCTSTR lpStart, LPCTSTR lpEnd, const TCHAR wMatch)
{
LPCTSTR lpFound = NULL;
IfNullReturnNull(lpStart);
if (NULL == lpEnd)
lpEnd = lpStart + lstrlen(lpStart);
LPCTSTR lpPtr = lpEnd;
while (lpPtr > lpStart)
{
if (*lpPtr == wMatch)
break;
lpPtr = CharPrev(lpStart, lpPtr);
}
if (lpStart == lpPtr)
{
return (*lpStart == wMatch) ? lpStart : NULL;
}
else
{
return (lpPtr > lpStart) ? lpPtr : NULL;
}
}
// ----------------------------------------------------------------------
//
// Public function StrChrI() - same as shlwapi StrChrI()
// Searches a string for the first occurrence of a character that
// matches the specified character. The comparison is case INsensitive.
//
// Input:
// lpStart - Address of the string to be searched
// wMatch - Character to be used for comparison
//
// Return:
// Returns the address of the first occurrence of the character in
// the string if successful, or NULL otherwise.
//
// ----------------------------------------------------------------------
LPCTSTR MyStrChrI(LPCTSTR lpStart, const TCHAR wMatch)
{
LPCTSTR lpPtr;
LPTSTR lpBuffer;
DWORD dwLength;
HANDLE hHeap;
IfNullReturnNull(lpStart);
//
// get buffer to store search string
//
hHeap = GetProcessHeap();
dwLength = lstrlen(lpStart);
lpBuffer = (LPTSTR) HeapAlloc(
GetProcessHeap(),
0,
(dwLength + 1) * sizeof(TCHAR)
);
IfNullReturnNull(lpBuffer);
//
// copy the search string to buffer
//
//The buffer allocated is sufficient to hold the lpStart string.
StringCchCopyEx(lpBuffer,dwLength + 1,lpStart,NULL,NULL,MISTSAFE_STRING_FLAGS);
//
// based on the case of wMatch, determine how to convert
// the search string
//
if (IsCharUpper(wMatch))
{
CharUpperBuff(lpBuffer, dwLength);
}
else
{
CharLowerBuff(lpBuffer, dwLength);
}
//
// search the char in in new string
//
lpPtr = lpBuffer;
while (_T('\0') != *lpPtr && wMatch != *lpPtr)
{
lpPtr = CharNext(lpPtr);
}
//
// map the position to original string, if found.
//
lpPtr = (_T('\0') != *lpPtr) ? lpStart + (lpPtr - lpBuffer) : NULL;
HeapFree(hHeap, 0, lpBuffer);
return lpPtr;
}
// ----------------------------------------------------------------------
//
// Convert a long number content in bstr into long
// if error, 0 returned.
//
// ----------------------------------------------------------------------
LONG MyBSTR2L(BSTR bstrLongNumber)
{
USES_IU_CONVERSION;
LPTSTR lpszNumber = OLE2T(bstrLongNumber);
return StrToInt(lpszNumber);
}
// ----------------------------------------------------------------------
//
// Convert a a long number into bstr
//
// ----------------------------------------------------------------------
BSTR MyL2BSTR(LONG lNumber)
{
USES_IU_CONVERSION;
WCHAR sNumber[32];
StringCchPrintfExW(sNumber,ARRAYSIZE(sNumber),NULL,NULL,MISTSAFE_STRING_FLAGS,L"%ld", lNumber);
return SysAllocString(sNumber);
}
BSTR MyUL2BSTR(ULONG ulNumber)
{
USES_IU_CONVERSION;
WCHAR sNumber[32];
StringCchPrintfExW(sNumber,ARRAYSIZE(sNumber),NULL,NULL,MISTSAFE_STRING_FLAGS,L"%lu", ulNumber);
return SysAllocString(sNumber);
}
// ----------------------------------------------------------------------
//
// Compare a binary buffer with a string, where data in the string
// has format:
//
// <String> ::= <Number> [<Space><String>]
// <Space> ::= TCHAR(' ')
// <Number> ::= 0x<HexValue>|x<HexValue>|<Decimal>
// <Decimal> ::= +<DecimalValue>|-<DecimalValue>
// <DecimalValue> ::= <DecimalDigit>|<DecimalDigit><DecimalValue>
// <DecimalDegit> ::= 0|1|2|3|4|5|6|7|8|9
// <HexValue> ::= <HexDigit>|<HexDigit><HexDigit>
// <HexDigit> ::= <DecimalDigit>|A|B|C|D|E|F
//
// example of strings that this function recognize:
// "12 0 45 0x1F"
//
// Return: similar to lstrcmp() API, each byte is compared
// as unsigned short
// if binary > string, +1
// if binary = string, 0
// if binary < string, -1
//
// Note:
// If the string is shorter than binary buffer, i.e., string contains
// less byte data than the binary buffer contain, we only compare till
// the number of bytes provided by the string offered.
// This request is based on the fact that many v3 data has reg value
// as DWORD but the update created the value with type binary. so for
// string data, e.g., it's "1", for binary data, it's "01 00 00 00" for
// 4 bytes, this function will return 0 meaning equality, per request
// from aavon for bug 364085 in Whistler RAID.
//
// ----------------------------------------------------------------------
int CmpBinaryToString(
LPBYTE pBinaryBuffer, // buffer to contain binary data
UINT nBinarySize, // number of bytes this binary has data
LPCTSTR pstrValue // string contains data to compare
)
{
int rc = 0;
int iNumber;
UINT nCharCount = nBinarySize;
LPCTSTR lpNumber = pstrValue;
if (NULL == pBinaryBuffer)
{
if (NULL == pstrValue)
{
return 0; // both NULL
}
nBinarySize = 0; // make sure
}
if (NULL == pstrValue || _T('\0') == *pstrValue)
{
//
// this is the case that binary not null,
// but string null.
// as of lstrcmp(), string 1 > string 2
//
return +1;
}
while (nBinarySize > 0)
{
if (NULL == lpNumber || _T('\0') == *lpNumber)
{
//
// when binary not done, string done, we don't care the left binary
//
return 0;
}
if (!StrToIntEx(lpNumber, STIF_SUPPORT_HEX, &iNumber) ||
iNumber < 0 ||
iNumber > 255)
{
//
// found un-convertable number in the
// string. or the number if out of range
// of a byte, treat it invalid, so the
// binary win
//
iNumber = 0x0;
}
if ((unsigned short)pBinaryBuffer[nCharCount - nBinarySize] > (unsigned short) iNumber)
{
return +1;
}
else if ((unsigned short)pBinaryBuffer[nCharCount - nBinarySize] < (unsigned short) iNumber)
{
//
// binary is smaller
//
return -1;
}
//
// if equal, continue to compare next byte
//
nBinarySize--;
//
// skip the white spaces before this number
//
while (_T('\0') != *lpNumber &&
(_T(' ') == *lpNumber ||
_T('\t') == *lpNumber ||
_T('\r') == *lpNumber ||
_T('\n') == *lpNumber)) lpNumber++;
//
// try to find the beginning of the next number
//
lpNumber = StrChr(lpNumber, _T(' '));
}
//
// these two parameters point to data having same meaning
//
return 0;
}
/*
* FUNCTION: int atoh(char *ptr)
*
* PURPOSE: This function converts an hexadecimal string into it's decimal value.
*
* PARAMETERS:
*
* char *ptr: pointer to string to be converted
*
* RETURNS: The converted value.
*
* COMMENTS: Like atoi this function ends the conversion on the first innvalid
* hex digit.
*
*/
int atoh(LPCSTR ptr)
{
int i = 0;
char ch;
//skip 0x if present
if (NULL == ptr) return 0;
if ( ptr[0] == '0') ptr++;
if ( ptr[0] == 'x' || ptr[0] == 'X') ptr++;
while( 1 )
{
ch = (char)toupper(*ptr);
if ( (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') )
{
ch -= '0';
if ( ch > 10 )
ch -= 7;
i *= 16;
i += (int)ch;
ptr++;
continue;
}
break;
}
return i;
}