/* UnicodeString.h Written by Matthew Fisher String class and related conversions. */ #pragma once // // Intellisense for custom types // //http://thejefffiles.com/blog/autoexpdat-your-key-to-better-debugging-part-1/ typedef wchar_t UnicodeCharacter; const UnicodeCharacter UnicodeNullTerminator = 0; const UnicodeCharacter UnicodeHeader = 0xFEFF; const UnicodeCharacter UnicodeNewline = 0x000D; const UnicodeCharacter UnicodeSpace = 0x0020; class UnicodeString { public: struct LexicographicComparison { bool operator()(const UnicodeString &L, const UnicodeString &R) const { SignalError("Not implemented"); } }; UnicodeString() { _Data = NULL; _Capacity = 0; _Length = 0; } ~UnicodeString() { if(_Data != NULL) { delete[] _Data; } } UnicodeString(const UnicodeString &S) { if(S._Data == NULL) { _Data = NULL; _Capacity = 0; _Length = 0; } else { _Length = S._Length; const UINT NewCapacity = _Length + 1; _Capacity = NewCapacity; _Data = new UnicodeCharacter[NewCapacity]; memcpy(_Data, S._Data, NewCapacity * sizeof(UnicodeCharacter)); } } UnicodeString(const UnicodeCharacter *Text) { _Data = NULL; _Capacity = 0; _Length = 0; *this = Text; } explicit UnicodeString(UnicodeCharacter C) { _Data = NULL; _Capacity = 0; _Length = 0; *this = C; } explicit UnicodeString(const Vector &S) { _Length = S.Length(); _Capacity = _Length + 1; _Data = new UnicodeCharacter[_Capacity]; memcpy(_Data, S.CArray(), _Length * sizeof(UnicodeCharacter)); _Data[_Length] = UnicodeNullTerminator; } explicit UnicodeString(const String &S) { _Length = S.Length(); _Capacity = _Length + 1; _Data = new UnicodeCharacter[_Capacity]; for(UINT Index = 0; Index < _Length; Index++) { _Data[Index] = S[Index]; } _Data[_Length] = UnicodeNullTerminator; } // // Memory // __forceinline void FreeMemory() { if(_Data != NULL) { delete[] _Data; _Data = NULL; } _Length = 0; _Capacity = 0; } __forceinline void Allocate(UINT Capacity) { if(_Data != NULL) { delete[] _Data; } _Data = new UnicodeCharacter[Capacity]; _Data[0] = UnicodeNullTerminator; _Length = 0; _Capacity = Capacity; } __forceinline void ReSize(UINT NewLength) { const UINT NewCapacity = NewLength + 1; _Length = Math::Min(_Length, NewLength); UnicodeCharacter *NewData = new UnicodeCharacter[NewCapacity]; if(_Length > 0) { memcpy(NewData, _Data, _Length * sizeof(UnicodeCharacter)); } NewData[_Length] = UnicodeNullTerminator; if(_Data != NULL) { delete[] _Data; } _Data = NewData; _Capacity = NewCapacity; } // // Accessors // __forceinline UnicodeCharacter* CString() { if(_Data != NULL) { return _Data; } else { return (UnicodeCharacter *)&(_Data); } } __forceinline const UnicodeCharacter* CString() const { if(_Data != NULL) { return _Data; } else { return (UnicodeCharacter *)&(_Data); } } __forceinline UINT Length() const { return _Length; } __forceinline UnicodeCharacter Last() const { #ifdef VECTOR_DEBUG if(_Length == 0) { SignalError("Last called on zero-length string"); } #endif return _Data[_Length - 1]; } __forceinline UnicodeCharacter& operator [] (UINT k) { #ifdef VECTOR_DEBUG if(k >= _Length) { SignalError("Out-of-bounds string access"); } #endif return _Data[k]; } __forceinline UnicodeCharacter& operator [] (int k) { #ifdef VECTOR_DEBUG if(k < 0 || k >= int(_Length)) { SignalError("Out-of-bounds string access"); } #endif return _Data[k]; } __forceinline const UnicodeCharacter& operator [] (UINT k) const { #ifdef VECTOR_DEBUG if(k >= _Length) { SignalError("Out-of-bounds string access"); } #endif return _Data[k]; } __forceinline const UnicodeCharacter& operator [] (int k) const { #ifdef VECTOR_DEBUG if(k < 0 || k >= int(_Length)) { SignalError("Out-of-bounds string access"); } #endif return _Data[k]; } // // Assignment // UnicodeString& operator = (UnicodeCharacter Character); UnicodeString& operator = (const UnicodeCharacter *S); UnicodeString& operator = (const UnicodeString &S); // // Query // bool ExactMatchAtOffset(const UnicodeString &Find, UINT Offset) const; bool Contains(const UnicodeString &Find) const; bool IsNumeric() const; bool IsSuffix(const UnicodeString &EndCanidate) const; bool IsPrefix(const UnicodeString &StartCanidate) const; void Partition(UnicodeCharacter Seperator, Vector &Output) const; Vector Partition(UnicodeCharacter Seperator) const; void PartitionAboutIndex(UINT Index, UnicodeString &Left, UnicodeString &Right) const; void Partition(const UnicodeString &Seperator, Vector &Output) const; int FindFirstIndex(UnicodeCharacter Seperator) const; int FindLastIndex(UnicodeCharacter Seperator) const; UnicodeString FindAndReplace(const UnicodeString &Find, const UnicodeString &Replace) const; UnicodeString RemoveSuffix(const UnicodeString &EndCandidate) const; UINT Hash() const; // // Modifiers // UnicodeString& operator += (const UnicodeString &S); __forceinline void operator += (UnicodeCharacter C) { PushEnd(C); } __forceinline void PushEnd(UnicodeCharacter C) { if(_Length + 1 >= _Capacity) { ReSize(_Capacity * 2 + 3); } _Data[_Length] = C; _Length++; _Data[_Length] = UnicodeNullTerminator; } __forceinline void PopEnd() { #ifdef VECTOR_DEBUG if(_Length == 0) { SignalError("Pop called on empty string"); } #endif _Length--; _Data[_Length] = UnicodeNullTerminator; } void PopFront() { #ifdef VECTOR_DEBUG if(_Length == 0) { SignalError("Pop called on empty string"); } #endif _Length--; for(UINT Index = 0; Index < _Length; Index++) { _Data[Index] = _Data[Index + 1]; } } private: void ResizeToCStringLength(); friend UnicodeString operator + (const UnicodeString &L, const UnicodeString &R); UnicodeCharacter *_Data; UINT _Capacity; UINT _Length; }; // // String Comparison // bool operator == (const UnicodeString &L, const UnicodeString &R); bool operator == (const UnicodeCharacter *L, const UnicodeString &R); bool operator == (const UnicodeString &R, const UnicodeCharacter *L); __forceinline bool operator != (const UnicodeString &L, const UnicodeString &R) {return !(L == R);} __forceinline bool operator != (const UnicodeCharacter *L, const UnicodeString &R) {return !(L == R);} __forceinline bool operator != (const UnicodeString &R, const UnicodeCharacter *L) {return !(L == R);} // // String Operations // UnicodeString operator + (const UnicodeString &L, const UnicodeString &R); ostream& operator << (ostream &os, const UnicodeString &S);