Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1619 lines
32 KiB

/*++
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 &amp; 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);
}
}