/*===========================================================================
 *
 * File:	SString.H
 * Author:	Dave Humphrey (uesp@m0use.net)
 * Created On:	Tuesday, May 08, 2001
 *
 * Contains the definition for the CSString class for handling simple
 * strings.
 *
 *=========================================================================*/
#ifndef __SSTRING_H
#define __SSTRING_H


/*===========================================================================
 *
 * Begin Required Includes
 *
 *=========================================================================*/
  #include "dl_base.h"
  #include "dl_mem.h"
  #include "dl_str.h"
/*===========================================================================
 *		End of Required Includes
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Definitions
 *
 *=========================================================================*/

	/* Number of extra bytes to allocate when creating strings */
  #define SSTRING_ALLOC_EXTRA 32

/*===========================================================================
 *		End of Definitions
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Class CSString Definition
 *
 * A simple class for handling strings. 
 *
 *=========================================================================*/
class CSString {

  /*---------- Begin Private Class Members ----------------------*/
private:
  char*  m_pString;	/* The string pointer */
  size_t m_Length;	/* The size of the string */
  size_t m_AllocLength;	/* The number of allocated string bytes */


  /*---------- Begin Protected Class Methods --------------------*/
protected:

	/* Allocate string buffers of a given size */
  void AllocString (const size_t StringSize);
  void AllocCopy   (const size_t StringSize);

	/* Create a string buffer from two source strings */
  void ConcatStrings (const size_t String1Size, const char* pString1,
		      const size_t String2Size, const char* pString2);


  /*---------- Begin Public Class Methods -----------------------*/
public:

	/* Class Constructors */
  CSString (const char*     pString = NULL);
  CSString (const char*     pString, const size_t Length);
  CSString (const CSString& SrcString);
  CSString (const size_t    StringSize);
  CSString (const char Char, const size_t Count);

	/* Class Destructors */
  virtual ~CSString();
  virtual void Destroy (void);

	/* String comparison */
  int Compare       (const char* pString) const;
  int CompareNoCase (const char* pString) const;

	/* Copy a number of characters from source strings */
  void Copy (const char*    pString, const size_t Count);
  void Copy (const CSString& String, const size_t Count);

	/* Empties the string contents */
  void Empty (void);

	/* Frees any extra memory allocated for the string */
  void FreeExtra (void);

	/* Get the length, in bytes, of the string */
  size_t GetLength      (void) const; 
  size_t GetAllocLength (void) const;

	/* Checks for an empty (zero sized) string */
  boolean IsEmpty (void);

	/* Extract sub-strings from string */
  CSString Left  (const size_t Count) const;
  CSString Mid   (const size_t Index, const size_t Count) const;
  CSString Mid   (const size_t Index) const;
  CSString Right (const size_t Count) const;

	/* Makes the string lower/upper case */
  void MakeLower (void);
  void MakeUpper (void);

  	/* Set a specific character in the string */
  void SetAt (const size_t Index, const char Char);

	/* Trims whitespace from left/right sides of string */
  CSString& TrimLeft  (void);
  CSString& TrimRight (void);
  CSString& Trim      (void);

	/* Overloaded copy operators */
  const CSString& operator= (const CSString& SrcString);
  const CSString& operator= (const char      Char);
  const CSString& operator= (const char*     pSrcString);  
  
	/* String concatenation */
  const CSString& operator+= (const CSString& String);
  const CSString& operator+= (const char      Char);
  const CSString& operator+= (const char*     pString);

	/* Addition operators, friend functions */
  friend CSString operator+ (const CSString&  String1, const CSString&  String2);
  friend CSString operator+ (const char          Char, const CSString&  String);
  friend CSString operator+ (const CSString&   String, const char       Char);
  friend CSString operator+ (const char*     pString1, const CSString&  String2);
  friend CSString operator+ (const CSString&  String1, const char*     pString2);

	/* Get a specific character from the string */
  char operator[] (const size_t Index) const;
  char GetAt      (const size_t Index) const;

	/* Return a const pointer to the string buffer */
  operator char* (void) const;

 };
/*===========================================================================
 *		End of Class CSString Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Begin Inline CSString Methods
 *
 *=========================================================================*/

	/* CSString class destructor */
inline CSString::~CSString () {
  DestroyPointer(m_pString);
 }

	/* Creates a new, empty, string */
inline void CSString::Destroy (void) {
  AllocString(0);
  *m_pString = NULL_CHAR;
 }  

	/* String comparison, case sensitive, returns as per strcmp() */
inline int CSString::Compare (const char* pString) const {
  IASSERT(pString != NULL);
  return (strcmp(m_pString, pString));
 }

	/* String comparison, case insensitive, returns as per stricmp() */
inline int CSString::CompareNoCase (const char* pString) const {
  IASSERT(pString != NULL);
  return (stricmp(m_pString, pString));
 }

	/* Creates a new string at most Count bytes in size */
inline void CSString::Copy (const char* pString, const size_t Count) {
  size_t InputSize = SafeStrLen(pString);

  AllocString(Count);
  if (pString != NULL) strncpy(m_pString, pString, Count);
  if (InputSize < Count) m_Length = InputSize;
  m_pString[m_Length] = NULL_CHAR;
 }

	/* Return the current string size */
inline size_t CSString::GetLength (void) const { 
  return (m_Length);
 }

	/* Get the current allocated size of string */
inline size_t CSString::GetAllocLength (void) const {
  return (m_AllocLength); 
 }

	/* Returns TRUE if the string is empty, "" */
inline boolean CSString::IsEmpty (void) { 
  return ((m_Length == 0) ? TRUE : FALSE); 
 }

	/* Returns a string containing the first Count characters from the
	 * left of the string object */
inline CSString CSString::Left (const size_t Count) const {
  IASSERT(Count <= m_Length);
  CSString NewString(m_pString, Count);
  return NewString;
 }

	/* Makes the string all lower/upper case */
inline void CSString::MakeLower (void) { strlwr(m_pString); }
inline void CSString::MakeUpper (void) { strupr(m_pString); }

	/* Returns a new string starting at the 0-based index of the current string */
inline CSString CSString::Mid (const size_t Index) const {
  IASSERT(Index <= m_Length);
  CSString NewString(m_pString + Index);
  return NewString;
 }

	/* Returns a new string starting at the 0-based index of the current string 
	 * with the given length. */
inline CSString CSString::Mid (const size_t Index, const size_t Length) const {
  IASSERT(Index <= m_Length);
  IASSERT(Length <= m_Length);
  IASSERT(Index + Length <= m_Length);
  CSString NewString(m_pString + Index, Length);
  return NewString;
 }

	/* Returns a string containing the first Count characters from the
	 * right side of the string object */
inline CSString CSString::Right (const size_t Count) const {
  IASSERT(Count <= m_Length);
  CSString NewString(m_pString + m_Length - Count, Count);
  return NewString;
 }

	/* Trim whitespace from right and left sides of string */
inline CSString& CSString::Trim (void) { 
  TrimLeft(); 
  TrimRight(); 
  return (*this); 
 }

	/* Access the (const char*) string */
inline CSString::operator char* (void) const {
  return (m_pString);
 }

	/* Get the specified character from the string.  ASSERTs if given an
	   invalid index (0 returns the first character in string). */
inline char CSString::operator[] (const size_t Index) const {
  return GetAt(Index);
 }

	/* Same as operator[], return a specific character in string */
inline char CSString::GetAt (const size_t Index) const {
  IASSERT(Index < m_Length);
  return (m_pString[Index]);
 }

	/* Sets a specific character in the string.  ASSERTs if an invalid
	 * index is given.  0 is the first character in string. */
inline void CSString::SetAt (const size_t Index, const char Char) {
  IASSERT(Index < m_Length);
  m_pString[Index] = Char;
 }

	/* String comparisons */
inline boolean operator== (const CSString& String1, const CSString& String2) { return (String1.Compare(String2) == 0); }
inline boolean operator== (const char*     String1, const CSString& String2) { return (String2.Compare(String1) == 0); }
inline boolean operator== (const CSString& String1, const char*     String2) { return (String1.Compare(String2) == 0); }
inline boolean operator!= (const CSString& String1, const CSString& String2) { return (String1.Compare(String2) != 0); }
inline boolean operator!= (const char*     String1, const CSString& String2) { return (String2.Compare(String1) != 0); }
inline boolean operator!= (const CSString& String1, const char*     String2) { return (String1.Compare(String2) != 0); }
inline boolean operator<= (const CSString& String1, const CSString& String2) { return (String1.Compare(String2) <= 0); }
inline boolean operator<= (const char*     String1, const CSString& String2) { return (String2.Compare(String1) >= 0); }
inline boolean operator<= (const CSString& String1, const char*     String2) { return (String1.Compare(String2) <= 0); }
inline boolean operator>= (const CSString& String1, const CSString& String2) { return (String1.Compare(String2) >= 0); }
inline boolean operator>= (const char*     String1, const CSString& String2) { return (String2.Compare(String1) <= 0); }
inline boolean operator>= (const CSString& String1, const char*     String2) { return (String1.Compare(String2) >= 0); }
inline boolean operator<  (const CSString& String1, const CSString& String2) { return (String1.Compare(String2) <  0); }
inline boolean operator<  (const char*     String1, const CSString& String2) { return (String2.Compare(String1) >  0); }
inline boolean operator<  (const CSString& String1, const char*     String2) { return (String1.Compare(String2) <  0); }
inline boolean operator>  (const CSString& String1, const CSString& String2) { return (String1.Compare(String2) >  0); }
inline boolean operator>  (const char*     String1, const CSString& String2) { return (String2.Compare(String1) <  0); }
inline boolean operator>  (const CSString& String1, const char*     String2) { return (String1.Compare(String2) >  0); }



/*===========================================================================
 *		End of Begin Inline CSString Methods
 *=========================================================================*/
      	         	

#endif
/*===========================================================================
 *		End of File Sstring.H
 *=========================================================================*/