|
|
/*++
Copyright (c) 1989-2001 Microsoft Corporation
Module Name:
CSTRING.cpp Abstract:
The code for the CSTRING and the CSTRINGLIST Author:
kinshu created December 12, 2001 Revision History:
--*/
#include "precomp.h"
///////////////////////////////////////////////////////////////////////////////
//
// The string class
//
//
CSTRING::CSTRING() /*++
CSTRING::CSTRING() Desc: Constructor --*/ {
Init();
}
CSTRING::CSTRING(CSTRING& Str) /*++
CSTRING::CSTRING(CSTRING& Str) Desc: Constructor Params: CSTRING& Str: Another string. --*/ { Init(); SetString(Str.pszString); }
CSTRING::CSTRING(IN LPCTSTR szString) /*++
CSTRING::CSTRING(IN LPCTSTR szString) Desc: Constructor Params: IN LPCTSTR szString: The CSTRING should have this as its value --*/ { Init(); SetString(szString); }
CSTRING::CSTRING(IN UINT uID) /*++
CSTRING::CSTRING(IN UINT uID) Desc: Constructor. Loads the string resource with resource id uID and sets that to this string Params: IN UINT uID: The resource id for the string that we want to load --*/ { Init(); SetString(uID); }
CSTRING::~CSTRING() /*++
CSTRING::~CSTRING() Desc: Destructor --*/ { Release(); }
void CSTRING::Init( void ) /*++
CSTRING::Init
Desc: Does some initialisation stuff --*/ { pszString = NULL; pszANSI = NULL; }
inline void CSTRING::Release( void ) /*++
CSTRING::Release Desc: Frees the data associated with this string --*/ { if (NULL != pszString) { delete[] pszString; }
if (NULL != pszANSI) { delete[] pszANSI; }
pszString = NULL; pszANSI = NULL; }
inline BOOL CSTRING::SetString( IN UINT uID ) /*++
Desc: Loads the string resource with resource id uId and sets that to this string
Params: IN UINT uID: The resource id for the string that we want to load
Return: TRUE: String value set successfully FALSE: Otherwise --*/ { TCHAR szString[1024];
if (0 != LoadString(GetModuleHandle(NULL), uID, szString, ARRAYSIZE(szString))) { return SetString(szString); }
return FALSE; }
inline BOOL CSTRING::SetString( IN LPCTSTR pszStringIn ) /*++
CSTRING::SetString
Desc: Frees the current data for this string and assigns a new string value to it
Params: IN LPCTSTR pszStringIn: Pointer to the new string
Return: TRUE: Successful FALSE: Otherwise --*/ { UINT uLen = 0;
if (pszString == pszStringIn) { return TRUE; }
Release();
if (NULL == pszStringIn) { return TRUE; }
uLen = lstrlen(pszStringIn) + 1;
try { pszString = new TCHAR[uLen]; } catch(...) { pszString = NULL; }
if (NULL != pszString) { SafeCpyN(pszString, pszStringIn, uLen); } else { MEM_ERR; return FALSE; }
return TRUE; }
void __cdecl CSTRING::Sprintf( IN LPCTSTR szFormat, ... ) /*++
CSTRING::Sprintf
Desc: Please see _vsntprintf
Params: Please see _vsntprintf
Return: void --*/ { K_SIZE k_pszTemp = MAX_STRING_SIZE; PTSTR pszTemp = new TCHAR[k_pszTemp]; INT cch = 0; va_list list; HRESULT hr;
if (pszTemp == NULL) { MEM_ERR; goto End; }
if (szFormat == NULL) { ASSERT(FALSE); goto End; }
va_start(list, szFormat); hr = StringCchVPrintf(pszTemp, k_pszTemp, szFormat, list);
if (hr != S_OK) { DBGPRINT((sdlError,("CSTRING::Sprintf"), ("%s"), TEXT("Too long for StringCchVPrintf()"))); goto End; }
pszTemp[k_pszTemp - 1] = 0;
SetString(pszTemp);
End: if (pszTemp) { delete[] pszTemp; pszTemp = NULL; } }
UINT CSTRING::Trim( void ) /*++
CSTRING::Trim
Desc: Removes white spaces tabs from the left and right of this string
Params: void
Return: The length of the final string --*/ { CSTRING szTemp = *this; UINT uOrig_length = Length(); WCHAR* pStart = szTemp.pszString; WCHAR* pEnd = szTemp.pszString + uOrig_length - 1; UINT nLength = 0;
if (pStart == NULL) { nLength = 0; goto End; }
while (*pStart == TEXT(' ') || *pStart == TEXT('\t')) { ++pStart; }
while ((pEnd >= pStart) && (*pEnd == TEXT(' ') || *pEnd == TEXT('\t'))) { --pEnd; }
*(pEnd + 1) = TEXT('\0');
nLength = pEnd - pStart + 1;
//
// If no trimming has been done, return right away
//
if (uOrig_length == nLength || pStart == szTemp.pszString) { return nLength; }
SetString(pStart);
End: return(nLength); }
BOOL CSTRING::SetChar( IN int nPos, IN TCHAR chValue ) /*++
CSTRING::SetChar
Desc: Sets the character at position nPos of the string to chValue Pos is 0 based
Params: IN int nPos: The position IN TCHAR chValue: The new value
Return: TRUE: Successful FALSE: Otherwise --*/ { int length = Length();
if (nPos >= length || nPos < 0 || length <= 0) { return FALSE; }
pszString[nPos] = chValue; return TRUE; }
BOOL CSTRING::GetChar( IN int nPos, OUT TCHAR* pchReturn ) /*++
CSTRING::GetChar Desc: Gets the character at position nPos in the string
Params: IN int nPos: The position of the character OUT TCHAR* pchReturn: This will store the character
Return: void --*/ {
int length = Length();
if (nPos >= length || length <= 0 || pchReturn == NULL) { return FALSE; }
*pchReturn = pszString[nPos];
return TRUE; }
CSTRING CSTRING::SpecialCharToXML( IN BOOL bApphelpMessage ) /*++
CSTRING::SpecialCharToXML
Desc: Substitutes the special chars such as & with the correct XML string Please note that this function returns a new string and DOES NOT modify the existing string
Params: IN BOOL bApphelpMessage: Whether this is an apphelp message. For apphelp messages we should NOT check for <, > but check for &, "
Return: The new string if we made some changes, otherwise the present string --*/
{ TCHAR* pszBuffer = NULL; TCHAR* pszIndex = pszString; TCHAR* pszIndexBuffer = NULL; BOOL bFound = FALSE; CSTRING strTemp; INT iRemainingsize; INT iBuffSize = 0;
strTemp = GetString(IDS_UNKNOWN);
//
// Some vendor names might be NULL.
//
if (pszString == NULL) { return strTemp; }
iBuffSize = max((Length() + 1) * sizeof(TCHAR) * 2, MAX_STRING_SIZE); // 2 at the end because some special chars may need to be expanded
pszBuffer = new TCHAR[iBuffSize];
if (pszBuffer == NULL) { MEM_ERR; return *this; }
pszIndexBuffer = pszBuffer;
iRemainingsize = iBuffSize / sizeof(TCHAR);
INT iCount = sizeof(g_rgSpecialCharMap) / sizeof(g_rgSpecialCharMap[0]);
while (*pszIndex) {
INT iArrayIndex = 0;
for (iArrayIndex = 0; iArrayIndex < iCount; ++iArrayIndex) {
if (bApphelpMessage && (*pszIndex == TEXT('>') || *pszIndex == TEXT('<'))) { //
// Apphelp messages can have <P/> and <BR/>, so we should not change them
//
continue; }
if (g_rgSpecialCharMap[iArrayIndex][0].szString[0] == *pszIndex) {
bFound = TRUE; SafeCpyN(pszIndexBuffer, g_rgSpecialCharMap[iArrayIndex][1].szString, iRemainingsize);
iRemainingsize = iRemainingsize - g_rgSpecialCharMap[iArrayIndex][1].iLength;
if (iRemainingsize <= 1) { //
// No space in buffer now
//
//
// If we did not manage to copy the entire substring, make sure that we do not copy a part. This will
// be an invalid XML
//
*pszIndexBuffer = 0; goto End; }
pszIndexBuffer += g_rgSpecialCharMap[iArrayIndex][1].iLength; break; } }
if (iArrayIndex == iCount) { //
// This is not a special char
//
*pszIndexBuffer = *pszIndex; iRemainingsize = iRemainingsize - 1;
if (iRemainingsize <= 1) { //
// No space in buffer now
//
//
// Point to the end of the buffer, we will be nulling it at the end
//
pszIndexBuffer = pszBuffer + (iBuffSize / sizeof(TCHAR)) - 1; goto End; }
++pszIndexBuffer; }
pszIndex++; }
End: if (pszIndexBuffer) { *pszIndexBuffer = 0; }
if (bFound) { //
// Some special chars were found
//
strTemp = pszBuffer;
if (pszBuffer) { delete[] pszBuffer; pszBuffer = NULL; }
return strTemp; }
//
// Free the allocated buffer
//
if (pszBuffer) { delete[] pszBuffer; pszBuffer = NULL; }
return *this; }
TCHAR* CSTRING::XMLToSpecialChar( void ) /*++
CSTRING::XMLToSpecialChar
Desc: Substitutes the strings such as & with the normals characters such as & Please note that this function DOES modify the existing string
Params: void
Return: The pointer to the pszString member of this string --*/ {
if (pszString == NULL) { assert(FALSE); Dbg(dlError, "CSTRING::XMLToSpecialChar - Invalid value of memeber pszString"); return NULL; }
TCHAR* pszBuffer = NULL; TCHAR* pszIndex = pszString; TCHAR* pszEnd = pszString + Length() - 1; TCHAR* pszIndexBuffer = NULL; BOOL bFound = FALSE; INT iRemainingsize; INT iBuffSize = 0;
iBuffSize = (Length() + 1) * sizeof(TCHAR);
pszBuffer = new TCHAR[iBuffSize];
if (pszBuffer == NULL) { MEM_ERR; return *this; }
pszIndexBuffer = pszBuffer;
iRemainingsize = iBuffSize / sizeof(TCHAR);
const INT iCount = sizeof(g_rgSpecialCharMap) / sizeof(g_rgSpecialCharMap[0]);
while (*pszIndex) {
INT iArrayIndex = 0;
for (iArrayIndex = 0; iArrayIndex < iCount; ++iArrayIndex) {
if (pszIndex + g_rgSpecialCharMap[iArrayIndex][1].iLength > pszEnd) { continue; }
if (StrCmpNI(pszIndex, g_rgSpecialCharMap[iArrayIndex][1].szString, g_rgSpecialCharMap[iArrayIndex][1].iLength) == 0) {
bFound = TRUE;
SafeCpyN(pszIndexBuffer, g_rgSpecialCharMap[iArrayIndex][0].szString, iRemainingsize);
iRemainingsize = iRemainingsize - g_rgSpecialCharMap[iArrayIndex][0].iLength;
if (iRemainingsize <= 1) { //
// No space in buffer now
//
//
// Point to the end of the buffer, we will be nulling it at the end
//
pszIndexBuffer = pszBuffer + (iBuffSize / sizeof(TCHAR)) - 1; goto End; }
pszIndexBuffer += g_rgSpecialCharMap[iArrayIndex][0].iLength; pszIndex += g_rgSpecialCharMap[iArrayIndex][1].iLength;
break; } }
if (iArrayIndex == iCount) { //
// This is not XML for any special char
//
*pszIndexBuffer = *pszIndex++;
iRemainingsize = iRemainingsize - 1;
if (iRemainingsize <= 1) { //
// No space in buffer now
//
//
// Point to the end of the buffer, we will be nulling it at the end
//
pszIndexBuffer = pszBuffer + (iBuffSize / sizeof(TCHAR)) - 1; goto End; }
++pszIndexBuffer; } }
End: if (pszIndexBuffer) { *pszIndexBuffer = 0; }
if (bFound) { *this = pszBuffer; } //
// Free the allocated buffer
//
if (pszBuffer) { delete[] pszBuffer; pszBuffer = NULL; }
return this->pszString; }
BOOL CSTRING::BeginsWith( IN LPCTSTR pszPrefix ) /*++
CSTRING::BeginsWith
Desc: Checks if the string begins with a prefix Comparison is case insensitive
Params: IN LPCTSTR pszPrefix: The prefix that we want to check for
Return: TRUE: The string begins with the prefix FALSE: Otherwise --*/ { if (StrStrI(this->pszString, pszPrefix) == this->pszString) { return TRUE; }
return FALSE; }
BOOL CSTRING::EndsWith( IN LPCTSTR pszPrefix ) /*++
CSTRING::EndsWith
Desc: Checks if the string ends with some suffix
Params: IN LPCTSTR pszPrefix: The suffix that we want to check for
Return: TRUE: The string ends with the suffix FALSE: Otherwise --*/ { return EndsWith(pszString, pszPrefix); }
BOOL CSTRING::EndsWith( IN LPCTSTR pszString, IN LPCTSTR pszSuffix ) /*++
CSTRING::EndsWith
Desc: Checks if the string ends with some suffix
Params: IN LPCTSTR pszString: The string for which we want to make this check IN LPCTSTR pszSuffix: The suffix that we want to check for
Return: TRUE: The string ends with the suffix FALSE: Otherwise --*/ {
INT iLengthStr = lstrlen(pszString); INT iLengthSuffix = lstrlen(pszSuffix);
if (iLengthSuffix > iLengthStr) { return FALSE; }
return((lstrcmpi(pszString + (iLengthStr - iLengthSuffix), pszSuffix) == 0) ? TRUE: FALSE); }
LPCTSTR CSTRING::Strcat( IN CSTRING& szStr ) /*++
CSTRING::Strcat Desc: String concatenations
Params: IN CSTRING& szStr: The string to concatenate
Return: The resultant string --*/ { return Strcat((LPCTSTR)szStr); }
LPCTSTR CSTRING::Strcat( IN LPCTSTR pString ) /*++
CSTRING::Strcat Desc: String concatenations
Params: IN CSTRING& szStr: The string to concatenate
Return: The resultant string --*/ { if (pString == NULL) { return pszString; }
int nLengthCat = lstrlen(pString); int nLengthStr = Length(); TCHAR *szTemp = new TCHAR [nLengthStr + nLengthCat + 1];
if (szTemp == NULL) { MEM_ERR; return NULL; }
szTemp[0] = 0;
//
// Copy only if pszString != NULL. Otherwise we will get mem exception/garbage value
//
if (nLengthStr) { SafeCpyN(szTemp, pszString, nLengthStr + 1); }
SafeCpyN(szTemp + nLengthStr, pString, nLengthCat + 1);
szTemp[nLengthStr + nLengthCat] = TEXT('\0');
Release(); pszString = szTemp;
return pszString; }
BOOL CSTRING::isNULL( void ) /*++
CSTRING::isNULL
Desc: Checks if the pszString parameter is NULL
Params: void
Return: TRUE: The pszString parameter is NULL FALSE: Otherwise --*/ { return(this->pszString == NULL); }
inline int CSTRING::Length( void ) /*++
CSTRING::Length Desc: Gets the length of the string in TCHARS
Params: void
Return: The length of the string in TCHARS --*/ { if (NULL == pszString) { return 0; }
return lstrlen(pszString); }
CSTRING& CSTRING::ShortFilename( void ) /*++
CSTRING::ShortFilename
Desc: Gets the filename and the exe part from a path Modifies the string
Params: void
Return: Filename and the exe part of the path --*/ { TCHAR szTemp[MAX_PATH_BUFFSIZE]; LPTSTR pszHold = NULL;
if (pszString == NULL) { goto End; }
*szTemp = 0;
SafeCpyN(szTemp, pszString, ARRAYSIZE(szTemp));
LPTSTR szWalk = szTemp;
pszHold = szWalk;
while (0 != *szWalk) { if (TEXT('\\') == *szWalk) { pszHold = szWalk + 1; }
++szWalk; }
SetString(pszHold);
End: return *this; }
BOOL CSTRING::RelativeFile( CSTRING& szPath ) /*++
CSTRING::RelativeFile
Desc: If this string contains a complete path, gets the relative path w.r.t to some other complete path. Modifies this string
Params: CSTRING& szPath: The other path w.r.t to which we have to get the relative path
Return: --*/ { return RelativeFile((LPCTSTR)szPath); }
//
// BUGBUG : consider using shlwapi PathRelativePathTo
//
BOOL CSTRING::RelativeFile( LPCTSTR pExeFile ) /*++
CSTRING::RelativeFile
Desc: If this string contains a complete path, gets the relative path w.r.t to some other complete path. Modifies this string
Params: CSTRING& szPath: The other path w.r.t to which we have to get the relative path
Return: --*/ { if (pExeFile == NULL) { assert(FALSE); return FALSE; }
LPCTSTR pMatchFile = pszString; int nLenExe = 0; int nLenMatch = 0; LPCTSTR pExe = NULL; LPCTSTR pMatch = NULL; LPTSTR pReturn = NULL; BOOL bCommonBegin = FALSE; // Indicates if the paths have a common beginning
LPTSTR resultIdx = NULL; TCHAR result[MAX_PATH * 2]; INT iLength = 0;
resultIdx = result; *result = TEXT('\0');
iLength = lstrlen(pExeFile);
if (iLength > min(MAX_PATH, ARRAYSIZE(result) - 1)) { assert(FALSE); Dbg(dlError, "CSTRING::RelativeFile", "Length of passed file name greater than size of buffer"); return FALSE; }
//
// Ensure that the beginning of the path matches between the two files
//
// BUGBUG this code has to go -- look into replacing this with Shlwapi PathStripPath
//
//
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) {
//_tcsncpy(resultIdx, TEXT("..\\"), ARRAYSIZE(result) - (resultIdx - result));
SafeCpyN(resultIdx, TEXT("..\\"), ARRAYSIZE(result) - (resultIdx - result)); resultIdx = resultIdx + 3; pExeFile = pExe + 1; pExe = _tcschr(pExeFile, TEXT('\\')); }
//_tcsncpy(resultIdx, pMatchFile, ARRAYSIZE(result) - (resultIdx - result));
SafeCpyN(resultIdx, pMatchFile, ARRAYSIZE(result) - (resultIdx - result));
SetString(result);
} else {
return FALSE; }
return TRUE;
}
inline TCHAR* CSTRING::Replace( IN PCTSTR pszToFind, IN PCTSTR pszWith ) /*++
CSTRING::Replace
Desc: Replace a substring with another string. As almost all others this function is also case insensitive
Params: IN PCTSTR pszToFind: The sub string to find IN PCTSTR pszWith: Replace the above sub-string by this
Return: The pszString member --*/ { TCHAR* pszPtr = pszString; TCHAR* pszFoundPos = NULL; INT iLength = lstrlen(pszToFind); CSTRING strTemp;
while (pszFoundPos = StrStrI(pszPtr, pszToFind)) {
*pszFoundPos = 0; strTemp.Strcat(pszPtr); pszPtr = pszFoundPos + iLength; }
if (strTemp.Length()) { *this = strTemp; }
return pszString; }
///////////////////////////////////////////////////////////////////////////////
//
// Static Member Functions for CSTRING
//
//
//
TCHAR* CSTRING::StrStrI( IN PCTSTR pszString, IN PCTSTR pszMatch ) /*++
CSTRING::StrStrI
Desc: Finds a substring in this string. Not case sensitive
Params: IN PCTSTR pszString: The string in which we want to search IN PCTSTR pszMatch: The string to search
Return: If found pointer to the substring NULL: Otherwise --*/ { INT iLenghtStr = lstrlen(pszString); INT iLengthMatch = lstrlen(pszMatch);
for (INT iIndex = 0; iIndex <= iLenghtStr - iLengthMatch; ++iIndex) {
if (StrCmpNI(pszString + iIndex, pszMatch, iLengthMatch) == 0) {
return (TCHAR*)(pszString + iIndex); } }
return NULL; }
INT CSTRING::Trim( IN OUT LPTSTR str ) /*++
CSTRING::Trim
Desc: Removes white spaces tabs from the left and right of this string
Params: IN OUT LPTSTR str: The string to trim
Return: The length of the final string --*/ { UINT nLength = 0; UINT uOrig_length = lstrlen(str); // Original length
TCHAR* pStart = str; TCHAR* pEnd = str + uOrig_length - 1;
if (str == NULL) { return 0; }
while (*pStart == TEXT(' ') || *pStart == TEXT('\t')) { ++pStart; }
while ((pEnd >= pStart) && (*pEnd == TEXT(' ') || *pEnd == TEXT('\t'))) { --pEnd; }
*(pEnd + 1) = TEXT('\0');
nLength = pEnd - pStart + 1;
//
// If no trimming has been done, return right away
//
if (uOrig_length == nLength || pStart == str) { //
// In case of RTRIM we are putting in the NULL char appropriately
//
return nLength; }
wmemmove(str, pStart, (nLength + 1)); // + 1 for the 0 character.
return(nLength); }
///////////////////////////////////////////////////////////////////////////////
//
// The CSTRINGLIST member functions
//
//
CSTRINGLIST::CSTRINGLIST() /*++
CSTRINGLIST::CSTRINGLIST
Desc: Constructor --*/ { m_pHead = NULL; m_pTail = NULL; m_uCount = 0; }
CSTRINGLIST::~CSTRINGLIST() /*++
CSTRINGLIST::~CSTRINGLIST
Desc: Destructor --*/ {
DeleteAll(); }
BOOL CSTRINGLIST::IsEmpty( void ) /*++
CSTRINGLIST::IsEmpty
Desc: Checks if there are elements in the string list
Params: void
Return: TRUE: There are no elements in the string list FALSE: Otherwise --*/ { if (m_pHead == NULL) { assert (m_pTail == NULL); return TRUE; } else { assert(m_pTail != NULL); }
return FALSE; }
void CSTRINGLIST::DeleteAll( void ) /*++
CSTRINGLIST::DeleteAll
Desc: Removes all the elements in this string list --*/ { while (NULL != m_pHead) { PSTRLIST pHold = m_pHead->pNext; delete m_pHead; m_pHead = pHold; }
m_pTail = NULL; m_uCount = 0; }
BOOL CSTRINGLIST::AddString( IN CSTRING& Str, IN int data // (0)
) /*++
CSTRINGLIST::AddString
Desc: Adds a CSTRING to the end of this string list
Params: IN CSTRING& Str: The CSTRING to add IN int data (0): The data member. Please see STRLIST in CSTRING.H
Return: TRUE: Successful FALSE: Otherwise --*/ { return AddString((LPCTSTR)Str, data); }
BOOL CSTRINGLIST::AddStringAtBeg( IN LPCTSTR lpszStr, IN int data // (0)
) /*++
CSTRINGLIST::AddStringAtBeg
Desc: Adds a CSTRING to the beginning of this string list
Params: IN CSTRING& Str: The CSTRING to add IN int data (0): The data member. Please see STRLIST in CSTRING.H
Return: TRUE: Successful FALSE: Otherwise --*/ { PSTRLIST pNew = new STRLIST;
if (NULL == pNew) { MEM_ERR; return FALSE; }
pNew->data = data; pNew->szStr = lpszStr;
pNew->pNext = m_pHead; m_pHead = pNew;
if (m_pTail == NULL) { m_pTail = m_pHead; }
++m_uCount;
return TRUE; }
BOOL CSTRINGLIST::AddStringInOrder( IN LPCTSTR pStr, IN int data // (0)
) /*++
CSTRINGLIST::AddStringInOrder
Desc: Adds a string in a sorted fashion, sorted by the data member. Please see STRLIST in CSTRING.H
Params: IN LPCTSTR pStr: The string to add IN int data (0): The data member. Please see STRLIST in CSTRING.H
Return: TRUE: Successful FALSE: Otherwise --*/ { PSTRLIST pTemp, pPrev; PSTRLIST pNew = new STRLIST;
if (NULL == pNew) { MEM_ERR; return FALSE; }
pNew->data = data; pNew->szStr = pStr;
pTemp = m_pHead; pPrev = NULL;
while (pTemp) {
if (data < pTemp->data && (pPrev == NULL || data >= pPrev->data)) { break; }
pPrev = pTemp; pTemp = pTemp->pNext; }
if (pPrev == NULL) { //
// Add it to the beg, smallest number
//
pNew->pNext = m_pHead; m_pHead = pNew;
} else { //
// Add somewhere in the middle or end
//
pNew->pNext = pTemp; pPrev->pNext = pNew; }
if (pTemp == NULL) { //
// largest number.
//
m_pTail = pNew; }
if (m_pTail == NULL) { //
// Added first element
//
m_pTail = m_pHead; }
++m_uCount; return TRUE; }
BOOL CSTRINGLIST::GetElement( IN UINT uPos, OUT CSTRING& str ) /*++
CSTRINGLIST::GetElement
Desc: Gets the element at a given position in the string list The position of the first string is 0
Params: IN UINT uPos: The position OUT CSTRING& str: This will contain the CSTRING at that position
Return: TRUE: Successful FALSE: Otherwise --*/ { PSTRLIST pHead = m_pHead; UINT uIndex = 0;
while (pHead && uIndex != uPos) { pHead = pHead->pNext; ++uIndex; }
if (uIndex == uPos) { str = pHead->szStr; return TRUE;
} else { return FALSE; } }
BOOL CSTRINGLIST::AddString( IN LPCTSTR pStr, IN int data // (0)
) /*++
CSTRINGLIST::AddString
Desc: Adds a string to the end of this string list
Params: IN LPCTSTR pStr: The string to add IN int data (0): The data member. Please see STRLIST in CSTRING.H
Return: TRUE: Successful FALSE: Otherwise --*/ { PSTRLIST pNew = new STRLIST;
if (NULL == pNew) { MEM_ERR; return FALSE; }
pNew->data = data; pNew->szStr = pStr; pNew->pNext = NULL;
if (NULL == m_pTail) { m_pHead = m_pTail = pNew; } else { m_pTail->pNext = pNew; m_pTail = pNew; }
++m_uCount; return TRUE; }
CSTRINGLIST& CSTRINGLIST::operator = ( IN CSTRINGLIST& strlTemp ) /*++
CSTRINGLIST::operator = Desc: Assigns one string list to another
Params: CSTRINGLIST& strlTemp: The right hand side of the = operator
Return: This string list --*/ { PSTRLIST tempHead = NULL;
DeleteAll();
tempHead = strlTemp.m_pHead;
while (tempHead) {
AddString(tempHead->szStr, tempHead->data); tempHead = tempHead->pNext; }
return *this; }
BOOL CSTRINGLIST::operator != ( IN CSTRINGLIST &strlTemp ) /*++
CSTRINGLIST::operator != Desc: Cheks if two string lists are different
Params: CSTRINGLIST& strlTemp: The right hand side of the != operator
Return: TRUE: The string lists are different FALSE: The two string lists are similar --*/ { return(! (*this == strlTemp)); }
BOOL CSTRINGLIST::operator == ( IN CSTRINGLIST &strlTemp ) /*++
CSTRINGLIST::operator ==
Desc: Presently we check that the two stringlists are in the exact order. e.g if string A = {x, y} and string B = {x, y} this function will return TRUE but if string B = {y, x} then this function will return FALSE. Their corresponding data members should also match
Params: CSTRINGLIST& strlTemp: The right hand side of the == operator
Return: TRUE: The string lists are similar FALSE: The two string lists are different --*/ { PSTRLIST tempHeadOne = m_pHead; PSTRLIST tempHeadTwo = strlTemp.m_pHead;
if (m_uCount != strlTemp.m_uCount) { Dbg(dlInfo, "CSTRINGLIST::operator == ", "Lengths are different for the two stringlists so we will return FALSE"); return FALSE; }
while (tempHeadOne && tempHeadTwo) {
if (!(tempHeadOne->szStr == tempHeadTwo->szStr && tempHeadOne->data == tempHeadTwo->data)) { return FALSE; }
tempHeadOne = tempHeadOne->pNext; tempHeadTwo = tempHeadTwo->pNext; } return TRUE; }
BOOL CSTRINGLIST::Remove( IN CSTRING &str ) /*++
CSTRINGLIST::Remove
Desc: Removes the element with CSTRING value of str from this string list
Params: IN CSTRING &str: The CSTRING to remove
Return: --*/ { PSTRLIST pHead = m_pHead, pPrev = NULL;
while (pHead) {
if (pHead->szStr == str) { break; }
pPrev = pHead; pHead = pHead->pNext; }
if (pHead) {
if (pPrev == NULL) { //
// First element.
//
m_pHead = pHead->pNext; } else { pPrev->pNext = pHead->pNext; } if (pHead == m_pTail) { //
// Last element
//
m_pTail = pPrev; }
delete pHead; pHead = NULL;
--m_uCount;
return TRUE; }
return FALSE; }
void CSTRINGLIST::RemoveLast( void ) /*++
CSTRINGLIST::RemoveLast
Desc: Removes the last element from this string list
Params: void
Return: void --*/ { if (m_pTail) { Remove(m_pTail->szStr); } }
|