#ifndef ECHARSTRING_H #define ECHARSTRING_H //===========================================================================// // Copyright (C) Microsoft Corporation. All rights reserved. // //===========================================================================// // Notes essentially EString, except that it uses chars (not wchars) even when UNICODE is defined // //*************************************************************** //*************************************************************** /* just for this file, we want UNICODE, K_UNICODE and MBCS undefined */ #ifdef UNICODE #define _UNICODE_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #define _PREVIOUS_UNICODE___ECHARSTRING_H UNICODE #undef UNICODE #endif /* def UNICODE */ #ifdef K_UNICODE #define _K_UNICODE_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #define _PREVIOUS_K_UNICODE___ECHARSTRING_H UNICODE #undef K_UNICODE #endif /* def K_UNICODE */ #ifdef MBCS #define _MBCS_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #define _PREVIOUS_MBCS___ECHARSTRING_H MBCS #undef MBCS #endif /* def MBCS */ //*************************************************************** #ifdef UNICODE #define ECSChar unsigned short #else #define ECSChar char #endif #include class ECharString { public: // ENUMERATIONS & CONSTANTS static const int INVALID_INDEX; // CONSTRUCTORS/DESTRUCTORS /*explicit*/ ECharString( const ECSChar* newString ); ECharString( const ECharString& ); /*explicit*/ ECharString( const ECSChar ); ECharString(); ~ECharString(); // MANIPULATORS void Replace( int Start_Index, const ECharString& String ); void Replace( int Start_Index, const ECSChar* ); bool Remove( int Start_Index, int End_Index ); bool Remove( ECharString& Sub_String ); // puts this string in the middle of another string inline void Insert( int Start_Index, const ECharString& String ); void Insert( int Start_Index, const ECSChar* String ); void Swap( ECharString& ); inline void Empty(); void MakeUpper(); void MakeLower(); void Reverse(); // works like sprintf with the destination buffer being // the this pointer void Format( const ECSChar*, ... ); inline const ECharString& operator=( const ECSChar* ); inline const ECharString& operator=( const ECharString& ); inline const ECharString& operator=( ECSChar ); inline const ECharString& operator+=( const ECSChar* ); inline const ECharString& operator+=( const ECharString& ); inline const ECharString& operator+=( ECSChar ); friend ECharString operator+( const ECharString&, const ECharString& ); friend ECharString operator+( const ECSChar*, const ECharString& ); friend ECharString operator+( const ECharString& , const ECSChar* ); friend ECharString operator+( const ECharString&, const ECSChar ); friend ECharString operator+( const ECSChar, const ECharString& ); // ACCESSORS // these are case sensitive, use Compare // if you don't want case senstitivity inline bool operator==( const ECharString& ) const; inline bool operator==( const ECSChar* ) const; inline friend bool operator==( const ECSChar*, const ECharString& ); // these functions return -1 if "this" is less than the passed in string int Compare( const ECharString&, bool Case_Sensitive = false ) const; int Compare( const ECSChar*, bool Case_Sensitive = false ) const; bool operator!=( const ECharString& ) const; bool operator!=( const ECSChar*) const; friend bool operator!=( const ECSChar*, const ECharString& ); inline ECSChar& operator[]( int Index ); inline const ECSChar& operator[](int Index) const; inline bool operator<( const ECharString& ) const; inline bool operator<( const ECSChar* ) const; inline friend bool operator<( const ECSChar*, const ECharString& ); inline bool operator<=( const ECharString& ) const; inline bool operator<=( const ECSChar*) const; inline friend bool operator<=( const ECSChar*, const ECharString&); inline bool operator>( const ECharString& ) const; inline bool operator>(const ECSChar*) const; inline friend bool operator>( const ECSChar*, const ECharString&); inline bool operator>=( const ECharString& ) const; inline bool operator>=( const ECSChar*) const; inline friend bool operator>=( const ECSChar*, const ECharString&); int Size() const; // number of bytes int Length() const; // number of characters // search functions int Find( ECSChar, int Start_Index = ECharString::INVALID_INDEX) const; int Find( const ECharString&, int Start_Index = ECharString::INVALID_INDEX) const; int Find( const ECSChar*, int Start_Index = ECharString::INVALID_INDEX) const; int ReverseFind ( ECSChar, int End_Index = ECharString::INVALID_INDEX) const; // we are going to treat this object as a TCHAR array, so we // don't have to worry about #of chars versus #of bytes ECharString SubString( int Start_Index, int End_Index ) const; inline ECharString Left( int Num_Chars) const; inline ECharString Right( int Num_Chars) const; inline bool IsEmpty() const; unsigned short* CreateUNICODE() const; char* CreateMBCS() const; inline const ECSChar* Data() const; // ALL UNICODE SPECIFIC AND #ifndef UNICODE int Find( unsigned short, int Start_Index = -1 ) const; #else // K_UNICODE // we'll convert string literals for you ECharString( const char* ); friend ECharString operator+( const ECharString&, char* ); friend ECharString operator+( char*, const ECharString& ); friend ECharString operator+( char, const ECharString& ); friend ECharString operator+( const ECharString&, char ); const ECharString& operator+=( const char* ); const ECharString& operator+=( char ); const ECharString& operator=( char ); bool operator==( const char* ); friend bool operator==( const char*, const ECharString& ); bool operator!=( const char*) const; friend bool operator!=( const char*, const ECharString& ); bool operator<( const char* ) const; friend bool operator<( const char*, const ECharString& ); bool operator>( const char* ) const; friend bool operator>( const char*, const ECharString& ); bool operator<=( const char*) const; friend bool operator<=( const char*, const ECharString&); bool operator>=( const char*) const; friend bool operator>=( const char*, const ECharString&); void Format( const char*, ... ); int Find( char, int Start_Index = ECharString::INVALID_INDEX) const; #endif // Unicode private: // helper functions // Allocates a specific amount void Alloc( int Min_Amount ); // Reallocates if you want to make a change to a shared buffer inline void ChecEBuffer(); void ChecEBufferDoRealloc(); // sets the buffer, reallocs if necessary void Assign( const ECSChar* p_Str ); static inline unsigned short* ToUnicode( unsigned short* Buffer, const unsigned char* p_Str, int Num_Chars ); static inline int StrSize( const ECSChar* p_Str ); struct EBuffer { int m_Ref_Count; // reference count int m_Data_Length; // Length of String int m_Alloc_Length; // Length of the Buffer inline ECSChar* Data(); inline void Release(); static EBuffer s_Empty_Buffer; static EBuffer* s_p_Empty_Buffer; }; EBuffer* m_pBuffer; static const int s_Alloc_Allign; static const int s_Force_Ansi; static const int s_Force_Unicode; }; //*************************************************************** // inlines ///////////////////////////////////////////////////////////////// inline void ECharString::ChecEBuffer() { if ( m_pBuffer->m_Ref_Count > 0 ) { m_pBuffer->m_Ref_Count --; m_pBuffer = EBuffer::s_p_Empty_Buffer; } } ///////////////////////////////////////////////////////////////// inline void ECharString::EBuffer::Release() { if ( this != s_p_Empty_Buffer ) { m_Ref_Count --; if ( m_Ref_Count < 0 ) { delete [] (char*)this; } } } ///////////////////////////////////////////////////////////////// inline void ECharString::Empty() { m_pBuffer->Release(); m_pBuffer = EBuffer::s_p_Empty_Buffer; } ///////////////////////////////////////////////////////////////// inline void ECharString::Insert( int Start_Index, const ECharString& String ) { Insert( Start_Index, String.m_pBuffer->Data() ); } ///////////////////////////////////////////////////////////////// inline const ECharString& ECharString::operator=( const ECSChar* p_String ) { ChecEBuffer(); Assign( p_String ); return *this; } ///////////////////////////////////////////////////////////////// inline const ECharString& ECharString::operator=( const ECharString& Src ) { if ( &Src != this ) { m_pBuffer->Release(); m_pBuffer = Src.m_pBuffer; Src.m_pBuffer->m_Ref_Count ++; } return *this; } ///////////////////////////////////////////////////////////////// inline const ECharString& ECharString::operator=( ECSChar Char ) { ChecEBuffer(); ECSChar Tmp[2]; Tmp[0] = Char; Tmp[1] = 0; Assign( Tmp ); return *this; } ///////////////////////////////////////////////////////////////// inline const ECharString& ECharString::operator+=( const ECSChar* p_String ) { Insert( m_pBuffer->m_Data_Length, p_String ); return *this; } ///////////////////////////////////////////////////////////////// inline const ECharString& ECharString::operator+=( const ECharString& String ) { Insert( m_pBuffer->m_Data_Length, String ); return *this; } ///////////////////////////////////////////////////////////////// inline const ECharString& ECharString::operator+=( ECSChar Char ) { ECSChar Tmp[2]; Tmp[0] = Char; Tmp[1] = 0; Insert( m_pBuffer->m_Data_Length, Tmp ); return *this; } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator!=( const ECharString& Str_To_Compare ) const { return !( operator==(Str_To_Compare) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator!=( const ECSChar* p_Str_To_Compare ) const { return !( operator==( p_Str_To_Compare ) ); } ///////////////////////////////////////////////////////////////// inline ECharString ECharString::Left( int Num_Chars) const { // Bill changed to Num_Chars - 1, this was always returning one character too many return SubString( 0, Num_Chars - 1 ); } ///////////////////////////////////////////////////////////////// inline ECharString ECharString::Right( int Num_Chars) const { return SubString( m_pBuffer->m_Data_Length - Num_Chars, m_pBuffer->m_Data_Length - 1 ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::IsEmpty() const { return (m_pBuffer->m_Data_Length <= 0); } ///////////////////////////////////////////////////////////////// inline const ECSChar* ECharString::Data() const { return ( m_pBuffer->Data() ); } ///////////////////////////////////////////////////////////////// inline ECSChar* ECharString::EBuffer::Data() { if ( !m_Alloc_Length ) { return 0; } return (ECSChar*)(this + 1); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator==( const ECharString& Str_To_Compare) const { return ( 0 == Compare( Str_To_Compare, true ) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator==( const ECSChar* p_String ) const { return ( 0 == Compare( p_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool operator==( const ECSChar* p_String, const ECharString& Str ) { return ( 0 == Str.Compare( p_String ) ); } ///////////////////////////////////////////////////////////////// inline bool operator!=( const ECSChar* p_String, const ECharString& Str ) { return !(Str == p_String ); } ///////////////////////////////////////////////////////////////// inline ECSChar& ECharString::operator[]( int Index ) { ChecEBufferDoRealloc(); gosASSERT( Index < m_pBuffer->m_Data_Length ); return *(m_pBuffer->Data() + Index); } ///////////////////////////////////////////////////////////////// inline const ECSChar& ECharString::operator[](int Index) const { gosASSERT( Index < m_pBuffer->m_Data_Length ); return *(m_pBuffer->Data() + Index); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator<( const ECharString& Greater_String ) const { return ( 0 > Compare( Greater_String, true)); } ///////////////////////////////////////////////////////////////// inline bool operator<( const ECSChar* p_Lesser_String, const ECharString& Greater_String ) { return ( 0 < Greater_String.Compare( p_Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator<( const ECSChar* p_Greater_String ) const { return ( 0 > Compare( p_Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator<=( const ECharString& Greater_String ) const { return ( 1 > Compare( Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool operator<=( const ECSChar* p_Lesser_String, const ECharString& Greater_String ) { return ( 0 < Greater_String.Compare( p_Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator<=( const ECSChar* p_Greater_String ) const { return ( 1 > Compare( p_Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator>( const ECharString& Lesser_String ) const { return ( 0 < Compare( Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool operator>( const ECSChar* p_Greater_String, const ECharString& Lesser_String ) { return ( 0 > Lesser_String.Compare( p_Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator>( const ECSChar* p_Lesser_String ) const { return ( 0 < Compare( p_Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator>=( const ECharString& Lesser_String ) const { return ( -1 < Compare( Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool operator>=( const ECSChar* p_Greater_String, const ECharString& Lesser_String ) { return ( 1 > Lesser_String.Compare( p_Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool ECharString::operator>=( const ECSChar* p_Lesser_String ) const { return ( -1 < Compare( p_Lesser_String, true ) ); } //*************************************************************** /* restore UNICODE, K_UNICODE and MBCS to their previous state */ #ifdef _UNICODE_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #undef _UNICODE_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #define UNICODE _PREVIOUS_UNICODE___ECHARSTRING_H #undef _PREVIOUS_UNICODE___ECHARSTRING_H #endif /* def _UNICODE_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H */ #ifdef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #undef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #define K_UNICODE _PREVIOUS_K_UNICODE___ECHARSTRING_H #undef _PREVIOUS_K_UNICODE___ECHARSTRING_H #endif /* def _K_UNICODE_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H */ #ifdef _MBCS_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #undef _MBCS_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H #define MBCS _PREVIOUS_MBCS___ECHARSTRING_H #undef _PREVIOUS_MBCS___ECHARSTRING_H #endif /* def _MBCS_WAS_PREVIOUSLY_DEFINED___ECHARSTRING_H */ //*************************************************************** #endif //ECharString_H_