|
|
//*****************************************************************************
//
// Support Class: CSTRING
//
// Purpose: Handle strings for the application. CSTRING does smart memory
// management for strings.
//
// Notes: For more information, see CompatAdmin.DOC
//
// History
//
// A-COWEN Dec 12, 2000 Wrote it.
//
//*****************************************************************************
#define MAX_STRING_SIZE 2048
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include "stdarg.h"
class CMemException { private: TCHAR m_szMessageHeading[100]; TCHAR m_szMessage[512] ; public: CMemException() { _tcscpy(m_szMessageHeading,TEXT("Insufficient Memory Exception")); _tcscpy(m_szMessage, TEXT("Insufficient Memory Exception"));
} void SetString(TCHAR* szMsg ) { int nch = _sntprintf(m_szMessage, sizeof(m_szMessage)/sizeof(TCHAR), TEXT("%s : %s"), m_szMessageHeading, szMsg); #ifdef __DEBUG
if (nch < 0) { MessageBox(NULL,TEXT("Please make the error message Short"),TEXT("Long Error Message"), MB_ICONWARNING); } #endif
} TCHAR* GetString() { return m_szMessage; }
};
class CSTRING { public:
WCHAR * pszString; LPSTR pszANSI; public:
CSTRING() { Init(); }
CSTRING(CSTRING & Str) { Init(); SetString(Str.pszString); }
CSTRING(LPTSTR szString) { Init(); SetString(szString); }
CSTRING(UINT uID) { Init(); SetString(uID); }
~CSTRING() { Release(); }
void Init() { pszString = NULL; pszANSI = NULL; }
void Release(void) { if ( NULL != pszString ) delete pszString;
if ( NULL != pszANSI ) delete pszANSI;
pszString = NULL; pszANSI = NULL; }
BOOL SetString(UINT uID) { TCHAR szString[MAX_STRING_SIZE];
if ( 0 != LoadString(GetModuleHandle(NULL), uID, szString, MAX_STRING_SIZE) ) return SetString(szString);
return FALSE; }
BOOL SetString(LPCTSTR szStringIn) { if ( pszString == szStringIn ) return TRUE;
Release();
if ( NULL == szStringIn ) return TRUE;
UINT uLen = _tcslen(szStringIn) + 1;
pszString = new TCHAR[uLen];
if ( NULL != pszString ) _tcscpy(pszString,szStringIn); else {
CMemException memException; throw memException; return FALSE; }
return TRUE; }
operator LPCSTR() {
if (pszANSI != NULL) delete pszANSI;
int cbSize = WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,this->pszString, -1, NULL, 0, NULL, NULL); pszANSI = (LPSTR) new CHAR [cbSize+1];
ZeroMemory(pszANSI,sizeof(pszANSI) );
if (pszANSI == NULL) { MEM_ERR; return NULL; }
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,this->pszString, -1, pszANSI, cbSize+1, NULL, NULL); return pszANSI; }
operator LPWSTR() { return pszString; } operator LPCWSTR() {
return pszString;
}
CSTRING& operator =(LPCWSTR szStringIn) { #ifndef UNICODE
TCHAR szTemp[MAX_STRING_SIZE]; int nLength = lstrlenW(szStringIn);
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,szStringIn,nLength,szTemp,MAX_STRING_SIZE,NULL,NULL);
szTemp[nLength] = 0;
SetString(szTemp);
#else
SetString(szStringIn); #endif
return *this; }
CSTRING& operator =(CSTRING & szStringIn) { SetString(szStringIn.pszString);
return *this;
}
BOOL operator == (CSTRING & szString) { if (NULL == pszString && NULL == szString.pszString) { return TRUE; }
if ( NULL == pszString || NULL == szString.pszString) return FALSE;
if ( 0 == lstrcmpi(szString.pszString,pszString) ) return TRUE;
return FALSE; }
BOOL operator == (LPCTSTR szString) { if (NULL == pszString && NULL == szString) { return TRUE; }
if ( NULL == pszString || NULL == szString) return FALSE;
if ( 0 == lstrcmpi(szString,pszString) ) return TRUE;
return FALSE; }
BOOL operator != (CSTRING & szString) { if (NULL == pszString && NULL == szString.pszString) { return FALSE; }
if ( NULL == pszString || NULL == szString.pszString) return TRUE;
if ( 0 == lstrcmpi(szString.pszString,pszString) ) return FALSE;
return TRUE; }
BOOL operator != (LPCTSTR szString) { if ( NULL == pszString ) return TRUE;
if ( 0 == lstrcmpi(szString,pszString) ) return FALSE;
return TRUE; }
BOOL operator <= (CSTRING &szString) { return ( (lstrcmpi (*this,szString) <= 0 ) ? TRUE : FALSE); }
BOOL operator < (CSTRING &szString) { return ( (lstrcmpi (*this,szString) < 0 ) ? TRUE : FALSE); }
BOOL operator >= (CSTRING &szString) { return ( (lstrcmpi (*this,szString) >= 0 ) ? TRUE : FALSE); }
BOOL operator > (CSTRING &szString) { return ( (lstrcmpi (*this,szString) > 0 ) ? TRUE : FALSE); }
void __cdecl sprintf(LPCTSTR szFormat, ...) { va_list list; TCHAR szTemp[MAX_STRING_SIZE];
va_start(list,szFormat); int cch = _vsntprintf(szTemp, sizeof(szTemp)/sizeof(szTemp[0]), szFormat, list);
#ifdef __DEBUG
if (cch < 0) { DBGPRINT((sdlError,("CSTRING::sprintf"), ("%s"), TEXT("Too long for _vsntprintf()") ) ); } #endif
SetString(szTemp); }
UINT Trim() {
CSTRING szTemp = *this;
UINT uOrig_length = Length();
TCHAR *pStart = szTemp.pszString, *pEnd = szTemp.pszString + uOrig_length - 1;
while ( *pStart== TEXT(' ') ) ++pStart;
while ( (pEnd >= pStart) && ( *pEnd == TEXT(' ') ) ) --pEnd;
*( pEnd + 1) = TEXT('\0');//Keep it safe
UINT nLength = pEnd - pStart; ++nLength; // For the character
//
//If no trimming has been done, return right away
//
if ( uOrig_length == nLength ) { return nLength; }
SetString(pStart);
return ( nLength); }
BOOL SetChar(int nPos, TCHAR chValue) { //Pos is 0 based
int length = Length(); if (nPos >= length || length <= 0 ) { return FALSE; }
this->pszString[nPos] = chValue; return TRUE;
} static Trim(IN OUT LPTSTR str) { UINT uOrig_length = lstrlen(str); // Original length
TCHAR *pStart = str, *pEnd = str + uOrig_length - 1;
while ( *pStart== TEXT(' ') ) ++pStart;
while ( (pEnd >= pStart) && ( *pEnd == TEXT(' ') ) ) --pEnd;
*( pEnd + 1) = TEXT('\0');//Keep it safe
UINT nLength = pEnd - pStart; ++nLength; // For the character
//
//If no trimming has been done, return right away
//
if ( uOrig_length == nLength ) { return nLength; } wmemmove(str,pStart, (nLength+1) * sizeof(TCHAR) ); // +1 for the 0 character.
return (nLength);
} BOOL EndsWith(LPCTSTR szSuffix) { const TCHAR* pStr = this->pszString; const TCHAR* pPos = NULL; pPos = _tcsrchr(pStr,TEXT('.'));
if (pPos != NULL ) if (_tcsicmp(pPos,szSuffix) == 0 ) return TRUE;
return FALSE;
} PCTSTR strcat(CSTRING & szStr) { return strcat((LPCTSTR)szStr); }
LPCTSTR strcat(LPCTSTR pString) { if (pString == NULL) { return pszString; }
int nLengthCat = _tcslen(pString); int nLengthStr = Length(); TCHAR *szTemp = new TCHAR [nLengthStr + nLengthCat + 1];
if ( szTemp == NULL ) { CMemException memException; throw memException; return NULL;
}
szTemp[0] = 0;
//
// Copy only if pszString != NULL. Otherwise we will get mem exception/garbage value
//
if (nLengthStr ) _tcsncpy(szTemp, pszString, nLengthStr);
_tcsncpy(szTemp+nLengthStr, pString, nLengthCat); szTemp[nLengthStr + nLengthCat] = TEXT('\0');
Release(); pszString = szTemp;
return pszString; }//strcat
BOOL isNULL() { return(this->pszString == NULL); }
int Length(void) { if ( NULL == pszString ) return 0;
return lstrlen(pszString); }
void GUID(GUID & Guid) { TCHAR szGUID[80];
// NOTE: We could use StringFromGUID2, or StringfromIID, but that
// would require loading OLE32.DLL. Unless we have to, avoid it.
// OR you could use functions in SDBAPI
_stprintf(szGUID, TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"), Guid.Data1, Guid.Data2, Guid.Data3, Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3], Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
SetString(szGUID); }
void ShortFilename(void) { TCHAR szTemp[MAX_PATH_BUFFSIZE]; LPTSTR szHold;
// BUGBUG consider using shlwapi PathFindFileName
_tcscpy(szTemp,pszString);
LPTSTR szWalk = szTemp;
szHold = szWalk;
while ( 0 != *szWalk ) { //
// use _tcsrchr BUGBUG
//
if ( TEXT('\\') == *szWalk ) szHold = szWalk+1;
++szWalk; }
SetString(szHold); }
BOOL RelativeFile(CSTRING & szPath) { return RelativeFile((LPCTSTR)szPath); }
//
// BUGBUG : consider using shlwapi PathRelativePathTo
//
BOOL RelativeFile(LPCTSTR pExeFile) { LPCTSTR pMatchFile = pszString; int nLenExe = 0; int nLenMatch = 0; LPCTSTR pExe = NULL; LPCTSTR pMatch = NULL; LPTSTR pReturn = NULL; TCHAR result[MAX_PATH_BUFFSIZE]; LPTSTR resultIdx = result; BOOL bCommonBegin = FALSE; // Indicates if the paths have a common beginning
*result = TEXT('\0'); //
// Ensure that the beginning of the path matches between the two files
//
// BUGBUG this code has to go -- look into replacing this with Shlwapi Path*
//
//
pExe = _tcschr(pExeFile, TEXT('\\')); pMatch = _tcschr(pMatchFile, TEXT('\\'));
while ( pExe && pMatch ) {
nLenExe = pExe - pExeFile; nLenMatch = pMatch - pMatchFile;
if ( nLenExe != nLenMatch ) { break; }
if ( !(_tcsnicmp(pExeFile, pMatchFile, nLenExe) == 0) ) { break; }
bCommonBegin = TRUE; pExeFile = pExe + 1; pMatchFile = pMatch + 1;
pExe = _tcschr(pExeFile, TEXT('\\')); pMatch = _tcschr(pMatchFile, TEXT('\\')); }
//
// Walk the path and put '..\' where necessary
//
if ( bCommonBegin ) {
while ( pExe ) { _tcscpy(resultIdx, TEXT("..\\")); resultIdx = resultIdx + 3; pExeFile = pExe + 1; pExe = _tcschr(pExeFile, TEXT('\\')); }
_tcscpy(resultIdx, pMatchFile);
SetString(result); } else{
return FALSE; }
return TRUE; } };
//
// BUGBUG: consider using list class from STL
//
//
template <class T> class CList { protected:
typedef struct _tagList { T Entry; struct _tagList * pNext; } LIST, *PLIST;
PLIST m_pHead; PLIST m_pCurrent; PLIST m_pFindPrev;
private:
PLIST Find(T * pData) { PLIST pWalk = m_pHead;
m_pFindPrev = NULL;
while ( NULL != pWalk ) { if ( pData == &pWalk->Entry ) return pWalk;
m_pFindPrev = pWalk; pWalk = pWalk->pNext; }
return NULL; }
public:
CList() { Init(); }
~CList() { Release(); }
void Init(void) { m_pHead = NULL; m_pCurrent = NULL; }
void Release(void) { while ( NULL != m_pHead ) { PLIST pHold = m_pHead->pNext;
delete m_pHead;
m_pHead = pHold; } }
T * First(void) { m_pCurrent = m_pHead;
if ( NULL == m_pHead ) return NULL;
return &m_pHead->Entry; }
T * Next(void) { if ( NULL != m_pCurrent ) { m_pCurrent = m_pCurrent->pNext;
if ( NULL != m_pCurrent ) return &m_pCurrent->Entry; }
return NULL; }
BOOL Insert(T * pInsert, T * pAfter = NULL) { PLIST pNew = new LIST;
if ( NULL == pNew ) return FALSE;
pNew->Entry = *pInsert;
if ( NULL == pAfter ) { pNew->pNext = m_pHead; m_pHead = pNew; } else { PLIST pHold = Find(pAfter);
if ( NULL == pHold ) { delete pNew; return FALSE; }
pNew->pNext = pHold->pNext; pHold->pNext = pNew; }
return TRUE; }
T * Insert(T * pAfter = NULL) { PLIST pNew = new LIST;
if ( NULL == pNew ) return NULL;
if ( NULL == pAfter ) { pNew->pNext = m_pHead; m_pHead = pNew; } else { PLIST pHold = Find(pAfter);
if ( NULL == pHold ) { delete pNew; return NULL; }
pNew->pNext = pHold->pNext; pHold->pNext = pNew; }
return &pNew->Entry; }
BOOL Delete(T * pEntry) { PLIST pHold = Find(pEntry);
if ( NULL == pHold ) return FALSE;
if ( NULL != m_pFindPrev ) { m_pFindPrev->pNext = pHold->pNext; delete pHold; } else { m_pHead = m_pHead->pNext; delete m_pHead; }
m_pCurrent = NULL;
return TRUE; } };
typedef struct _tagSList { CSTRING szStr; union { PVOID pExtraData; UINT uExtraData; DWORD dwExtraData; int nExtraData; }; struct _tagSList * pNext; } STRLIST, *PSTRLIST;
class CSTRINGList { public:
PSTRLIST m_pHead; PSTRLIST m_pTail;
public:
CSTRINGList() { m_pHead = NULL; m_pTail = NULL; }
~CSTRINGList() { while ( NULL != m_pHead ) { PSTRLIST pHold = m_pHead->pNext; delete m_pHead; m_pHead = pHold; } }
BOOL AddString(CSTRING & Str, PVOID pExtraData = NULL) { return AddString((LPCTSTR)Str,pExtraData); }
BOOL AddString(LPCTSTR pStr, PVOID pExtraData = NULL) { PSTRLIST pNew = new STRLIST;
if ( NULL == pNew ) return FALSE;
pNew->szStr = pStr; pNew->pExtraData = pExtraData; pNew->pNext = NULL;
if ( NULL == m_pTail ) { m_pHead = m_pTail = pNew; } else { m_pTail->pNext = pNew; m_pTail = pNew; }
return TRUE; } };
|