csutil/csstring.h
Go to the documentation of this file.00001 /* 00002 Crystal Space utility library: string class 00003 Copyright (C) 1999,2000 by Andrew Zabolotny <bit@eltech.ru> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 #ifndef __CS_CSSTRING_H__ 00020 #define __CS_CSSTRING_H__ 00021 00026 #include "csextern.h" 00027 #include "csutil/csuctransform.h" 00028 #include "csutil/snprintf.h" 00029 #include "csutil/util.h" 00030 00052 class CS_CRYSTALSPACE_EXPORT csStringBase 00053 { 00054 protected: 00059 enum { DEFAULT_GROW_BY = 64 }; 00060 00062 char* Data; 00064 size_t Size; 00066 size_t MaxSize; 00071 size_t GrowBy; 00072 00078 void ExpandIfNeeded (size_t NewSize); 00079 00084 virtual void SetCapacityInternal (size_t NewSize, bool soft); 00085 00087 size_t ComputeNewSize (size_t NewSize); 00088 00100 virtual char* GetDataMutable () 00101 { return Data; } 00102 00103 public: 00111 void SetCapacity (size_t NewSize); 00112 00117 virtual size_t GetCapacity() const 00118 { return MaxSize > 0 ? MaxSize - 1 : 0; } 00119 00127 csStringBase& Append (const char* Str, size_t Count = (size_t)-1); 00128 00137 csStringBase& Append (const wchar_t* Str, size_t Count = (size_t)-1); 00138 00146 csStringBase& Append (const csStringBase& Str, size_t Count = (size_t)-1); 00147 00152 csStringBase& Append (char c); 00153 00158 /*csStringBase& Append (unsigned char c) 00159 { return Append(char(c)); }*/ 00160 00162 csStringBase& Append (bool b) { return Append (b ? "1" : "0"); } 00163 00169 csStringBase& AppendFmt (const char* format, ...) CS_GNUC_PRINTF (2, 3); 00170 csStringBase& AppendFmtV (const char* format, va_list args); 00174 00175 csStringBase& Append (short v) { return AppendFmt ("%hd", v); } 00176 csStringBase& Append (unsigned short v) { return AppendFmt ("%hu", v); } 00177 csStringBase& Append (int v) { return AppendFmt ("%d", v); } 00178 csStringBase& Append (unsigned int v) { return AppendFmt ("%u", v); } 00179 csStringBase& Append (long v) { return AppendFmt ("%ld", v); } 00180 csStringBase& Append (unsigned long v) { return AppendFmt ("%lu", v); } 00181 csStringBase& Append (float v) { return AppendFmt ("%g", v); } 00182 csStringBase& Append (double v) { return AppendFmt ("%g", v); } 00183 #ifndef __STRICT_ANSI__ 00184 csStringBase& Append (longlong v) { return AppendFmt ("%lld", v); } 00185 csStringBase& Append (ulonglong v) { return AppendFmt ("%llu", v); } 00186 #endif 00187 00193 csStringBase () : Data (0), Size (0), MaxSize (0), GrowBy (DEFAULT_GROW_BY) 00194 {} 00195 00202 csStringBase (size_t Length) : Data (0), Size (0), MaxSize (0), 00203 GrowBy (DEFAULT_GROW_BY) 00204 { SetCapacity (Length); } 00205 00211 csStringBase (const csStringBase& copy) : Data (0), Size (0), MaxSize (0), 00212 GrowBy (DEFAULT_GROW_BY) 00213 { Append (copy); } 00214 00220 csStringBase (const char* src) : Data (0), Size (0), MaxSize (0), 00221 GrowBy (DEFAULT_GROW_BY) 00222 { Append (src); } 00223 00230 csStringBase (const wchar_t* src) : Data (0), Size (0), MaxSize (0), 00231 GrowBy (DEFAULT_GROW_BY) 00232 { Append (src); } 00233 00239 csStringBase (const char* src, size_t _length) : Data (0), Size (0), 00240 MaxSize (0), GrowBy (DEFAULT_GROW_BY) 00241 { Append (src, _length); } 00242 00249 csStringBase (const wchar_t* src, size_t _length) : Data (0), Size (0), 00250 MaxSize (0), GrowBy (DEFAULT_GROW_BY) 00251 { Append (src, _length); } 00252 00254 csStringBase (char c) : Data (0), Size (0), MaxSize (0), 00255 GrowBy (DEFAULT_GROW_BY) 00256 { Append (c); } 00257 00259 csStringBase (unsigned char c) : Data(0), Size (0), MaxSize (0), 00260 GrowBy (DEFAULT_GROW_BY) 00261 { Append ((char) c); } 00262 00264 virtual ~csStringBase (); 00265 00278 void SetGrowsBy(size_t); 00279 00285 size_t GetGrowsBy() const 00286 { return GrowBy; } 00287 00294 virtual void Free (); 00295 00312 csStringBase& Truncate (size_t Len); 00313 00319 csStringBase& Empty() { return Truncate (0); } 00320 00330 virtual void ShrinkBestFit (); 00331 00341 csStringBase& Reclaim () { ShrinkBestFit(); return *this; } 00342 00349 csStringBase& Clear () { return Empty(); } 00350 00358 CS_VISIBILITY_DEFAULT // <- @@@ FIXME: needed for gcc 4.1.0 00359 virtual char const* GetData () const 00360 { return Data; } 00361 00371 char const* GetDataSafe() const 00372 { char const* p = GetData(); return p != 0 ? p : ""; } 00373 00379 size_t Length () const 00380 { return Size; } 00381 00387 bool IsEmpty () const 00388 { return (Size == 0); } 00389 00391 char& operator [] (size_t n) 00392 { 00393 CS_ASSERT (n < Size); 00394 return GetDataMutable()[n]; 00395 } 00396 00398 char operator [] (size_t n) const 00399 { 00400 CS_ASSERT (n < Size); 00401 return GetData()[n]; 00402 } 00403 00410 void SetAt (size_t n, const char c) 00411 { 00412 CS_ASSERT (n < Size); 00413 GetDataMutable() [n] = c; 00414 } 00415 00417 char GetAt (size_t n) const 00418 { 00419 CS_ASSERT (n < Size); 00420 return GetData() [n]; 00421 } 00422 00429 csStringBase& DeleteAt (size_t Pos, size_t Count = 1); 00430 00437 csStringBase& Insert (size_t Pos, const csStringBase& Str); 00438 00445 csStringBase& Insert (size_t Pos, const char* Str); 00446 00453 csStringBase& Insert (size_t Pos, char C); 00454 00463 csStringBase& Overwrite (size_t Pos, const csStringBase& Str); 00464 00471 csStringBase Slice (size_t start, size_t len = (size_t)-1) const; 00472 00483 void SubString (csStringBase& sub, size_t start, 00484 size_t len = (size_t)-1) const; 00485 00492 size_t FindFirst (char c, size_t pos = 0) const; 00493 00500 size_t FindFirst (const char *c, size_t pos = 0) const; 00501 00509 size_t FindLast (char c, size_t pos = (size_t)-1) const; 00510 00518 size_t FindLast (const char *c, size_t pos = (size_t)-1) const; 00519 00527 size_t Find (const char* search, size_t pos = 0, bool ignore_case = false) const; 00528 00536 /* CS_DEPRECATED_METHOD_MSG("Use Find() instead.") */ 00537 size_t FindStr (const char* search, size_t pos = 0) const 00538 { return Find(search, pos); } 00539 00545 csStringBase& ReplaceAll (const char* search, const char* replacement); 00546 00552 /* CS_DEPRECATED_METHOD_MSG("Use ReplaceAll() instead.") */ 00553 void FindReplace (const char* search, const char* replacement) 00554 { ReplaceAll(search, replacement); } 00555 00563 csStringBase& Format (const char* format, ...) CS_GNUC_PRINTF (2, 3); 00564 00572 csStringBase& FormatV (const char* format, va_list args); 00573 00583 csStringBase& Replace (const csStringBase& Str, size_t Count = (size_t)-1); 00584 00594 csStringBase& Replace (const char* Str, size_t Count = (size_t)-1); 00595 00600 template<typename T> 00601 inline csStringBase& Replace (T const& val); 00602 00609 bool Compare (const csStringBase& iStr) const 00610 { 00611 if (&iStr == this) 00612 return true; 00613 size_t const n = iStr.Length(); 00614 if (Size != n) 00615 return false; 00616 if (Size == 0 && n == 0) 00617 return true; 00618 return (memcmp (GetDataSafe(), iStr.GetDataSafe (), Size) == 0); 00619 } 00620 00627 bool Compare (const char* iStr) const 00628 { return (strcmp (GetDataSafe(), iStr ? iStr : "") == 0); } 00629 00636 bool CompareNoCase (const csStringBase& iStr) const 00637 { 00638 if (&iStr == this) 00639 return true; 00640 size_t const n = iStr.Length(); 00641 if (Size != n) 00642 return false; 00643 if (Size == 0 && n == 0) 00644 return true; 00645 return (csStrNCaseCmp (GetDataSafe(), iStr.GetDataSafe(), Size) == 0); 00646 } 00647 00654 bool CompareNoCase (const char* iStr) const 00655 { return (csStrCaseCmp (GetDataSafe(), iStr) == 0); } 00656 00663 bool StartsWith (const csStringBase& iStr, bool ignore_case = false) const 00664 { 00665 char const* p = GetDataSafe(); 00666 if (&iStr == this) 00667 return true; 00668 size_t const n = iStr.Length(); 00669 if (n == 0) 00670 return true; 00671 if (n > Size) 00672 return false; 00673 CS_ASSERT(p != 0); 00674 if (ignore_case) 00675 return (csStrNCaseCmp (p, iStr.GetDataSafe (), n) == 0); 00676 else 00677 return (strncmp (p, iStr.GetDataSafe (), n) == 0); 00678 } 00679 00686 bool StartsWith (const char* iStr, bool ignore_case = false) const 00687 { 00688 char const* p = GetDataSafe(); 00689 if (iStr == 0) 00690 return false; 00691 size_t const n = strlen (iStr); 00692 if (n == 0) 00693 return true; 00694 if (n > Size) 00695 return false; 00696 CS_ASSERT(p != 0); 00697 if (ignore_case) 00698 return (csStrNCaseCmp (p, iStr, n) == 0); 00699 else 00700 return (strncmp (p, iStr, n) == 0); 00701 } 00702 00709 bool EndsWith (const csStringBase& iStr, bool ignore_case = false) const 00710 { 00711 char const* p = GetDataSafe(); 00712 if (&iStr == this) 00713 return true; 00714 size_t const n = iStr.Length(); 00715 if (n == 0) 00716 return true; 00717 if (n > Size) 00718 return false; 00719 CS_ASSERT(p != 0); 00720 if (ignore_case) 00721 return (csStrNCaseCmp (p+(Size-n), iStr.GetDataSafe (), n) == 0); 00722 else 00723 return (strncmp (p+(Size-n), iStr.GetDataSafe (), n) == 0); 00724 } 00725 00732 bool EndsWith (const char* iStr, bool ignore_case = false) const 00733 { 00734 char const* p = GetDataSafe(); 00735 if (iStr == 0) 00736 return false; 00737 size_t const n = strlen (iStr); 00738 if (n == 0) 00739 return true; 00740 if (n > Size) 00741 return false; 00742 CS_ASSERT(p != 0); 00743 if (ignore_case) 00744 return (csStrNCaseCmp (p+(Size-n), iStr, n) == 0); 00745 else 00746 return (strncmp (p+(Size-n), iStr, n) == 0); 00747 } 00748 00754 csStringBase Clone () const 00755 { return csStringBase (*this); } 00756 00764 csStringBase& LTrim(); 00765 00773 csStringBase& RTrim(); 00774 00780 csStringBase& Trim(); 00781 00787 csStringBase& Collapse(); 00788 00797 csStringBase& PadLeft (size_t NewSize, char PadChar = ' '); 00798 00807 csStringBase& PadRight (size_t NewSize, char PadChar = ' '); 00808 00820 csStringBase& PadCenter (size_t NewSize, char PadChar = ' '); 00821 00825 template<typename T> 00826 const csStringBase& operator = (T const& s) { return Replace (s); } 00827 00829 const csStringBase& operator = (const csStringBase& copy) 00830 { Replace(copy); return *this; } 00831 00835 template<typename T> 00836 csStringBase &operator += (T const& s) { return Append (s); } 00837 00838 // Specialization which prevents gcc from barfing on strings allocated via 00839 // CS_ALLOC_STACK_ARRAY(). 00840 csStringBase &operator += (char const* s) 00841 { return Append(s); } 00842 00844 csStringBase operator + (const csStringBase &iStr) const 00845 { return Clone ().Append (iStr); } 00846 00854 operator const char* () const 00855 { return GetData(); } 00856 00863 bool operator == (const csStringBase& Str) const 00864 { return Compare (Str); } 00871 bool operator == (const char* Str) const 00872 { return Compare (Str); } 00879 bool operator < (const csStringBase& Str) const 00880 { 00881 return strcmp (GetDataSafe (), Str.GetDataSafe ()) < 0; 00882 } 00889 bool operator < (const char* Str) const 00890 { 00891 return strcmp (GetDataSafe (), Str) < 0; 00892 } 00899 bool operator > (const csStringBase& Str) const 00900 { 00901 return strcmp (GetDataSafe (), Str.GetDataSafe ()) > 0; 00902 } 00909 bool operator > (const char* Str) const 00910 { 00911 return strcmp (GetDataSafe (), Str) > 0; 00912 } 00919 bool operator != (const csStringBase& Str) const 00920 { return !Compare (Str); } 00927 bool operator != (const char* Str) const 00928 { return !Compare (Str); } 00929 00937 template <typename T> 00938 csStringBase &operator << (T const& v) 00939 { return Append (v); } 00940 00941 // Specialization which prevents gcc from barfing on strings allocated via 00942 // CS_ALLOC_STACK_ARRAY(). 00943 csStringBase &operator << (char const* v) 00944 { return Append(v); } 00945 00956 csStringBase& Downcase (uint flags = csUcMapSimple); 00967 csStringBase& Upcase (uint flags = csUcMapSimple); 00968 00979 virtual char* Detach () 00980 { char* d = Data; Data = 0; Size = 0; MaxSize = 0; return d; } 00985 uint GetHash() const; 00986 }; 00987 00989 inline csStringBase operator + (const char* iStr1, const csStringBase &iStr2) 00990 { 00991 return csStringBase (iStr1).Append (iStr2); 00992 } 00993 00995 inline csStringBase operator + (const csStringBase& iStr1, const char* iStr2) 00996 { 00997 return iStr1.Clone ().Append (iStr2); 00998 } 00999 01004 template<int LEN = 36> 01005 class csStringFast : public csStringBase 01006 { 01007 protected: 01009 char minibuff[LEN]; 01018 size_t miniused; 01019 01020 virtual void SetCapacityInternal (size_t NewSize, bool soft) 01021 { 01022 if (Data != 0) // If dynamic buffer already allocated, just re-use it. 01023 csStringBase::SetCapacityInternal(NewSize, soft); 01024 else 01025 { 01026 if (NewSize < LEN) 01027 { 01028 NewSize++; // Plus one for implicit null byte. 01029 // minibuff may still be wholly uninitialized, so ensure a null terminator 01030 if (miniused == 0) minibuff[0] = 0; 01031 miniused = NewSize; 01032 } 01033 else 01034 { 01035 CS_ASSERT(MaxSize == 0); 01036 csStringBase::SetCapacityInternal(NewSize, soft); 01037 memcpy(Data, minibuff, miniused); 01038 } 01039 } 01040 } 01041 01042 virtual char* GetDataMutable () 01043 { return (miniused == 0 && Data == 0 ? 0 : (Data != 0 ? Data : minibuff)); } 01044 01045 public: 01049 csStringFast () : csStringBase(), miniused(0) { } 01054 csStringFast (size_t Length) : csStringBase(), miniused(0) 01055 { SetCapacity (Length); } 01059 csStringFast (const csStringBase& copy) : csStringBase (), miniused(0) 01060 { Append (copy); } 01064 csStringFast (const csStringFast& copy) : csStringBase (), miniused(0) 01065 { Append (copy); } 01069 csStringFast (const char* src) : csStringBase(), miniused(0) 01070 { Append (src); } 01074 csStringFast (const char* src, size_t _length) : csStringBase(), miniused(0) 01075 { Append (src, _length); } 01076 01078 csStringFast (const wchar_t* src) : csStringBase (), miniused(0) 01079 { Append (src); } 01081 csStringFast (const wchar_t* src, size_t _length) : csStringBase (), miniused(0) 01082 { Append (src, _length); } 01083 01085 csStringFast (char c) : csStringBase(), miniused(0) 01086 { Append (c); } 01088 csStringFast (unsigned char c) : csStringBase(), miniused(0) 01089 { Append ((char)c); } 01091 virtual ~csStringFast () { } 01092 01094 const csStringFast& operator = (const csStringBase& copy) 01095 { Replace(copy); return *this; } 01096 01098 template<typename T> 01099 const csStringFast& operator = (T const& s) { Replace (s); return *this; } 01100 01101 virtual char const* GetData () const 01102 { return (miniused == 0 && Data == 0 ? 0 : (Data != 0 ? Data : minibuff)); } 01103 01104 virtual size_t GetCapacity() const 01105 { return Data != 0 ? csStringBase::GetCapacity() : miniused - 1; } 01106 01107 virtual void ShrinkBestFit () 01108 { 01109 if (Size == 0) 01110 { 01111 csStringBase::ShrinkBestFit(); 01112 miniused = 0; 01113 } 01114 else 01115 { 01116 size_t needed = Size + 1; 01117 if (needed > LEN) 01118 csStringBase::ShrinkBestFit(); 01119 else 01120 { 01121 miniused = needed; 01122 if (Data != 0) 01123 { 01124 memcpy(minibuff, Data, needed); // Includes implicit null byte. 01125 csStringBase::Free(); 01126 } 01127 } 01128 } 01129 } 01130 01131 virtual void Free () { miniused = 0; csStringBase::Free(); } 01132 01133 virtual char* Detach () 01134 { 01135 if (Data != 0) 01136 return csStringBase::Detach(); 01137 else if (miniused == 0) 01138 return 0; // Emulate NULL return of csStringBase in this case. 01139 else 01140 { 01141 CS_ASSERT(MaxSize == 0); 01142 char* d = csStrNew (minibuff); 01143 Size = 0; miniused = 0; 01144 return d; 01145 } 01146 } 01147 }; 01148 01149 template<> 01150 class csStringFast<0> : public csStringBase 01151 { 01152 public: 01153 csStringFast () : csStringBase() { } 01154 csStringFast (size_t Length) : csStringBase(Length) { } 01155 csStringFast (const csStringBase& copy) : csStringBase (copy) { } 01156 csStringFast (const char* src) : csStringBase(src) { } 01157 csStringFast (const char* src, size_t _length) : csStringBase(src, _length) 01158 { } 01159 csStringFast (const wchar_t* src) : csStringBase (src) {} 01160 csStringFast (const wchar_t* src, size_t _length) : csStringBase (src, _length) { } 01161 csStringFast (char c) : csStringBase(c) { } 01162 csStringFast (unsigned char c) : csStringBase(c) { } 01163 const csStringFast& operator = (const csStringBase& copy) 01164 { Replace(copy); return *this; } 01165 const csStringFast& operator = (const char* copy) 01166 { Replace(copy); return *this; } 01167 const csStringFast& operator = (char x) 01168 { Replace(x); return *this; } 01169 const csStringFast& operator = (unsigned char x) 01170 { Replace(x); return *this; } 01171 const csStringFast& operator = (bool x) 01172 { Replace(x); return *this; } 01173 const csStringFast& operator = (short x) 01174 { Replace(x); return *this; } 01175 const csStringFast& operator = (unsigned short x) 01176 { Replace(x); return *this; } 01177 const csStringFast& operator = (int x) 01178 { Replace(x); return *this; } 01179 const csStringFast& operator = (unsigned int x) 01180 { Replace(x); return *this; } 01181 const csStringFast& operator = (long x) 01182 { Replace(x); return *this; } 01183 const csStringFast& operator = (unsigned long x) 01184 { Replace(x); return *this; } 01185 const csStringFast& operator = (float x) 01186 { Replace(x); return *this; } 01187 const csStringFast& operator = (double x) 01188 { Replace(x); return *this; } 01189 #ifndef __STRICT_ANSI__ 01190 const csStringFast& operator = (longlong x) 01191 { Replace(x); return *this; } 01192 const csStringFast& operator = (ulonglong x) 01193 { Replace(x); return *this; } 01194 #endif 01195 }; 01196 01197 #ifndef SWIG 01198 01203 typedef csStringFast<> csStringFastDefault; 01204 #else 01205 #define csStringFastDefault csStringFast<36> 01206 %template(csStringParent) csStringFast<36>; 01207 #endif 01208 01212 class csString : public csStringFastDefault 01213 { 01214 public: 01216 csString () : csStringFast<> () { } 01221 csString (size_t Length) : csStringFast<> (Length) { } 01223 01224 csString (const csString& copy) : 01225 csStringFast<> ((const csStringBase&)copy) { } 01226 csString (const csStringBase& copy) : csStringFast<> (copy) { } 01228 01229 csString (const char* src) : csStringFast<> (src) { } 01231 csString (const char* src, size_t _length) : csStringFast<> (src, _length) { } 01233 csString (const wchar_t* src) : csStringFast<> (src) {} 01235 csString (const wchar_t* src, size_t _length) : csStringFast<> (src, _length) { } 01236 01238 csString (char c) : csStringFast<> (c) { } 01240 csString (unsigned char c) : csStringFast<> (c) { } 01241 01243 01244 const csString& operator = (const csString& copy) 01245 { Replace(copy); return *this; } 01246 const csString& operator = (const csStringBase& copy) 01247 { Replace(copy); return *this; } 01248 const csString& operator = (const char* copy) 01249 { Replace(copy); return *this; } 01250 const csString& operator = (char x) 01251 { Replace(x); return *this; } 01252 const csString& operator = (unsigned char x) 01253 { Replace(x); return *this; } 01254 const csString& operator = (bool x) 01255 { Replace(x); return *this; } 01256 const csString& operator = (short x) 01257 { Replace(x); return *this; } 01258 const csString& operator = (unsigned short x) 01259 { Replace(x); return *this; } 01260 const csString& operator = (int x) 01261 { Replace(x); return *this; } 01262 const csString& operator = (unsigned int x) 01263 { Replace(x); return *this; } 01264 const csString& operator = (long x) 01265 { Replace(x); return *this; } 01266 const csString& operator = (unsigned long x) 01267 { Replace(x); return *this; } 01268 const csString& operator = (float x) 01269 { Replace(x); return *this; } 01270 const csString& operator = (double x) 01271 { Replace(x); return *this; } 01272 #ifndef __STRICT_ANSI__ 01273 const csString& operator = (longlong x) 01274 { Replace(x); return *this; } 01275 const csString& operator = (ulonglong x) 01276 { Replace(x); return *this; } 01277 #endif 01278 01279 }; 01280 01281 template<typename T> 01282 csStringBase& csStringBase::Replace (T const& val) 01283 { 01284 // Use a temp string so replacing a string with itself works correctly 01285 csString temp; 01286 temp.Append (val); 01287 return Replace (static_cast<const csStringBase&> (temp)); 01288 } 01289 01290 #endif // __CS_CSSTRING_H__
Generated for Crystal Space 2.1 by doxygen 1.6.1
