## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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/snprintf.h"
    00028 #include "csutil/util.h"
    00029
    00051 class CS_CRYSTALSPACE_EXPORT csStringBase
    00052 {
    00053 protected:
    00058   enum { DEFAULT_GROW_BY = 64 };
    00059
    00061   char* Data;
    00063   size_t Size;
    00065   size_t MaxSize;
    00070   size_t GrowBy;
    00071
    00077   void ExpandIfNeeded (size_t NewSize);
    00078
    00083   virtual void SetCapacityInternal (size_t NewSize, bool soft);
    00084
    00086   size_t ComputeNewSize (size_t NewSize);
    00087
    00099   virtual char* GetDataMutable ()
    00100   { return Data; }
    00101
    00102 public:
    00110   void SetCapacity (size_t NewSize);
    00111
    00116   virtual size_t GetCapacity() const
    00117   { return MaxSize > 0 ? MaxSize - 1 : 0; }
    00118
    00126   csStringBase& Append (const char* Str, size_t Count = (size_t)-1);
    00127
    00136   csStringBase& Append (const wchar_t* Str, size_t Count = (size_t)-1);
    00137
    00145   csStringBase& Append (const csStringBase& Str, size_t Count = (size_t)-1);
    00146
    00151   csStringBase& Append (char c);
    00152
    00157   /*csStringBase& Append (unsigned char c)
    00158   { return Append(char(c)); }*/
    00159
    00161   csStringBase& Append (bool b) { return Append (b ? "1" : "0"); }
    00162
    00168   csStringBase& AppendFmt (const char* format, ...) CS_GNUC_PRINTF (2, 3);
    00169   csStringBase& AppendFmtV (const char* format, va_list args);
    00173
    00174   csStringBase& Append (short v) { return AppendFmt ("%hd", v); }
    00175   csStringBase& Append (unsigned short v) { return AppendFmt ("%hu", v); }
    00176   csStringBase& Append (int v) { return AppendFmt ("%d", v); }
    00177   csStringBase& Append (unsigned int v) { return AppendFmt ("%u", v); }
    00178   csStringBase& Append (long v) { return AppendFmt ("%ld", v); }
    00179   csStringBase& Append (unsigned long v) { return AppendFmt ("%lu", v); }
    00180   csStringBase& Append (float v) { return AppendFmt ("%g", v); }
    00181   csStringBase& Append (double v) { return AppendFmt ("%g", v); }
    00182 #ifndef __STRICT_ANSI__
    00183   csStringBase& Append (longlong v) { return AppendFmt ("%lld", v); }
    00184   csStringBase& Append (ulonglong v) { return AppendFmt ("%llu", v); }
    00185 #endif
    00186
    00192   csStringBase () : Data (0), Size (0), MaxSize (0), GrowBy (DEFAULT_GROW_BY)
    00193   {}
    00194
    00201   csStringBase (size_t Length) : Data (0), Size (0), MaxSize (0),
    00202     GrowBy (DEFAULT_GROW_BY)
    00203   { SetCapacity (Length); }
    00204
    00210   csStringBase (const csStringBase& copy) : Data (0), Size (0), MaxSize (0),
    00211     GrowBy (DEFAULT_GROW_BY)
    00212   { Append (copy); }
    00213
    00219   csStringBase (const char* src) : Data (0), Size (0), MaxSize (0),
    00220     GrowBy (DEFAULT_GROW_BY)
    00221   { Append (src); }
    00222
    00229   csStringBase (const wchar_t* src) : Data (0), Size (0), MaxSize (0),
    00230     GrowBy (DEFAULT_GROW_BY)
    00231   { Append (src); }
    00232
    00238   csStringBase (const char* src, size_t _length) : Data (0), Size (0),
    00239         MaxSize (0), GrowBy (DEFAULT_GROW_BY)
    00240   { Append (src, _length); }
    00241
    00248   csStringBase (const wchar_t* src, size_t _length) : Data (0), Size (0),
    00249         MaxSize (0), GrowBy (DEFAULT_GROW_BY)
    00250   { Append (src, _length); }
    00251
    00253   csStringBase (char c) : Data (0), Size (0), MaxSize (0),
    00254     GrowBy (DEFAULT_GROW_BY)
    00255   { Append (c); }
    00256
    00258   csStringBase (unsigned char c) : Data(0), Size (0), MaxSize (0),
    00259     GrowBy (DEFAULT_GROW_BY)
    00260   { Append ((char) c); }
    00261
    00263   virtual ~csStringBase ();
    00264
    00277   void SetGrowsBy(size_t);
    00278
    00284   size_t GetGrowsBy() const
    00285   { return GrowBy; }
    00286
    00291   CS_DEPRECATED_METHOD_MSG("Use SetGrowsBy(0) instead.")
    00292   void SetGrowsExponentially(bool b)
    00293   { SetGrowsBy(b ? 0 : DEFAULT_GROW_BY); }
    00294
    00299   CS_DEPRECATED_METHOD_MSG("Use GetGrowsBy() instead.")
    00300   bool GetGrowsExponentially() const
    00301   { return GetGrowsBy() == 0; }
    00302
    00309   virtual void Free ();
    00310
    00327   csStringBase& Truncate (size_t Len);
    00328
    00334   csStringBase& Empty() { return Truncate (0); }
    00335
    00345   virtual void ShrinkBestFit ();
    00346
    00356   csStringBase& Reclaim () { ShrinkBestFit(); return *this; }
    00357
    00364   csStringBase& Clear () { return Empty(); }
    00365
    00373   CS_VISIBILITY_DEFAULT // <- @@@ FIXME: needed for gcc 4.1.0
    00374   virtual char const* GetData () const
    00375   { return Data; }
    00376
    00386    char const* GetDataSafe() const
    00387    { char const* p = GetData(); return p != 0 ? p : ""; }
    00388
    00394   size_t Length () const
    00395   { return Size; }
    00396
    00402   bool IsEmpty () const
    00403   { return (Size == 0); }
    00404
    00406   char& operator [] (size_t n)
    00407   {
    00408     CS_ASSERT (n < Size);
    00409     return GetDataMutable()[n];
    00410   }
    00411
    00413   char operator [] (size_t n) const
    00414   {
    00415     CS_ASSERT (n < Size);
    00416     return GetData()[n];
    00417   }
    00418
    00425   void SetAt (size_t n, const char c)
    00426   {
    00427     CS_ASSERT (n < Size);
    00428     GetDataMutable() [n] = c;
    00429   }
    00430
    00432   char GetAt (size_t n) const
    00433   {
    00434     CS_ASSERT (n < Size);
    00435     return GetData() [n];
    00436   }
    00437
    00444   csStringBase& DeleteAt (size_t Pos, size_t Count = 1);
    00445
    00452   csStringBase& Insert (size_t Pos, const csStringBase& Str);
    00453
    00460   csStringBase& Insert (size_t Pos, const char* Str);
    00461
    00468   csStringBase& Insert (size_t Pos, char C);
    00469
    00478   csStringBase& Overwrite (size_t Pos, const csStringBase& Str);
    00479
    00486   csStringBase Slice (size_t start, size_t len = (size_t)-1) const;
    00487
    00498   void SubString (csStringBase& sub, size_t start,
    00499     size_t len = (size_t)-1) const;
    00500
    00507   size_t FindFirst (char c, size_t pos = 0) const;
    00508
    00515   size_t FindFirst (const char *c, size_t pos = 0) const;
    00516
    00524   size_t FindLast (char c, size_t pos = (size_t)-1) const;
    00525
    00533   size_t FindLast (const char *c, size_t pos = (size_t)-1) const;
    00534
    00541   size_t Find (const char* search, size_t pos = 0) const;
    00542
    00550   /* CS_DEPRECATED_METHOD_MSG("Use Find() instead.") */
    00551   size_t FindStr (const char* search, size_t pos = 0) const
    00552   { return Find(search, pos); }
    00553
    00558   void ReplaceAll (const char* search, const char* replacement);
    00559
    00565   /* CS_DEPRECATED_METHOD_MSG("Use ReplaceAll() instead.") */
    00566   void FindReplace (const char* search, const char* replacement)
    00567   { ReplaceAll(search, replacement); }
    00568
    00576   csStringBase& Format (const char* format, ...) CS_GNUC_PRINTF (2, 3);
    00577
    00585   csStringBase& FormatV (const char* format, va_list args);
    00586
    00596   csStringBase& Replace (const csStringBase& Str, size_t Count = (size_t)-1);
    00597
    00607   csStringBase& Replace (const char* Str, size_t Count = (size_t)-1);
    00608
    00613   template<typename T>
    00614   csStringBase& Replace (T const& val) { Truncate (0); return Append (val); }
    00615
    00622   bool Compare (const csStringBase& iStr) const
    00623   {
    00624     if (&iStr == this)
    00625       return true;
    00626     size_t const n = iStr.Length();
    00627     if (Size != n)
    00628       return false;
    00629     if (Size == 0 && n == 0)
    00630       return true;
    00631     return (memcmp (GetDataSafe(), iStr.GetDataSafe (), Size) == 0);
    00632   }
    00633
    00640   bool Compare (const char* iStr) const
    00641   { return (strcmp (GetDataSafe(), iStr) == 0); }
    00642
    00649   bool CompareNoCase (const csStringBase& iStr) const
    00650   {
    00651     if (&iStr == this)
    00652       return true;
    00653     size_t const n = iStr.Length();
    00654     if (Size != n)
    00655       return false;
    00656     if (Size == 0 && n == 0)
    00657       return true;
    00658     return (csStrNCaseCmp (GetDataSafe(), iStr.GetDataSafe(), Size) == 0);
    00659   }
    00660
    00667   bool CompareNoCase (const char* iStr) const
    00668   { return (csStrCaseCmp (GetDataSafe(), iStr) == 0); }
    00669
    00676   bool StartsWith (const csStringBase& iStr, bool ignore_case = false) const
    00677   {
    00678     char const* p = GetDataSafe();
    00679     if (&iStr == this)
    00680       return true;
    00681     size_t const n = iStr.Length();
    00682     if (n == 0)
    00683       return true;
    00684     if (n > Size)
    00685       return false;
    00686     CS_ASSERT(p != 0);
    00687     if (ignore_case)
    00688       return (csStrNCaseCmp (p, iStr.GetDataSafe (), n) == 0);
    00689     else
    00690       return (strncmp (p, iStr.GetDataSafe (), n) == 0);
    00691   }
    00692
    00699   bool StartsWith (const char* iStr, bool ignore_case = false) const
    00700   {
    00701     char const* p = GetDataSafe();
    00702     if (iStr == 0)
    00703       return false;
    00704     size_t const n = strlen (iStr);
    00705     if (n == 0)
    00706       return true;
    00707     if (n > Size)
    00708       return false;
    00709     CS_ASSERT(p != 0);
    00710     if (ignore_case)
    00711       return (csStrNCaseCmp (p, iStr, n) == 0);
    00712     else
    00713       return (strncmp (p, iStr, n) == 0);
    00714   }
    00715
    00721   csStringBase Clone () const
    00722   { return csStringBase (*this); }
    00723
    00731   csStringBase& LTrim();
    00732
    00740   csStringBase& RTrim();
    00741
    00747   csStringBase& Trim();
    00748
    00754   csStringBase& Collapse();
    00755
    00764   csStringBase& PadLeft (size_t NewSize, char PadChar = ' ');
    00765
    00774   csStringBase& PadRight (size_t NewSize, char PadChar = ' ');
    00775
    00787   csStringBase& PadCenter (size_t NewSize, char PadChar = ' ');
    00788
    00792   template<typename T>
    00793   const csStringBase& operator = (T const& s) { return Replace (s); }
    00794
    00796   const csStringBase& operator = (const csStringBase& copy)
    00797   { Replace(copy); return *this; }
    00798
    00802   template<typename T>
    00803   csStringBase &operator += (T const& s) { return Append (s); }
    00804
    00805   // Specialization which prevents gcc from barfing on strings allocated via
    00806   // CS_ALLOC_STACK_ARRAY().
    00807   csStringBase &operator += (char const* s)
    00808   { return Append(s); }
    00809
    00811   csStringBase operator + (const csStringBase &iStr) const
    00812   { return Clone ().Append (iStr); }
    00813
    00821   operator const char* () const
    00822   { return GetData(); }
    00823
    00830   bool operator == (const csStringBase& Str) const
    00831   { return Compare (Str); }
    00838   bool operator == (const char* Str) const
    00839   { return Compare (Str); }
    00846   bool operator < (const csStringBase& Str) const
    00847   {
    00848     return strcmp (GetDataSafe (), Str.GetDataSafe ()) < 0;
    00849   }
    00856   bool operator < (const char* Str) const
    00857   {
    00858     return strcmp (GetDataSafe (), Str) < 0;
    00859   }
    00866   bool operator > (const csStringBase& Str) const
    00867   {
    00868     return strcmp (GetDataSafe (), Str.GetDataSafe ()) > 0;
    00869   }
    00876   bool operator > (const char* Str) const
    00877   {
    00878     return strcmp (GetDataSafe (), Str) > 0;
    00879   }
    00886   bool operator != (const csStringBase& Str) const
    00887   { return !Compare (Str); }
    00894   bool operator != (const char* Str) const
    00895   { return !Compare (Str); }
    00896
    00904   template <typename T>
    00905   csStringBase &operator << (T const& v)
    00906   { return Append (v); }
    00907
    00908   // Specialization which prevents gcc from barfing on strings allocated via
    00909   // CS_ALLOC_STACK_ARRAY().
    00910   csStringBase &operator << (char const* v)
    00911   { return Append(v); }
    00912
    00917   csStringBase& Downcase();
    00922   csStringBase& Upcase();
    00923
    00934   virtual char* Detach ()
    00935   { char* d = Data; Data = 0; Size = 0; MaxSize = 0; return d; }
    00940   uint GetHash() const;
    00941 };
    00942
    00944 inline csStringBase operator + (const char* iStr1, const csStringBase &iStr2)
    00945 {
    00946   return csStringBase (iStr1).Append (iStr2);
    00947 }
    00948
    00950 inline csStringBase operator + (const csStringBase& iStr1, const char* iStr2)
    00951 {
    00952   return iStr1.Clone ().Append (iStr2);
    00953 }
    00954
    00959 template<int LEN = 36>
    00960 class csStringFast : public csStringBase
    00961 {
    00962 protected:
    00964   char minibuff[LEN];
    00973   size_t miniused;
    00974
    00975   virtual void SetCapacityInternal (size_t NewSize, bool soft)
    00976   {
    00977     if (Data != 0) // If dynamic buffer already allocated, just re-use it.
    00978       csStringBase::SetCapacityInternal(NewSize, soft);
    00979     else
    00980     {
    00981       NewSize++; // Plus one for implicit null byte.
    00982       if (NewSize <= LEN)
    00983         miniused = NewSize;
    00984       else
    00985       {
    00986         CS_ASSERT(MaxSize == 0);
    00987         if (soft)
    00988           NewSize = ComputeNewSize (NewSize);
    00989         Data = new char[NewSize];
    00990         MaxSize = NewSize;
    00991         if (Size == 0)
    00992           Data[0] = '\0';
    00993         else
    00994           memcpy(Data, minibuff, Size + 1);
    00995       }
    00996     }
    00997   }
    00998
    00999   virtual char* GetDataMutable ()
    01000   { return (miniused == 0 && Data == 0 ? 0 : (Data != 0 ? Data : minibuff)); }
    01001
    01002 public:
    01006   csStringFast () : csStringBase(), miniused(0) { }
    01011   csStringFast (size_t Length) : csStringBase(), miniused(0)
    01012   { SetCapacity (Length); }
    01016   csStringFast (const csStringBase& copy) : csStringBase (), miniused(0)
    01017   { Append (copy); }
    01021   csStringFast (const csStringFast& copy) : csStringBase (), miniused(0)
    01022   { Append (copy); }
    01026   csStringFast (const char* src) : csStringBase(), miniused(0)
    01027   { Append (src); }
    01031   csStringFast (const char* src, size_t _length) : csStringBase(), miniused(0)
    01032   { Append (src, _length); }
    01033
    01034
    01036   csStringFast (char c) : csStringBase(), miniused(0)
    01037   { Append (c); }
    01039   csStringFast (unsigned char c) : csStringBase(), miniused(0)
    01040   { Append ((char)c); }
    01042   virtual ~csStringFast () { }
    01043
    01045   const csStringFast& operator = (const csStringBase& copy)
    01046   { Replace(copy); return *this; }
    01047
    01049   template<typename T>
    01050   const csStringFast& operator = (T const& s) { Replace (s); return *this; }
    01051
    01052   virtual char const* GetData () const
    01053   { return (miniused == 0 && Data == 0 ? 0 : (Data != 0 ? Data : minibuff)); }
    01054
    01055   virtual size_t GetCapacity() const
    01056   { return Data != 0 ? csStringBase::GetCapacity() : miniused - 1; }
    01057
    01058   virtual void ShrinkBestFit ()
    01059   {
    01060     if (Size == 0)
    01061     {
    01062       csStringBase::ShrinkBestFit();
    01063       miniused = 0;
    01064     }
    01065     else
    01066     {
    01067       size_t needed = Size + 1;
    01068       if (needed > LEN)
    01069         csStringBase::ShrinkBestFit();
    01070       else
    01071       {
    01072         miniused = needed;
    01073         if (Data != 0)
    01074         {
    01075           memcpy(minibuff, Data, needed); // Includes implicit null byte.
    01076           csStringBase::Free();
    01077         }
    01078       }
    01079     }
    01080   }
    01081
    01082   virtual void Free () { miniused = 0; csStringBase::Free(); }
    01083
    01084   virtual char* Detach ()
    01085   {
    01086     if (Data != 0)
    01087       return csStringBase::Detach();
    01088     else if (miniused == 0)
    01089       return 0; // Emulate NULL return of csStringBase in this case.
    01090     else
    01091     {
    01092       CS_ASSERT(MaxSize == 0);
    01093       char* d = csStrNew (minibuff);
    01094       Size = 0; miniused = 0;
    01095       return d;
    01096     }
    01097   }
    01098 };
    01099
    01100 template<>
    01101 class csStringFast<0> : public csStringBase
    01102 {
    01103 public:
    01104   csStringFast () : csStringBase() { }
    01105   csStringFast (size_t Length) : csStringBase(Length) { }
    01106   csStringFast (const csStringBase& copy) : csStringBase (copy) { }
    01107   csStringFast (const char* src) : csStringBase(src) { }
    01108   csStringFast (const char* src, size_t _length) : csStringBase(src, _length)
    01109   { }
    01110   csStringFast (char c) : csStringBase(c) { }
    01111   csStringFast (unsigned char c) : csStringBase(c) { }
    01112   const csStringFast& operator = (const csStringBase& copy)
    01113   { Replace(copy); return *this; }
    01114   const csStringFast& operator = (const char* copy)
    01115   { Replace(copy); return *this; }
    01116   const csStringFast& operator = (char x)
    01117   { Replace(x); return *this; }
    01118   const csStringFast& operator = (unsigned char x)
    01119   { Replace(x); return *this; }
    01120   const csStringFast& operator = (bool x)
    01121   { Replace(x); return *this; }
    01122   const csStringFast& operator = (short x)
    01123   { Replace(x); return *this; }
    01124   const csStringFast& operator = (unsigned short x)
    01125   { Replace(x); return *this; }
    01126   const csStringFast& operator = (int x)
    01127   { Replace(x); return *this; }
    01128   const csStringFast& operator = (unsigned int x)
    01129   { Replace(x); return *this; }
    01130   const csStringFast& operator = (long x)
    01131   { Replace(x); return *this; }
    01132   const csStringFast& operator = (unsigned long x)
    01133   { Replace(x); return *this; }
    01134   const csStringFast& operator = (float x)
    01135   { Replace(x); return *this; }
    01136   const csStringFast& operator = (double x)
    01137   { Replace(x); return *this; }
    01138 #ifndef __STRICT_ANSI__
    01139   const csStringFast& operator = (longlong x)
    01140   { Replace(x); return *this; }
    01141   const csStringFast& operator = (ulonglong x)
    01142   { Replace(x); return *this; }
    01143 #endif
    01144 };
    01145
    01146 #ifndef SWIG
    01147
    01152 typedef csStringFast<> csStringFastDefault;
    01153 #else
    01154 #define csStringFastDefault csStringFast<36>
    01155 %template(csStringParent) csStringFast<36>;
    01156 #endif
    01157
    01161 class csString : public csStringFastDefault
    01162 {
    01163 public:
    01165   csString () : csStringFast<> () { }
    01170   csString (size_t Length) : csStringFast<> (Length) { }
    01172
    01173   csString (const csString& copy) :
    01174     csStringFast<> ((const csStringBase&)copy) { }
    01175   csString (const csStringBase& copy) : csStringFast<> (copy) { }
    01177
    01178   csString (const char* src) : csStringFast<> (src) { }
    01180   csString (const char* src, size_t _length) : csStringFast<> (src, _length) { }
    01182   csString (char c) : csStringFast<> (c) { }
    01184   csString (unsigned char c) : csStringFast<> (c) { }
    01185
    01187
    01188   const csString& operator = (const csString& copy)
    01189   { Replace(copy); return *this; }
    01190   const csString& operator = (const csStringBase& copy)
    01191   { Replace(copy); return *this; }
    01192   const csString& operator = (const char* copy)
    01193   { Replace(copy); return *this; }
    01194   const csString& operator = (char x)
    01195   { Replace(x); return *this; }
    01196   const csString& operator = (unsigned char x)
    01197   { Replace(x); return *this; }
    01198   const csString& operator = (bool x)
    01199   { Replace(x); return *this; }
    01200   const csString& operator = (short x)
    01201   { Replace(x); return *this; }
    01202   const csString& operator = (unsigned short x)
    01203   { Replace(x); return *this; }
    01204   const csString& operator = (int x)
    01205   { Replace(x); return *this; }
    01206   const csString& operator = (unsigned int x)
    01207   { Replace(x); return *this; }
    01208   const csString& operator = (long x)
    01209   { Replace(x); return *this; }
    01210   const csString& operator = (unsigned long x)
    01211   { Replace(x); return *this; }
    01212   const csString& operator = (float x)
    01213   { Replace(x); return *this; }
    01214   const csString& operator = (double x)
    01215   { Replace(x); return *this; }
    01216 #ifndef __STRICT_ANSI__
    01217   const csString& operator = (longlong x)
    01218   { Replace(x); return *this; }
    01219   const csString& operator = (ulonglong x)
    01220   { Replace(x); return *this; }
    01221 #endif
    01222
    01223 };
    01224
    01225 #endif // __CS_CSSTRING_H__