#ifndef EWCHARSTRING_H #define EWCHARSTRING_H //===========================================================================// // Copyright (C) Microsoft Corporation. All rights reserved. // //===========================================================================// // Notes essentially EString, except that it uses wchars (not chars) even when UNICODE is not defined // //*************************************************************** //*************************************************************** /* just for this file, we want UNICODE and K_UNICODE defined and MBCS undefined */ #ifdef UNICODE #define _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #else #define UNICODE #endif /* def UNICODE */ #ifdef K_UNICODE #define _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #else #define K_UNICODE #endif /* def K_UNICODE */ #ifdef MBCS #define _MBCS_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #define _PREVIOUS_MBCS___EWCHARSTRING_H MBCS #undef MBCS #endif /* def MBCS */ //*************************************************************** #ifdef UNICODE #define EWCSChar unsigned short #else #define EWCSChar char #endif #include class EWCharString { public: // ENUMERATIONS & CONSTANTS static const int INVALID_INDEX; // CONSTRUCTORS/DESTRUCTORS /*explicit*/ EWCharString( const EWCSChar* newString ); EWCharString( const EWCharString& ); /*explicit*/ EWCharString( const EWCSChar ); EWCharString(); ~EWCharString(); // MANIPULATORS void Replace( int Start_Index, const EWCharString& String ); void Replace( int Start_Index, const EWCSChar* ); bool Remove( int Start_Index, int End_Index ); bool Remove( EWCharString& Sub_String ); // puts this string in the middle of another string inline void Insert( int Start_Index, const EWCharString& String ); void Insert( int Start_Index, const EWCSChar* String ); void Swap( EWCharString& ); inline void Empty(); void MakeUpper(); void MakeLower(); void Reverse(); // works like sprintf with the destination buffer being // the this pointer void Format( const EWCSChar*, ... ); inline const EWCharString& operator=( const EWCSChar* ); inline const EWCharString& operator=( const EWCharString& ); inline const EWCharString& operator=( EWCSChar ); inline const EWCharString& operator+=( const EWCSChar* ); inline const EWCharString& operator+=( const EWCharString& ); inline const EWCharString& operator+=( EWCSChar ); friend EWCharString operator+( const EWCharString&, const EWCharString& ); friend EWCharString operator+( const EWCSChar*, const EWCharString& ); friend EWCharString operator+( const EWCharString& , const EWCSChar* ); friend EWCharString operator+( const EWCharString&, const EWCSChar ); friend EWCharString operator+( const EWCSChar, const EWCharString& ); // ACCESSORS // these are case sensitive, use Compare // if you don't want case senstitivity inline bool operator==( const EWCharString& ) const; inline bool operator==( const EWCSChar* ) const; inline friend bool operator==( const EWCSChar*, const EWCharString& ); // these functions return -1 if "this" is less than the passed in string int Compare( const EWCharString&, bool Case_Sensitive = false ) const; int Compare( const EWCSChar*, bool Case_Sensitive = false ) const; bool operator!=( const EWCharString& ) const; bool operator!=( const EWCSChar*) const; friend bool operator!=( const EWCSChar*, const EWCharString& ); inline EWCSChar& operator[]( int Index ); inline const EWCSChar& operator[](int Index) const; inline bool operator<( const EWCharString& ) const; inline bool operator<( const EWCSChar* ) const; inline friend bool operator<( const EWCSChar*, const EWCharString& ); inline bool operator<=( const EWCharString& ) const; inline bool operator<=( const EWCSChar*) const; inline friend bool operator<=( const EWCSChar*, const EWCharString&); inline bool operator>( const EWCharString& ) const; inline bool operator>(const EWCSChar*) const; inline friend bool operator>( const EWCSChar*, const EWCharString&); inline bool operator>=( const EWCharString& ) const; inline bool operator>=( const EWCSChar*) const; inline friend bool operator>=( const EWCSChar*, const EWCharString&); int Size() const; // number of bytes int Length() const; // number of characters // search functions int Find( EWCSChar, int Start_Index = EWCharString::INVALID_INDEX) const; int Find( const EWCharString&, int Start_Index = EWCharString::INVALID_INDEX) const; int Find( const EWCSChar*, int Start_Index = EWCharString::INVALID_INDEX) const; int ReverseFind ( EWCSChar, int End_Index = EWCharString::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 EWCharString SubString( int Start_Index, int End_Index ) const; inline EWCharString Left( int Num_Chars) const; inline EWCharString Right( int Num_Chars) const; inline bool IsEmpty() const; unsigned short* CreateUNICODE() const; char* CreateMBCS() const; inline const EWCSChar* 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 EWCharString( const char* ); friend EWCharString operator+( const EWCharString&, char* ); friend EWCharString operator+( char*, const EWCharString& ); friend EWCharString operator+( char, const EWCharString& ); friend EWCharString operator+( const EWCharString&, char ); const EWCharString& operator+=( const char* ); const EWCharString& operator+=( char ); const EWCharString& operator=( char ); bool operator==( const char* ); friend bool operator==( const char*, const EWCharString& ); bool operator!=( const char*) const; friend bool operator!=( const char*, const EWCharString& ); bool operator<( const char* ) const; friend bool operator<( const char*, const EWCharString& ); bool operator>( const char* ) const; friend bool operator>( const char*, const EWCharString& ); bool operator<=( const char*) const; friend bool operator<=( const char*, const EWCharString&); bool operator>=( const char*) const; friend bool operator>=( const char*, const EWCharString&); void Format( const char*, ... ); int Find( char, int Start_Index = EWCharString::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 EWCSChar* p_Str ); static inline unsigned short* ToUnicode( unsigned short* Buffer, const unsigned char* p_Str, int Num_Chars ); static inline int StrSize( const EWCSChar* 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 EWCSChar* 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 EWCharString::ChecEBuffer() { if ( m_pBuffer->m_Ref_Count > 0 ) { m_pBuffer->m_Ref_Count --; m_pBuffer = EBuffer::s_p_Empty_Buffer; } } ///////////////////////////////////////////////////////////////// inline void EWCharString::EBuffer::Release() { if ( this != s_p_Empty_Buffer ) { m_Ref_Count --; if ( m_Ref_Count < 0 ) { delete [] (char*)this; } } } ///////////////////////////////////////////////////////////////// inline void EWCharString::Empty() { m_pBuffer->Release(); m_pBuffer = EBuffer::s_p_Empty_Buffer; } ///////////////////////////////////////////////////////////////// inline void EWCharString::Insert( int Start_Index, const EWCharString& String ) { Insert( Start_Index, String.m_pBuffer->Data() ); } ///////////////////////////////////////////////////////////////// inline const EWCharString& EWCharString::operator=( const EWCSChar* p_String ) { ChecEBuffer(); Assign( p_String ); return *this; } ///////////////////////////////////////////////////////////////// inline const EWCharString& EWCharString::operator=( const EWCharString& Src ) { if ( &Src != this ) { m_pBuffer->Release(); m_pBuffer = Src.m_pBuffer; Src.m_pBuffer->m_Ref_Count ++; } return *this; } ///////////////////////////////////////////////////////////////// inline const EWCharString& EWCharString::operator=( EWCSChar Char ) { ChecEBuffer(); EWCSChar Tmp[2]; Tmp[0] = Char; Tmp[1] = 0; Assign( Tmp ); return *this; } ///////////////////////////////////////////////////////////////// inline const EWCharString& EWCharString::operator+=( const EWCSChar* p_String ) { Insert( m_pBuffer->m_Data_Length, p_String ); return *this; } ///////////////////////////////////////////////////////////////// inline const EWCharString& EWCharString::operator+=( const EWCharString& String ) { Insert( m_pBuffer->m_Data_Length, String ); return *this; } ///////////////////////////////////////////////////////////////// inline const EWCharString& EWCharString::operator+=( EWCSChar Char ) { EWCSChar Tmp[2]; Tmp[0] = Char; Tmp[1] = 0; Insert( m_pBuffer->m_Data_Length, Tmp ); return *this; } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator!=( const EWCharString& Str_To_Compare ) const { return !( operator==(Str_To_Compare) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator!=( const EWCSChar* p_Str_To_Compare ) const { return !( operator==( p_Str_To_Compare ) ); } ///////////////////////////////////////////////////////////////// inline EWCharString EWCharString::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 EWCharString EWCharString::Right( int Num_Chars) const { return SubString( m_pBuffer->m_Data_Length - Num_Chars, m_pBuffer->m_Data_Length - 1 ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::IsEmpty() const { return (m_pBuffer->m_Data_Length <= 0); } ///////////////////////////////////////////////////////////////// inline const EWCSChar* EWCharString::Data() const { return ( m_pBuffer->Data() ); } ///////////////////////////////////////////////////////////////// inline EWCSChar* EWCharString::EBuffer::Data() { if ( !m_Alloc_Length ) { return 0; } return (EWCSChar*)(this + 1); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator==( const EWCharString& Str_To_Compare) const { return ( 0 == Compare( Str_To_Compare, true ) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator==( const EWCSChar* p_String ) const { return ( 0 == Compare( p_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool operator==( const EWCSChar* p_String, const EWCharString& Str ) { return ( 0 == Str.Compare( p_String ) ); } ///////////////////////////////////////////////////////////////// inline bool operator!=( const EWCSChar* p_String, const EWCharString& Str ) { return !(Str == p_String ); } ///////////////////////////////////////////////////////////////// inline EWCSChar& EWCharString::operator[]( int Index ) { ChecEBufferDoRealloc(); gosASSERT( Index < m_pBuffer->m_Data_Length ); return *(m_pBuffer->Data() + Index); } ///////////////////////////////////////////////////////////////// inline const EWCSChar& EWCharString::operator[](int Index) const { gosASSERT( Index < m_pBuffer->m_Data_Length ); return *(m_pBuffer->Data() + Index); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator<( const EWCharString& Greater_String ) const { return ( 0 > Compare( Greater_String, true)); } ///////////////////////////////////////////////////////////////// inline bool operator<( const EWCSChar* p_Lesser_String, const EWCharString& Greater_String ) { return ( 0 < Greater_String.Compare( p_Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator<( const EWCSChar* p_Greater_String ) const { return ( 0 > Compare( p_Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator<=( const EWCharString& Greater_String ) const { return ( 1 > Compare( Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool operator<=( const EWCSChar* p_Lesser_String, const EWCharString& Greater_String ) { return ( 0 < Greater_String.Compare( p_Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator<=( const EWCSChar* p_Greater_String ) const { return ( 1 > Compare( p_Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator>( const EWCharString& Lesser_String ) const { return ( 0 < Compare( Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool operator>( const EWCSChar* p_Greater_String, const EWCharString& Lesser_String ) { return ( 0 > Lesser_String.Compare( p_Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator>( const EWCSChar* p_Lesser_String ) const { return ( 0 < Compare( p_Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator>=( const EWCharString& Lesser_String ) const { return ( -1 < Compare( Lesser_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool operator>=( const EWCSChar* p_Greater_String, const EWCharString& Lesser_String ) { return ( 1 > Lesser_String.Compare( p_Greater_String, true ) ); } ///////////////////////////////////////////////////////////////// inline bool EWCharString::operator>=( const EWCSChar* p_Lesser_String ) const { return ( -1 < Compare( p_Lesser_String, true ) ); } //*************************************************************** /* restore UNICODE, K_UNICODE and MBCS to their previous state */ #ifndef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #undef UNICODE #else #undef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #endif /* ndef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H */ #ifndef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #undef K_UNICODE #else #undef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #endif /* ndef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H */ #ifdef _MBCS_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #undef _MBCS_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H #define MBCS _PREVIOUS_MBCS___EWCHARSTRING_H #undef _PREVIOUS_MBCS___EWCHARSTRING_H #endif /* def _MBCS_WAS_PREVIOUSLY_DEFINED___EWCHARSTRING_H */ //*************************************************************** #endif //EWCharString_H_