Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

626 lines
14 KiB

/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
WSTRING.CPP
Abstract:
Utility string class
History:
a-raymcc 30-May-96 Created.
a-dcrews 16-Mar-99 Added out-of-memory exception handling
--*/
#include "precomp.h"
#include <stdio.h>
#include <wstring.h>
#include <corex.h>
static wchar_t g_szNullString[1] = {0};
/*inline*/ void WString::DeleteString(wchar_t *pStr)
{
if (pStr != g_szNullString)
delete [] pStr;
}
WString::WString()
{
m_pString = g_szNullString;
}
WString::WString(wchar_t *pSrc, BOOL bAcquire)
{
if (bAcquire) {
m_pString = pSrc;
if (m_pString == 0)
m_pString = g_szNullString;
return;
}
if (pSrc == 0) {
m_pString = g_szNullString;
return;
}
m_pString = new wchar_t[wcslen(pSrc) + 1];
// Watch for allocation failures
if ( NULL == m_pString )
{
throw CX_MemoryException();
}
wcscpy(m_pString, pSrc);
}
WString::WString(DWORD dwResourceID, HMODULE hMod)
{
int iSize = 100;
BOOL bNotDone = TRUE;
TCHAR* pTemp = NULL;
// load the string from the string table. Since we dont know what size, try increasing the
// buffer till it works, or until the clearly obsurd case is hit
while (iSize < 10240)
{
pTemp = new TCHAR [iSize];
// Watch for allocation failures
if ( NULL == pTemp )
{
throw CX_MemoryException();
}
int iRead = LoadString(hMod, dwResourceID, pTemp, iSize);
if(iRead == 0)
{
// Bad string
m_pString = g_szNullString;
delete [] pTemp;
return;
}
if(iRead +1 < iSize)
break; // all is well;
iSize += 100; // Try again
delete [] pTemp;
pTemp = NULL;
}
#ifdef UNICODE
//For unicode, this is the string we need!
m_pString = pTemp;
#else
//Only have to convert if we are not using unicode, otherwise it is already in wide mode!
if(pTemp)
{
// got a narrow string, allocate a large string buffer and convert
long len = mbstowcs(NULL, pTemp, lstrlen(pTemp)+1) + 1;
m_pString = new wchar_t[len];
// Watch for allocation failures
if ( NULL == m_pString )
{
delete [] pTemp;
throw CX_MemoryException();
}
mbstowcs(m_pString, pTemp, lstrlen(pTemp)+1);
delete [] pTemp;
}
else
m_pString = g_szNullString;
#endif
}
WString::WString(const wchar_t *pSrc)
{
if (pSrc == 0) {
m_pString = g_szNullString;
return;
}
m_pString = new wchar_t[wcslen(pSrc) + 1];
// Watch for allocation failures
if ( NULL == m_pString )
{
throw CX_MemoryException();
}
wcscpy(m_pString, pSrc);
}
WString::WString(const char *pSrc)
{
m_pString = new wchar_t[strlen(pSrc) + 1];
// Watch for allocation failures
if ( NULL == m_pString )
{
throw CX_MemoryException();
}
mbstowcs(m_pString, pSrc, strlen(pSrc) + 1);
// swprintf(m_pString, L"%S", pSrc);
}
LPSTR WString::GetLPSTR() const
{
long len = 2*(wcslen(m_pString) + 1);
char *pTmp = new char[len];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
wcstombs(pTmp, m_pString, len);
// sprintf(pTmp, "%S", m_pString);
return pTmp;
}
WString& WString::operator =(const WString &Src)
{
DeleteString(m_pString);
m_pString = new wchar_t[wcslen(Src.m_pString) + 1];
// Watch for allocation failures
if ( NULL == m_pString )
{
throw CX_MemoryException();
}
wcscpy(m_pString, Src.m_pString);
return *this;
}
WString& WString::operator =(LPCWSTR pSrc)
{
DeleteString(m_pString);
m_pString = new wchar_t[wcslen(pSrc) + 1];
// Watch for allocation failures
if ( NULL == m_pString )
{
throw CX_MemoryException();
}
wcscpy(m_pString, pSrc);
return *this;
}
WString& WString::operator +=(const wchar_t *pOther)
{
wchar_t *pTmp = new wchar_t[wcslen(m_pString) +
wcslen(pOther) + 1];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
wcscpy(pTmp, m_pString);
wcscat(pTmp, pOther);
DeleteString(m_pString);
m_pString = pTmp;
return *this;
}
WString& WString::operator +=(wchar_t NewChar)
{
wchar_t Copy[2];
Copy[0] = NewChar;
Copy[1] = 0;
wchar_t *pTmp = new wchar_t[wcslen(m_pString) + 2];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
wcscpy(pTmp, m_pString);
wcscat(pTmp, Copy);
DeleteString(m_pString);
m_pString = pTmp;
return *this;
}
WString& WString::operator +=(const WString &Other)
{
wchar_t *pTmp = new wchar_t[wcslen(m_pString) +
wcslen(Other.m_pString) + 1];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
wcscpy(pTmp, m_pString);
wcscat(pTmp, Other.m_pString);
DeleteString(m_pString);
m_pString = pTmp;
return *this;
}
wchar_t WString::operator[](int nIndex) const
{
if (nIndex >= (int) wcslen(m_pString))
return 0;
return m_pString[nIndex];
}
WString& WString::TruncAtRToken(wchar_t Token)
{
for (int i = (int) wcslen(m_pString); i >= 0; i--) {
wchar_t wc = m_pString[i];
m_pString[i] = 0;
if (wc == Token)
break;
}
return *this;
}
WString& WString::TruncAtLToken(wchar_t Token)
{
int nStrlen = wcslen(m_pString);
for (int i = 0; i < nStrlen ; i++)
{
if (Token == m_pString[i])
{
m_pString[i] = 0;
break;
}
}
return *this;
}
WString& WString::StripToToken(wchar_t Token, BOOL bIncludeToken)
{
int nStrlen = wcslen(m_pString);
wchar_t *pTmp = new wchar_t[nStrlen + 1];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
*pTmp = 0;
BOOL bFound = FALSE;
for (int i = 0; i < nStrlen; i++) {
if (m_pString[i] == Token) {
bFound = TRUE;
break;
}
}
if (!bFound)
{
delete [] pTmp;
return *this;
}
if (bIncludeToken) i++;
wcscpy(pTmp, &m_pString[i]);
DeleteString(m_pString);
m_pString = pTmp;
return *this;
}
LPWSTR WString::UnbindPtr()
{
if (m_pString == g_szNullString)
{
m_pString = new wchar_t[1];
// Watch for allocation failures
if ( NULL == m_pString )
{
throw CX_MemoryException();
}
*m_pString = 0;
}
wchar_t *pTmp = m_pString;
m_pString = g_szNullString;
return pTmp;
}
WString& WString::StripWs(int nType)
{
if (nType & leading)
{
wchar_t *pTmp = new wchar_t[wcslen(m_pString) + 1];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
int i = 0;
while (iswspace(m_pString[i]) && m_pString[i]) i++;
wcscpy(pTmp, &m_pString[i]);
DeleteString(m_pString);
m_pString = pTmp;
}
if (nType & trailing)
{
wchar_t *pCursor = m_pString + wcslen(m_pString) - 1;
while (pCursor >= m_pString && iswspace(*pCursor))
*pCursor-- = 0;
}
return *this;
}
wchar_t *WString::GetLToken(wchar_t Tok) const
{
wchar_t *pCursor = m_pString;
while (*pCursor && *pCursor != Tok) pCursor++;
if (*pCursor == Tok)
return pCursor;
return 0;
}
WString WString::operator()(int nLeft, int nRight) const
{
wchar_t *pTmp = new wchar_t[wcslen(m_pString) + 1];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
wchar_t *pCursor = pTmp;
for (int i = nLeft; i < (int) wcslen(m_pString) && i <= nRight; i++)
*pCursor++ = m_pString[i];
*pCursor = 0;
return WString(pTmp, TRUE);
}
BOOL WString::ExtractToken(const wchar_t * pDelimiters, WString &Extract)
{
if(pDelimiters == NULL)
{
Extract.Empty();
return FALSE;
}
// Find which character in the list works. Use the first if none are
// present
int nLen = wcslen(m_pString);
int nDimLen = wcslen(pDelimiters);
for (int i = 0; i < nLen; i++)
for(int j = 0; j < nDimLen; j++)
if (m_pString[i] == pDelimiters[j])
return ExtractToken(pDelimiters[j], Extract);
// If none were found, just use the first.
return ExtractToken(*pDelimiters, Extract);
}
BOOL WString::ExtractToken(wchar_t Delimiter, WString &Extract)
{
int i, i2;
BOOL bTokFound = FALSE;
Extract.Empty();
int nLen = wcslen(m_pString);
wchar_t *pTmp = new wchar_t[nLen + 1];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
for (i = 0; i < nLen; i++)
if (m_pString[i] == Delimiter) {
bTokFound = TRUE;
break;
}
else
pTmp[i] = m_pString[i];
pTmp[i] = 0;
Extract.BindPtr(pTmp);
// Now make *this refer to any leftover stuff.
// ===========================================
pTmp = new wchar_t[nLen - wcslen(pTmp) + 1];
// Watch for allocation failures
if ( NULL == pTmp )
{
throw CX_MemoryException();
}
*pTmp = 0;
for (i2 = 0, i++; i <= nLen; i++)
pTmp[i2++] = m_pString[i];
DeleteString(m_pString);
m_pString = pTmp;
// Return TRUE if the token was encountered, FALSE if not.
// =======================================================
return bTokFound;
}
void WString::Empty()
{
DeleteString(m_pString);
m_pString = g_szNullString;
}
static int _WildcardAux(const wchar_t *pszWildstr, const wchar_t *pszTargetstr,
int iGreedy)
{
enum { start, wild, strip } eState;
wchar_t cInput, cInputw, cLaToken;
if (!wcslen(pszTargetstr) || !wcslen(pszWildstr))
return 0;
for (eState = start;;)
switch (eState)
{
case start:
cInputw = *pszWildstr++; // wildcard input
cInput = *pszTargetstr; // target input
if (!cInputw) // at end of wildcard string?
goto EndScan;
// Check for wildcard chars first
if (cInputw == L'?') { // Simply strips both inputs
if (!cInput) // If end of input, error
return 0;
pszTargetstr++;
continue;
}
if (cInputw == L'*') {
eState = wild;
break;
}
// If here, an exact match is required.
if (cInput != cInputw)
return 0;
// Else remain in same state, since match succeeded
pszTargetstr++;
break;
case wild:
cLaToken = *pszWildstr++; // Establish the lookahead token
eState = strip;
break;
case strip:
cInput = *pszTargetstr;
if (cInput == cLaToken) {
if (!cInput) // Match on a NULL
goto EndScan;
++pszTargetstr;
// If there is another occurrence of the lookahead
// token in the string, and we are in greedy mode,
// stay in this state
if (!iGreedy)
eState = start;
if (!wcschr(pszTargetstr, cLaToken))
eState = start;
break;
}
if (cLaToken && !cInput) // End of input with a non-null la token
return 0;
++pszTargetstr; // Still stripping input
break;
}
// Here if the wildcard input is exhausted. If the
// target string is also empty, we have a match,
// otherwise not.
EndScan:
if (wcslen(pszTargetstr))
return 0;
return 1;
}
// Run the test both with greedy and non-greedy matching, allowing the
// greatest possible chance of a match.
BOOL WString::WildcardTest(const wchar_t *pszWildstr) const
{
return (_WildcardAux(pszWildstr, m_pString, 0) |
_WildcardAux(pszWildstr, m_pString, 1));
}
void WString::Unquote()
{
if (!m_pString)
return;
int nLen = wcslen(m_pString);
if (nLen == 0)
return;
// Remove trailing quote.
// ======================
if (m_pString[nLen - 1] == L'"')
m_pString[nLen - 1] = 0;
// Remove leading quote.
// =====================
if (m_pString[0] == L'"')
{
for (int i = 0; i < nLen; i++)
m_pString[i] = m_pString[i + 1];
}
}
WString WString::EscapeQuotes() const
{
WString ws;
int nLen = Length();
for(int i = 0; i < nLen; i++)
{
if(m_pString[i] == '"' || m_pString[i] == '\\')
{
ws += L'\\';
}
ws += m_pString[i];
}
return ws;
}