|
|
/*******************************************************************************
* * (C) COPYRIGHT MICROSOFT CORPORATION, 1998 * * TITLE: SIMSTR.H * * VERSION: 1.0 * * AUTHOR: ShaunIv * * DATE: 5/12/1998 * * DESCRIPTION: Simple string classes * *******************************************************************************/ #ifndef _SIMSTR_H_INCLUDED
#define _SIMSTR_H_INCLUDED
/*
* Simple string class. * * Template class: * CSimpleStringBase<T> * Implementations: * CSimpleStringBase<wchar_t> CSimpleStringWide * CSimpleStringBase<char> CSimpleStringAnsi * CSimpleString = CSimpleString[Ansi|Wide] depending on UNICODE macro * Inline functions: * CSimpleStringAnsi CSimpleStringConvert::AnsiString(T n) * CSimpleStringWide CSimpleStringConvert::WideString(T n) * CSimpleString CSimpleStringConvert::NaturalString(T n) * Macros: * IS_CHAR(T) * IS_WCHAR(T) */
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#include <tchar.h>
#define IS_CHAR(x) (sizeof(x)==sizeof(char))
#define IS_WCHAR(x) (sizeof(x)==sizeof(wchar_t))
#ifndef ARRAYSIZE
#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
template <class T> class CSimpleStringBase { private: enum { m_nDefaultGranularity = 16, // Default number of extra characters to allocate when we have to grow
m_nMaxLoadStringBuffer = 1024, // Maximum length of .RC string
m_nMaxAutoDataLength = 128 // Length of non-dynamically allocated string
};
private: T *m_pstrData; T m_pstrAutoData[m_nMaxAutoDataLength]; UINT m_nMaxSize; UINT m_nGranularity;
private: static int Min( int a, int b ) { return((a < b) ? a : b); }
public: // Replacements (in some cases just wrappers) for strlen, strcpy, ...
static inline T *GenericCopy( T *pstrTgtStr, const T *pstrSrcStr ); static inline T *GenericCopyLength( T *pstrTgtStr, const T *pstrSrcStr, UINT nSize ); static inline UINT GenericLength( const T *pstrStr ); static inline T *GenericConcatenate( T *pstrTgtStr, const T *pstrSrcStr ); static inline int GenericCompare( const T *pstrTgtStr, const T *pstrSrcStr ); static inline int GenericCompareNoCase( const T *pstrStrA, const T *pstrStrB ); static inline int GenericCompareLength( const T *pstrTgtStr, const T *pstrSrcStr, UINT nLength ); static inline T *GenericCharNext( const T *pszStr );
public: // Constructors and destructor
CSimpleStringBase( void ); CSimpleStringBase( const CSimpleStringBase & ); CSimpleStringBase( const T *szStr ); CSimpleStringBase( T ch ); CSimpleStringBase( UINT nResId, HMODULE hModule ); virtual ~CSimpleStringBase(void);
bool EnsureLength( UINT nMaxSize ); UINT Length(void) const; void Concat( const CSimpleStringBase &other ); int Resize(void); UINT Truncate( UINT nLen ); bool Assign( const T *szStr ); bool Assign( const CSimpleStringBase & ); void DeleteStorage(void); static inline T *CreateStorage( UINT nCount ); void Destroy(void);
CSimpleStringBase &Format( const T *strFmt, ... ); CSimpleStringBase &Format( int nResId, HINSTANCE hInst, ... );
// Handy Win32 wrappers
CSimpleStringBase &GetWindowText( HWND hWnd ); bool SetWindowText( HWND hWnd ); bool LoadString( UINT nResId, HMODULE hModule ); bool Load( HKEY hRegKey, const T *pszValueName, const T *pszDefault=NULL ); bool Store( HKEY hRegKey, const T *pszValueName, DWORD nType = REG_SZ ); void SetAt( UINT nIndex, T chValue ); CSimpleStringBase &operator=( const CSimpleStringBase &other ); CSimpleStringBase &operator=( const T *other ); CSimpleStringBase &operator+=( const CSimpleStringBase &other ); CSimpleStringBase operator+( const CSimpleStringBase &other ) const; T &operator[](int index); const T &operator[](int index) const;
CSimpleStringBase ToUpper(void) const; CSimpleStringBase ToLower(void) const;
CSimpleStringBase &MakeUpper(void); CSimpleStringBase &MakeLower(void); CSimpleStringBase &TrimRight(void); CSimpleStringBase &TrimLeft(void); CSimpleStringBase &Trim(void); CSimpleStringBase &Reverse(void);
int Find( T cChar ) const; int Find( const CSimpleStringBase &other, UINT nStart=0 ) const; int ReverseFind( T cChar ) const; int ReverseFind( const CSimpleStringBase &other ) const;
CSimpleStringBase SubStr( int nStart, int nCount=-1 ) const; int CompareNoCase( const CSimpleStringBase &other, int nLength=-1 ) const; int Compare( const CSimpleStringBase &other, int nLength=-1 ) const; bool MatchLastCharacter( T cChar ) const;
// Some useful inlines
UINT Granularity( UINT nGranularity ) { if (nGranularity>0) m_nGranularity = nGranularity;return m_nGranularity;} UINT Granularity( void ) const { return m_nGranularity;} CSimpleStringBase Left( int nCount ) const { return SubStr( 0, nCount );} CSimpleStringBase Right( int nCount ) const { return SubStr( max(0,(int)Length()-nCount), -1 );} bool operator<( const CSimpleStringBase &other ) const { return(Compare(other) < 0);} bool operator<=( const CSimpleStringBase &other ) const { return(Compare(other) <= 0);} bool operator==( const CSimpleStringBase &other ) const { return(Compare(other) == 0);} bool operator!=( const CSimpleStringBase &other ) const { return(Compare(other) != 0);} bool operator>=( const CSimpleStringBase &other ) const { return(Compare(other) >= 0);} bool operator>( const CSimpleStringBase &other ) const { return(Compare(other) > 0);} const T *String(void) const { return m_pstrData;} operator const T *(void) const { return String();} bool IsValid(void) const { return(NULL != m_pstrData);} };
template <class T> inline T *CSimpleStringBase<T>::GenericCopy( T *pszDest, const T *pszSource ) { T *pCurr = pszDest; while (*pCurr++ = *pszSource++) ; return(pszDest); }
template <class T> inline T *CSimpleStringBase<T>::GenericCharNext( const T *pszStr ) { if (IS_CHAR(*pszStr)) return (T*)CharNextA((LPCSTR)pszStr); else if (!*pszStr) return (T*)pszStr; else return (T*)((LPWSTR)pszStr + 1); }
template <class T> inline T *CSimpleStringBase<T>::GenericCopyLength( T *pszDest, const T *source, UINT count ) { T *start = pszDest; while (count && (*pszDest++ = *source++)) count--; if (count) while (--count) *pszDest++ = 0; return(start); }
template <class T> inline UINT CSimpleStringBase<T>::GenericLength( const T *pszString ) { const T *eos = pszString;
while (*eos++) ; return((UINT)(eos - pszString - 1)); }
template <class T> inline T*CSimpleStringBase<T>::GenericConcatenate( T *pszDest, const T *pszSource ) { T *pCurr = pszDest;
while (*pCurr) pCurr++;
while (*pCurr++ = *pszSource++) ;
return( pszDest ); }
template <class T> inline int CSimpleStringBase<T>::GenericCompare( const T *pszSource, const T *pszDest ) { #if defined(DBG) && !defined(UNICODE) && !defined(_UNICODE)
if (sizeof(T) == sizeof(wchar_t)) { OutputDebugString(TEXT("CompareStringW is not supported under win9x, so this call is going to fail!")); } #endif
int nRes = IS_CHAR(*pszSource) ? CompareStringA( LOCALE_USER_DEFAULT, 0, (LPCSTR)pszSource, -1, (LPCSTR)pszDest, -1 ) : CompareStringW( LOCALE_USER_DEFAULT, 0, (LPCWSTR)pszSource, -1, (LPCWSTR)pszDest, -1 ); switch (nRes) { case CSTR_LESS_THAN: return -1; case CSTR_GREATER_THAN: return 1; default: return 0; } }
template <class T> inline int CSimpleStringBase<T>::GenericCompareNoCase( const T *pszSource, const T *pszDest ) { #if defined(DBG) && !defined(UNICODE) && !defined(_UNICODE)
if (sizeof(T) == sizeof(wchar_t)) { OutputDebugString(TEXT("CompareStringW is not supported under win9x, so this call is going to fail!")); } #endif
int nRes = IS_CHAR(*pszSource) ? CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE, (LPCSTR)pszSource, -1, (LPCSTR)pszDest, -1 ) : CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE, (LPCWSTR)pszSource, -1, (LPCWSTR)pszDest, -1 ); switch (nRes) { case CSTR_LESS_THAN: return -1; case CSTR_GREATER_THAN: return 1; default: return 0; } }
template <class T> inline int CSimpleStringBase<T>::GenericCompareLength( const T *pszStringA, const T *pszStringB, UINT nLength ) { #if defined(DBG) && !defined(UNICODE) && !defined(_UNICODE)
if (sizeof(T) == sizeof(wchar_t)) { OutputDebugString(TEXT("CompareStringW is not supported under win9x, so this call is going to fail!")); } #endif
if (!nLength) return(0); int nRes = IS_CHAR(*pszStringA) ? CompareStringA( LOCALE_USER_DEFAULT, 0, (LPCSTR)pszStringA, Min(nLength,CSimpleStringBase<CHAR>::GenericLength((LPCSTR)pszStringA)), (LPCSTR)pszStringB, Min(nLength,CSimpleStringBase<CHAR>::GenericLength((LPCSTR)pszStringB)) ) : CompareStringW( LOCALE_USER_DEFAULT, 0, (LPWSTR)pszStringA, Min(nLength,CSimpleStringBase<WCHAR>::GenericLength((LPCWSTR)pszStringA)), (LPCWSTR)pszStringB, Min(nLength,CSimpleStringBase<WCHAR>::GenericLength((LPCWSTR)pszStringB)) ); switch (nRes) { case CSTR_LESS_THAN: return -1; case CSTR_GREATER_THAN: return 1; default: return 0; } }
template <class T> bool CSimpleStringBase<T>::EnsureLength( UINT nMaxSize ) { //
// If the string is already long enough, just return true
//
if (m_nMaxSize >= nMaxSize) { return true; }
//
// Save the old max size
//
UINT nOldMaxSize = m_nMaxSize;
//
// Get the new size
//
UINT nNewMaxSize = nMaxSize + m_nGranularity;
//
// Allocate the new buffer
//
T *pszTmp = CreateStorage(nNewMaxSize);
//
// Make sure the allocation succeded
//
if (pszTmp) { //
// If we have an existing string, copy it and delete it
//
if (m_pstrData) { GenericCopy(pszTmp,m_pstrData); DeleteStorage(); }
//
// Save the new max size
//
m_nMaxSize = nNewMaxSize; //
// Save this new string
//
m_pstrData = pszTmp;
//
// Return success
//
return true; } //
// Couldn't allocate memory
//
return false; }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::GetWindowText( HWND hWnd ) { Destroy(); // Assume it didn't work
bool bSuccess = false; int nLen = ::GetWindowTextLength(hWnd); if (nLen) { if (EnsureLength(nLen+1)) { if (::GetWindowText( hWnd, m_pstrData, (nLen+1) )) { bSuccess = true; } } } if (!bSuccess) Destroy(); return *this; }
template <class T> bool CSimpleStringBase<T>::SetWindowText( HWND hWnd ) { return(::SetWindowText( hWnd, String() ) != FALSE); }
template <class T> UINT CSimpleStringBase<T>::Truncate( UINT nLen ) { if (Length() < nLen) return Length(); if (!nLen) return 0; m_pstrData[nLen-1] = 0; Resize(); return Length(); }
template <class T> int CSimpleStringBase<T>::Resize(void) { m_nMaxSize = m_pstrData ? GenericLength(m_pstrData) : 0; ++m_nMaxSize; T *pszTmp = CreateStorage(m_nMaxSize); if (pszTmp) { if (m_pstrData) { GenericCopy(pszTmp,m_pstrData); DeleteStorage(); } else *pszTmp = 0; m_pstrData = pszTmp; } return Length(); }
template <class T> CSimpleStringBase<T>::CSimpleStringBase(void) : m_pstrData(m_pstrAutoData),m_nMaxSize(ARRAYSIZE(m_pstrAutoData)),m_nGranularity(m_nDefaultGranularity) { m_pstrAutoData[0] = 0; T szTmp[1] = { 0}; Assign(szTmp); }
template <class T> CSimpleStringBase<T>::CSimpleStringBase( const CSimpleStringBase &other ) : m_pstrData(m_pstrAutoData),m_nMaxSize(ARRAYSIZE(m_pstrAutoData)),m_nGranularity(m_nDefaultGranularity) { m_pstrAutoData[0] = 0; Assign(other.String()); }
template <class T> CSimpleStringBase<T>::CSimpleStringBase( const T *szStr ) : m_pstrData(m_pstrAutoData),m_nMaxSize(ARRAYSIZE(m_pstrAutoData)),m_nGranularity(m_nDefaultGranularity) { m_pstrAutoData[0] = 0; Assign(szStr); }
template <class T> CSimpleStringBase<T>::CSimpleStringBase( T ch ) : m_pstrData(m_pstrAutoData),m_nMaxSize(ARRAYSIZE(m_pstrAutoData)),m_nGranularity(m_nDefaultGranularity) { m_pstrAutoData[0] = 0; T szTmp[2]; szTmp[0] = ch; szTmp[1] = 0; Assign(szTmp); }
template <class T> CSimpleStringBase<T>::CSimpleStringBase( UINT nResId, HMODULE hModule ) : m_pstrData(m_pstrAutoData),m_nMaxSize(ARRAYSIZE(m_pstrAutoData)),m_nGranularity(m_nDefaultGranularity) { m_pstrAutoData[0] = 0; LoadString( nResId, hModule ); }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::Format( const T *strFmt, ... ) { T szTmp[1024]; va_list arglist;
va_start(arglist, strFmt); int nRet = IS_CHAR(*m_pstrData) ? _vsnprintf((LPSTR)szTmp, ARRAYSIZE(szTmp), (LPCSTR)strFmt, arglist) : _vsnwprintf((LPWSTR)szTmp, ARRAYSIZE(szTmp), (LPCWSTR)strFmt, arglist); va_end(arglist); Assign(szTmp); return *this; }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::Format( int nResId, HINSTANCE hInst, ... ) { CSimpleStringBase<T> strFmt; va_list arglist; if (strFmt.LoadString(nResId,hInst)) { T szTmp[1024]; va_start(arglist, hInst); int nRet = IS_CHAR(*m_pstrData) ? _vsnprintf((LPSTR)szTmp, ARRAYSIZE(szTmp), (LPCSTR)strFmt.String(), arglist) : _vsnwprintf((LPWSTR)szTmp, ARRAYSIZE(szTmp), (LPCWSTR)strFmt.String(), arglist); va_end(arglist); Assign(szTmp); } else Assign(NULL); return *this; }
template <class T> bool CSimpleStringBase<T>::LoadString( UINT nResId, HMODULE hModule ) { if (!hModule) hModule = GetModuleHandle(NULL); T szTmp[m_nMaxLoadStringBuffer]; int nRet = IS_CHAR(*m_pstrData) ? ::LoadStringA( hModule, nResId, (LPSTR)szTmp, ARRAYSIZE(szTmp)) : ::LoadStringW( hModule, nResId, (LPWSTR)szTmp, ARRAYSIZE(szTmp)); if (nRet) return Assign(szTmp); else return Assign(NULL); }
template <class T> CSimpleStringBase<T>::~CSimpleStringBase(void) { Destroy(); }
template <class T> void CSimpleStringBase<T>::DeleteStorage(void) { //
// Only delete the string if it is non-NULL and not pointing to our non-dynamically allocated buffer
//
if (m_pstrData && m_pstrData != m_pstrAutoData) { delete[] m_pstrData; } m_pstrData = NULL; }
template <class T> T *CSimpleStringBase<T>::CreateStorage( UINT nCount ) { return new T[nCount]; }
template <class T> void CSimpleStringBase<T>::Destroy(void) { DeleteStorage(); m_nMaxSize = 0; }
template <class T> UINT CSimpleStringBase<T>::Length(void) const { return(m_pstrData ? GenericLength(m_pstrData) : 0); }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::operator=( const CSimpleStringBase &other ) { if (&other != this) { Assign(other.String()); } return *this; }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::operator=( const T *other ) { if (other != String()) { Assign(other); } return *this; }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::operator+=( const CSimpleStringBase &other ) { Concat(other.String()); return *this; }
template <class T> CSimpleStringBase<T> CSimpleStringBase<T>::operator+( const CSimpleStringBase &other ) const { CSimpleStringBase tmp(*this); tmp.Concat(other); return tmp; }
template <class T> bool CSimpleStringBase<T>::Assign( const T *szStr ) { if (szStr && EnsureLength(GenericLength(szStr)+1)) { GenericCopy(m_pstrData,szStr); } else if (EnsureLength(1)) { *m_pstrData = 0; } else Destroy(); return(NULL != m_pstrData); }
template <class T> bool CSimpleStringBase<T>::Assign( const CSimpleStringBase &other ) { return Assign( other.String() ); }
template <class T> void CSimpleStringBase<T>::SetAt( UINT nIndex, T chValue ) { //
// Make sure we don't go off the end of the string or overwrite the '\0'
//
if (m_pstrData && Length() > nIndex) { m_pstrData[nIndex] = chValue; } }
template <class T> void CSimpleStringBase<T>::Concat( const CSimpleStringBase &other ) { if (EnsureLength( Length() + other.Length() + 1 )) { GenericConcatenate(m_pstrData,other.String()); } }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::MakeUpper(void) { //
// Make sure the string is not NULL
//
if (m_pstrData) { IS_CHAR(*m_pstrData) ? CharUpperBuffA( (LPSTR)m_pstrData, Length() ) : CharUpperBuffW( (LPWSTR)m_pstrData, Length() ); } return *this; }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::MakeLower(void) { //
// Make sure the string is not NULL
//
if (m_pstrData) { IS_CHAR(*m_pstrData) ? CharLowerBuffA( (LPSTR)m_pstrData, Length() ) : CharLowerBuffW( (LPWSTR)m_pstrData, Length() ); } return *this; }
template <class T> CSimpleStringBase<T> CSimpleStringBase<T>::ToUpper(void) const { CSimpleStringBase str(*this); str.MakeUpper(); return str; }
template <class T> CSimpleStringBase<T> CSimpleStringBase<T>::ToLower(void) const { CSimpleStringBase str(*this); str.MakeLower(); return str; }
template <class T> T &CSimpleStringBase<T>::operator[](int nIndex) { return m_pstrData[nIndex]; }
template <class T> const T &CSimpleStringBase<T>::operator[](int index) const { return m_pstrData[index]; }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::TrimRight(void) { T *pFirstWhitespaceCharacterInSequence = NULL; bool bInWhiteSpace = false; T *pszPtr = m_pstrData; while (pszPtr && *pszPtr) { if (*pszPtr == L' ' || *pszPtr == L'\t' || *pszPtr == L'\n' || *pszPtr == L'\r') { if (!bInWhiteSpace) { pFirstWhitespaceCharacterInSequence = pszPtr; bInWhiteSpace = true; } } else { bInWhiteSpace = false; } pszPtr = GenericCharNext(pszPtr); } if (pFirstWhitespaceCharacterInSequence && bInWhiteSpace) *pFirstWhitespaceCharacterInSequence = 0; return *this; }
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::TrimLeft(void) { T *pszPtr = m_pstrData; while (pszPtr && *pszPtr) { if (*pszPtr == L' ' || *pszPtr == L'\t' || *pszPtr == L'\n' || *pszPtr == L'\r') { pszPtr = GenericCharNext(pszPtr); } else break; } Assign(CSimpleStringBase<T>(pszPtr).String()); return *this; }
template <class T> inline CSimpleStringBase<T> &CSimpleStringBase<T>::Trim(void) { TrimLeft(); TrimRight(); return *this; }
//
// Note that this function WILL NOT WORK CORRECTLY for multi-byte characters in ANSI strings
//
template <class T> CSimpleStringBase<T> &CSimpleStringBase<T>::Reverse(void) { UINT nLen = Length(); for (UINT i = 0;i<nLen/2;i++) { T tmp = m_pstrData[i]; m_pstrData[i] = m_pstrData[nLen-i-1]; m_pstrData[nLen-i-1] = tmp; } return *this; }
template <class T> int CSimpleStringBase<T>::Find( T cChar ) const { T strTemp[2] = { cChar, 0}; return Find(strTemp); }
template <class T> int CSimpleStringBase<T>::Find( const CSimpleStringBase &other, UINT nStart ) const { if (!m_pstrData) return -1; if (nStart > Length()) return -1; T *pstrCurr = m_pstrData+nStart, *pstrSrc, *pstrSubStr; while (*pstrCurr) { pstrSrc = pstrCurr; pstrSubStr = (T *)other.String(); while (*pstrSrc && *pstrSubStr && *pstrSrc == *pstrSubStr) { pstrSrc = GenericCharNext(pstrSrc); pstrSubStr = GenericCharNext(pstrSubStr); } if (!*pstrSubStr) return static_cast<int>(pstrCurr-m_pstrData); pstrCurr = GenericCharNext(pstrCurr); } return -1; }
template <class T> int CSimpleStringBase<T>::ReverseFind( T cChar ) const { T strTemp[2] = { cChar, 0}; return ReverseFind(strTemp); }
template <class T> int CSimpleStringBase<T>::ReverseFind( const CSimpleStringBase &srcStr ) const { int nLastFind = -1, nFind=0; while ((nFind = Find( srcStr, nFind )) >= 0) { nLastFind = nFind; ++nFind; } return nLastFind; }
template <class T> CSimpleStringBase<T> CSimpleStringBase<T>::SubStr( int nStart, int nCount ) const { if (nStart >= (int)Length() || nStart < 0) return CSimpleStringBase<T>(); if (nCount < 0) nCount = Length() - nStart; CSimpleStringBase<T> strTmp; T *pszTmp = CreateStorage(nCount+1); if (pszTmp) { GenericCopyLength( pszTmp, m_pstrData+nStart, nCount+1 ); pszTmp[nCount] = 0; strTmp = pszTmp; delete[] pszTmp; } return strTmp; }
template <class T> int CSimpleStringBase<T>::CompareNoCase( const CSimpleStringBase &other, int nLength ) const { if (nLength < 0) { //
// Make sure both strings are non-NULL
//
if (!String() && !other.String()) { return 0; } else if (!String()) { return -1; } else if (!other.String()) { return 1; } else return GenericCompareNoCase(m_pstrData,other.String()); } CSimpleStringBase<T> strSrc(*this); CSimpleStringBase<T> strTgt(other); strSrc.MakeUpper(); strTgt.MakeUpper(); //
// Make sure both strings are non-NULL
//
if (!strSrc.String() && !strTgt.String()) { return 0; } else if (!strSrc.String()) { return -1; } else if (!strTgt.String()) { return 1; } else return GenericCompareLength(strSrc.String(),strTgt.String(),nLength); }
template <class T> int CSimpleStringBase<T>::Compare( const CSimpleStringBase &other, int nLength ) const { //
// Make sure both strings are non-NULL
//
if (!String() && !other.String()) { return 0; } else if (!String()) { return -1; } else if (!other.String()) { return 1; }
if (nLength < 0) { return GenericCompare(String(),other.String()); } return GenericCompareLength(String(),other.String(),nLength); }
template <class T> bool CSimpleStringBase<T>::MatchLastCharacter( T cChar ) const { int nFind = ReverseFind(cChar); if (nFind < 0) return false; if (nFind == (int)Length()-1) return true; else return false; }
template <class T> bool CSimpleStringBase<T>::Load( HKEY hRegKey, const T *pszValueName, const T *pszDefault ) { bool bResult = false; Assign(pszDefault); DWORD nType=0; DWORD nSize=0; LONG nRet; if (IS_CHAR(*m_pstrData)) nRet = RegQueryValueExA( hRegKey, (LPCSTR)pszValueName, NULL, &nType, NULL, &nSize); else nRet = RegQueryValueExW( hRegKey, (LPCWSTR)pszValueName, NULL, &nType, NULL, &nSize); if (ERROR_SUCCESS == nRet) { if ((nType == REG_SZ) || (nType == REG_EXPAND_SZ)) { // Round up to the nearest 2
nSize = ((nSize + 1) & 0xFFFFFFFE); T *pstrTemp = CreateStorage(nSize / sizeof(T)); if (pstrTemp) { if (IS_CHAR(*m_pstrData)) nRet = RegQueryValueExA( hRegKey, (LPCSTR)pszValueName, NULL, &nType, (PBYTE)pstrTemp, &nSize); else nRet = RegQueryValueExW( hRegKey, (LPCWSTR)pszValueName, NULL, &nType, (PBYTE)pstrTemp, &nSize); if (ERROR_SUCCESS == nRet) { Assign(pstrTemp); bResult = true; } delete pstrTemp; } } } return bResult; }
template <class T> bool CSimpleStringBase<T>::Store( HKEY hRegKey, const T *pszValueName, DWORD nType ) { bool bResult = false; long nRet; if (Length()) { if (IS_CHAR(*m_pstrData)) nRet = RegSetValueExA( hRegKey, (LPCSTR)pszValueName, 0, nType, (PBYTE)m_pstrData, sizeof(*m_pstrData)*(Length()+1) ); else nRet = RegSetValueExW( hRegKey, (LPCWSTR)pszValueName, 0, nType, (PBYTE)m_pstrData, sizeof(*m_pstrData)*(Length()+1) ); } else { T strBlank = 0; if (IS_CHAR(*m_pstrData)) nRet = RegSetValueExA( hRegKey, (LPCSTR)pszValueName, 0, nType, (PBYTE)&strBlank, sizeof(T) ); else nRet = RegSetValueExW( hRegKey, (LPCWSTR)pszValueName, 0, nType, (PBYTE)&strBlank, sizeof(T) ); } return(ERROR_SUCCESS == nRet); }
typedef CSimpleStringBase<char> CSimpleStringAnsi; typedef CSimpleStringBase<wchar_t> CSimpleStringWide;
#if defined(UNICODE) || defined(_UNICODE)
#define CSimpleString CSimpleStringWide
#else
#define CSimpleString CSimpleStringAnsi
#endif
namespace CSimpleStringConvert { template <class T> CSimpleStringWide WideString(const T &str) { if (IS_WCHAR(str[0])) return CSimpleStringWide((LPCWSTR)str.String()); else { if (!str.Length()) return CSimpleStringWide(L""); int iLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, (LPCSTR)str.String(), str.Length()+1, NULL, 0 ); CSimpleStringWide sswTmp; LPWSTR pwszTmp = new WCHAR[iLen]; if (pwszTmp) { MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, (LPCSTR)str.String(), str.Length()+1, pwszTmp, iLen ); sswTmp = pwszTmp; delete[] pwszTmp; } return sswTmp; } }
template <class T> CSimpleStringAnsi AnsiString(const T &str) { if (IS_CHAR(str[0])) return CSimpleStringAnsi((LPCSTR)str.String()); else { if (!str.Length()) return CSimpleStringAnsi(""); int iLen = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)str.String(), str.Length()+1, NULL, 0, NULL, NULL ); CSimpleStringAnsi ssaTmp; LPSTR pszTmp = new CHAR[iLen]; if (pszTmp) { WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)str.String(), str.Length()+1, pszTmp, iLen, NULL, NULL ); ssaTmp = pszTmp; delete[] pszTmp; } return ssaTmp; } }
#if defined(_UNICODE) || defined(UNICODE)
template <class T> CSimpleStringWide NaturalString(const T &str) { return WideString(str); } #else
template <class T> CSimpleStringAnsi NaturalString(const T &str) { return AnsiString(str); } #endif
inline CSimpleString NumberToString( int nNumber, LCID Locale=LOCALE_USER_DEFAULT ) { TCHAR szTmp[MAX_PATH]=TEXT(""); TCHAR szNumberStr[MAX_PATH]=TEXT(""); TCHAR szDigitGrouping[32]=TEXT(""); TCHAR szThousandsSeparator[32]=TEXT(""); TCHAR szDecimalSeparator[32]=TEXT("");
// Initialize the number format
NUMBERFMT NumberFormat; NumberFormat.NumDigits = 0; NumberFormat.LeadingZero = 0; NumberFormat.NegativeOrder = 0; // This turns a string into a number, like so: 3;2;0=32 or 3;0 = 3 or 1;2;3;4;5;6;0 = 123456. Got it?
GetLocaleInfo( Locale, LOCALE_SGROUPING, szDigitGrouping, ARRAYSIZE(szDigitGrouping)); NumberFormat.Grouping = 0; LPTSTR pszCurr = szDigitGrouping; while (*pszCurr && *pszCurr >= TEXT('1') && *pszCurr <= TEXT('9')) { NumberFormat.Grouping *= 10; NumberFormat.Grouping += (*pszCurr - TEXT('0')); pszCurr += 2; } GetLocaleInfo( Locale, LOCALE_STHOUSAND, szThousandsSeparator, ARRAYSIZE(szThousandsSeparator)); NumberFormat.lpThousandSep = szThousandsSeparator; GetLocaleInfo( Locale, LOCALE_SDECIMAL, szDecimalSeparator, ARRAYSIZE(szDecimalSeparator)); NumberFormat.lpDecimalSep = szDecimalSeparator; // Create the number string
_sntprintf( szTmp, ARRAYSIZE(szTmp), TEXT("%d"), nNumber ); if (GetNumberFormat( Locale, 0, szTmp, &NumberFormat, szNumberStr, ARRAYSIZE(szNumberStr))) return szNumberStr; else return TEXT(""); } } // End CSimpleStringConvert namespace
#endif // ifndef _SIMSTR_H_INCLUDED
|