/*=========================================================================== * * File: SString.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Tuesday, May 08, 2001 * * Contains the implementation for the simple string class CSString. * *=========================================================================*/ /* Include Files */ #include "sstring.h" #include <ctype.h> #include <limits.h> /*=========================================================================== * * Begin Local Variable Definitions * *=========================================================================*/ DEFINE_FILE(); /*=========================================================================== * End of Local Variable Definitions *=========================================================================*/ /*=========================================================================== * * Class CSString Constructor - CSString (pSrcString); * * Uses the given character buffer to initialize the string. Handles the * NULL input string case. * *=========================================================================*/ CSString::CSString (const char* pSrcString) { //DEFINE_FUNCTION("CSString::CSString(char*)"); /* Initialize the member variables */ m_Length = 0; m_AllocLength = 0; m_pString = NULL; /* Check for the NULL case */ if (pSrcString == NULL) { AllocString(0); *m_pString = NULL_CHAR; } /* Create a normally sized string */ else { AllocString(strlen(pSrcString)); strcpy(m_pString, pSrcString); } } /*=========================================================================== * End of Class CSString Constructor *=========================================================================*/ /*=========================================================================== * * Class CSString Constructor - CSString (pSrcString, SrcLength); * * Uses the given character buffer to initialize the string, up to the * given length. Handles the NULL input string case. * *=========================================================================*/ CSString::CSString (const char* pSrcString, const size_t SrcLength) { //DEFINE_FUNCTION("CSString::CSString(char*, size_t)"); /* Initialize the member variables */ m_Length = 0; m_AllocLength = 0; m_pString = NULL; /* Check for the NULL case */ if (pSrcString == NULL) { AllocString(SrcLength); *m_pString = NULL_CHAR; m_Length = 0; } /* Create a normally sized string */ else { size_t InputLength = strlen(pSrcString); AllocString(SrcLength); strnncpy(m_pString, pSrcString, SrcLength); if (InputLength < SrcLength) m_Length = InputLength; } } /*=========================================================================== * End of Class CSString Constructor *=========================================================================*/ /*=========================================================================== * * Class CSString Constructor - CSString (SrcString); * * Uses the given CSString object to initialize the string. * *=========================================================================*/ CSString::CSString (const CSString& SrcString) { //DEFINE_FUNCTION("CSString::CSString(CSString&)"); /* Initialize the member variables */ m_Length = 0; m_AllocLength = 0; m_pString = NULL; /* Copy the source string */ AllocString(SrcString.GetLength()); strcpy(m_pString, (char*) SrcString); } /*=========================================================================== * End of Class CSString Constructor *=========================================================================*/ /*=========================================================================== * * Class CSString Constructor - CSString (StringSize); * * Creates an empty string with the given number of bytes. String is * initially composed of all space characters. * *=========================================================================*/ CSString::CSString (const size_t StringSize) { //DEFINE_FUNCTION("CSString::CSString(size_t)"); /* Initialize the member variables */ m_Length = 0; m_AllocLength = 0; m_pString = NULL; /* Copy the source string */ AllocString(StringSize); memset(m_pString, ' ', StringSize); m_pString[StringSize] = NULL_CHAR; } /*=========================================================================== * End of Class CSString Constructor *=========================================================================*/ /*=========================================================================== * * Class CSString Constructor - CSString (Char, Count); * * Creates a multiple character string. ASSERTs on invalid input. * *=========================================================================*/ CSString::CSString (const char Char, const size_t Count) { //DEFINE_FUNCTION("CSString::CSString(char, size_t)"); /* Initialize the member variables */ m_Length = 0; m_AllocLength = 0; m_pString = NULL; /* Allocate and create the string */ AllocString((size_t)Count); memset(m_pString, (int)Char, Count); m_pString[m_Length] = NULL_CHAR; } /*=========================================================================== * End of Class Method CSString& CSString::operator=() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - void AllocString (StringSize); * * Protected class method which allocates a new string buffer for the * given size, if the string doesn't fit in the currently allocated * buffer. String is not initialized. * *=========================================================================*/ void CSString::AllocString (const size_t StringSize) { DEFINE_FUNCTION("CSString::AllocString()"); /* Check for integer wrap arounds */ ASSERT(StringSize < UINT_MAX - SSTRING_ALLOC_EXTRA - 1); /* Do we need to allocate a new buffer */ if (StringSize > m_AllocLength || m_pString == NULL) { DestroyArrayPointer(m_pString); m_AllocLength = StringSize + SSTRING_ALLOC_EXTRA; m_Length = StringSize; m_pString = (char *) AllocateMemory(m_AllocLength + 1); } else { m_Length = StringSize; } /* Ensure valid output */ ASSERT(m_pString != NULL); ASSERT(m_Length <= m_AllocLength); } /*=========================================================================== * End of Class Method CSString::AllocString() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - void AllocCopy (StringSize); * * Protected class method which allocates a copy of the the current * string buffer with the given size, if the new size doesn't fit in the * currently allocated buffer. Thus, all that possibly changes is * the allocated string length. * *=========================================================================*/ void CSString::AllocCopy (const size_t StringSize) { DEFINE_FUNCTION("CSString::AllocCopy()"); /* Check for integer wrap arounds */ ASSERT(StringSize < (size_t)(UINT_MAX - SSTRING_ALLOC_EXTRA - 1)); /* Do we need to allocate a new buffer */ if (StringSize > m_AllocLength) { char* pNewString; /* Allocate the new string buffer */ m_AllocLength = StringSize + SSTRING_ALLOC_EXTRA; pNewString = (char *) AllocateMemory(m_AllocLength + 1); /* Copy the old buffer to the new then destroy the old */ strcpy (pNewString, m_pString); DestroyPointer(m_pString); m_pString = pNewString; } /* Ensure valid output */ ASSERT(m_pString != NULL); ASSERT(m_Length <= m_AllocLength); } /*=========================================================================== * End of Class Method CSString::AllocCopy() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - void ConcatStrings (String1Size, pString1, * String2Size, pString2); * * Protected class method used by the friend operator+() functions. * Creates a concatenation of pString1+pString2. Handles NULL and * zero length strings. * *=========================================================================*/ void CSString::ConcatStrings (const size_t String1Size, const char* pString1, const size_t String2Size, const char* pString2) { DEFINE_FUNCTION("CSString::ConcatStrings()"); size_t NewSize; /* Ensure the strings can combine to produce a valid size */ ASSERT(String1Size < (size_t)(UINT_MAX - String2Size)); NewSize = String1Size + String2Size; /* Create a buffer larger enough to hold the new string */ AllocString(NewSize); /* Create the new string */ if (pString1 != NULL && String1Size != 0) memmove(m_pString, pString1, String1Size); if (pString2 != NULL && String2Size != 0) memmove(m_pString + String1Size, pString2, String2Size); m_pString[NewSize] = NULL_CHAR; } /*=========================================================================== * End of Class Method CSString::ConcatStrings() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - void Empty (void); * * Deletes the current string contents, reallocating an empty string. * *=========================================================================*/ void CSString::Empty (void) { DEFINE_FUNCTION("CSString::Empty()"); if (m_Length != 0) { DestroyPointer(m_pString); AllocString(0); *m_pString = NULL_CHAR; } /* Ensure success */ ASSERT(m_Length == 0); ASSERT(*m_pString == NULL_CHAR); } /*=========================================================================== * End of Class Method CSString::Empty() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - void FreeExtra (void); * * Ensures that the allocated and string lengths are equal, removing any * extra allocated buffer from the end of the string. * *=========================================================================*/ void CSString::FreeExtra (void) { DEFINE_FUNCTION("CSString::FreeExtra()"); char* pNewString; /* Ensure valid input */ ASSERT(m_pString != NULL); ASSERT(m_Length <= m_AllocLength); /* Create an allocated string the exact size of the current buffer */ if (m_Length != m_AllocLength) { pNewString = CreateString(m_Length); strcpy(pNewString, m_pString); DestroyPointer(m_pString) m_AllocLength = m_Length; m_pString = pNewString; } } /*=========================================================================== * End of Class Method CSString::FreeExtra() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - CSString& TrimLeft (void); * * Trims whitespace from the left side of the string (according to the * isspace() function). * *=========================================================================*/ CSString& CSString::TrimLeft (void) { DEFINE_FUNCTION("CSString::TrimLeft()"); size_t StringIndex = 0; /* Find the first non-whitespace character from left side of string */ while (m_pString[StringIndex] != NULL_CHAR) { if (!isspace(m_pString[StringIndex])) break; StringIndex++; } /* Shift the string, if required, to remove whitespace */ if (StringIndex != 0) { memmove(m_pString, m_pString + StringIndex, m_Length - StringIndex + 1); m_Length -= StringIndex; } ASSERT(m_pString[m_Length] == NULL_CHAR); return (*this); } /*=========================================================================== * End of Class Method CSString::TrimLeft() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - CSString& TrimRight (void); * * Trims whitespace from the right side of the string (according to the * isspace() function). * *=========================================================================*/ CSString& CSString::TrimRight (void) { DEFINE_FUNCTION("CSString::TrimRight()"); size_t StringIndex = m_Length; /* Find the first non-whitespace character from right side of string */ while (StringIndex != 0) { StringIndex--; if (!isspace(m_pString[StringIndex])) break; } /* Terminate the string at the last non-whitespace char */ if (StringIndex != m_Length) { m_pString[StringIndex + 1] = NULL_CHAR; m_Length = StringIndex; } ASSERT(m_pString[m_Length] == NULL_CHAR); return (*this); } /*=========================================================================== * End of Class Method CSString::TrimRight() *=========================================================================*/ /*=========================================================================== * * Class CSString& CSString Method - operator= (SrcString); * * Copies the given source string to the current object. * *=========================================================================*/ const CSString& CSString::operator= (const CSString& SrcString) { //DEFINE_FUNCTION("CSString::operator=(CSString&)"); AllocString(SrcString.GetLength()); strcpy(m_pString, (char*)SrcString); return (*this); } /*=========================================================================== * End of Class Method CSString& CSString::operator=() *=========================================================================*/ /*=========================================================================== * * Class CSString& CSString Method - operator= (Char); * * Creates a one character string. * *=========================================================================*/ const CSString& CSString::operator= (const char Char) { //DEFINE_FUNCTION("CSString::operator=(char)"); AllocString(1); m_pString[0] = Char; m_pString[1] = NULL_CHAR; return (*this); } /*=========================================================================== * End of Class Method CSString& CSString::operator=() *=========================================================================*/ /*=========================================================================== * * Class CSString& CSString Method - operator= (pSrcString); * * Copies the given string buffer to the current object. Handles the * NULL string case. * *=========================================================================*/ const CSString& CSString::operator= (const char* pSrcString) { //DEFINE_FUNCTION("CSString::operator=(char*)"); /* Check for the NULL string case */ if (pSrcString == NULL) { AllocString(0); *m_pString = NULL_CHAR; } /* Create a normally sized string */ else { AllocString(strlen(pSrcString)); strcpy(m_pString, pSrcString); } return (*this); } /*=========================================================================== * End of Class Method CSString& CSString::operator=() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - CSString& operator+= (pString); * * Concatenates the given string to the end of the string buffer. * Accepts NULL string input. * *=========================================================================*/ const CSString& CSString::operator+= (const char* pString) { DEFINE_FUNCTION("CSString::operator+=(char*)"); size_t NewLength; /* Ignore NULL inputs */ if (pString == NULL) return (*this); /* Ensure an allocated buffer of the correct length */ NewLength = strlen(pString); AllocCopy(NewLength + m_Length); /* Add the source string to the end of the buffer */ strcpy(m_pString + m_Length, pString); m_Length += NewLength; /* Ensure valid output */ ASSERT(m_pString[m_Length] == NULL_CHAR); return (*this); } /*=========================================================================== * End of Class Method CSString::operator+=() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - CSString& operator+= (SourceString); * * Concatenates the given string to the end of the string buffer. * Accepts NULL string input. * *=========================================================================*/ const CSString& CSString::operator+= (const CSString& SourceString) { DEFINE_FUNCTION("CSString::operator+=(CSString)"); /* Ensure an allocated buffer of the correct length */ AllocCopy(SourceString.GetLength() + m_Length); /* Add the source string to the end of the buffer */ strcpy(m_pString + m_Length, (const char*)SourceString); m_Length += SourceString.GetLength(); /* Ensure valid output */ ASSERT(m_pString[m_Length] == NULL_CHAR); return (*this); } /*=========================================================================== * End of Class Method CSString::operator+=() *=========================================================================*/ /*=========================================================================== * * Class CSString Method - CSString& operator+= (SourceChar); * * Concatenates the given character to the end of the string buffer. * *=========================================================================*/ const CSString& CSString::operator+= (const char SourceChar) { DEFINE_FUNCTION("CSString::operator+=(char)"); /* Ensure an allocated buffer of the correct length */ AllocCopy(m_Length + 1); /* Add the source character to the end of the buffer */ m_pString[m_Length] = SourceChar; m_Length++; m_pString[m_Length] = NULL_CHAR; /* Ensure valid output */ ASSERT(m_pString[m_Length] == NULL_CHAR); return (*this); } /*=========================================================================== * End of Class Method CSString::operator+=() *=========================================================================*/ /*=========================================================================== * * Function - CSString operator+ (String1, String2); * * Friend function to the CSString class to add two CSString objects. * *=========================================================================*/ CSString operator+ (const CSString& String1, const CSString& String2) { DEFINE_FUNCTION("operator+(CSString, CSString)"); CSString NewString; NewString.ConcatStrings(String1.GetLength(), (const char*)String1, String2.GetLength(), (const char*)String2); return (NewString); } /*=========================================================================== * End of Function operator+() *=========================================================================*/ /*=========================================================================== * * Function - CSString operator+ (pString1, String2); * * Friend function to the CSString class to add a string pointer with * a CSString object. * *=========================================================================*/ CSString operator+ (const char* pString1, const CSString& String2) { DEFINE_FUNCTION("operator+(char*, CSString)"); CSString NewString; NewString.ConcatStrings(SafeStrLen(pString1), pString1, String2.GetLength(), (const char*)String2); return (NewString); } /*=========================================================================== * End of Function operator+() *=========================================================================*/ /*=========================================================================== * * Function - CSString operator+ (String1, pString2); * * Friend function to the CSString class to add a string pointer with * a CSString object. * *=========================================================================*/ CSString operator+ (const CSString& String1, const char* pString2) { DEFINE_FUNCTION("operator+(CSString, char*)"); CSString NewString; NewString.ConcatStrings(String1.GetLength(), (const char*)String1, SafeStrLen(pString2), pString2); return (NewString); } /*=========================================================================== * End of Function operator+() *=========================================================================*/ /*=========================================================================== * * Function - CSString operator+ (String1, Char); * * Friend function to the CSString class to add a character pointer with * a CSString object. * *=========================================================================*/ CSString operator+ (const CSString& String1, const char Char2) { DEFINE_FUNCTION("operator+(CSString, char)"); CSString NewString; NewString.ConcatStrings(String1.GetLength(), (const char*)String1, 1, &Char2); return (NewString); } /*=========================================================================== * End of Function operator+() *=========================================================================*/ /*=========================================================================== * * Function - CSString operator+ (Char, String2); * * Friend function to the CSString class to add a character pointer with * a CSString object. * *=========================================================================*/ CSString operator+ (const char Char1, const CSString& String2) { DEFINE_FUNCTION("operator+(char, CSString)"); CSString NewString; NewString.ConcatStrings(1, &Char1, String2.GetLength(), (const char*)String2); return (NewString); } /*=========================================================================== * End of Function operator+() *=========================================================================*/