Home | History | Annotate | Download | only in Common
      1 // Common/String.h
      2 
      3 #ifndef __COMMON_STRING_H
      4 #define __COMMON_STRING_H
      5 
      6 #include <string.h>
      7 
      8 #include "MyVector.h"
      9 
     10 template <class T>
     11 inline int MyStringLen(const T *s)
     12 {
     13   int i;
     14   for (i = 0; s[i] != '\0'; i++);
     15   return i;
     16 }
     17 
     18 template <class T>
     19 inline T * MyStringCopy(T *dest, const T *src)
     20 {
     21   T *destStart = dest;
     22   while ((*dest++ = *src++) != 0);
     23   return destStart;
     24 }
     25 
     26 inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)
     27   { return (p + 1); }
     28 inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)
     29   { return (p + 1); }
     30 inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)
     31   { return (p - 1); }
     32 inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)
     33   { return (p - 1); }
     34 
     35 #ifdef _WIN32
     36 
     37 inline const char* MyStringGetNextCharPointer(const char *p)
     38 {
     39   #ifdef UNDER_CE
     40   return p + 1;
     41   #else
     42   return CharNextA(p);
     43   #endif
     44 }
     45 
     46 inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)
     47   { return CharPrevA(base, p); }
     48 
     49 inline char MyCharUpper(char c)
     50   { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }
     51 #ifdef _UNICODE
     52 inline wchar_t MyCharUpper(wchar_t c)
     53   { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); }
     54 #else
     55 wchar_t MyCharUpper(wchar_t c);
     56 #endif
     57 
     58 #ifdef _UNICODE
     59 inline wchar_t MyCharLower(wchar_t c)
     60   { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); }
     61 #else
     62 wchar_t MyCharLower(wchar_t c);
     63 #endif
     64 
     65 inline char MyCharLower(char c)
     66 #ifdef UNDER_CE
     67   { return (char)MyCharLower((wchar_t)c); }
     68 #else
     69   { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }
     70 #endif
     71 
     72 inline char * MyStringUpper(char *s) { return CharUpperA(s); }
     73 #ifdef _UNICODE
     74 inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
     75 #else
     76 wchar_t * MyStringUpper(wchar_t *s);
     77 #endif
     78 
     79 inline char * MyStringLower(char *s) { return CharLowerA(s); }
     80 #ifdef _UNICODE
     81 inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
     82 #else
     83 wchar_t * MyStringLower(wchar_t *s);
     84 #endif
     85 
     86 #else // Standard-C
     87 wchar_t MyCharUpper(wchar_t c);
     88 #endif
     89 
     90 //////////////////////////////////////
     91 // Compare
     92 
     93 /*
     94 #ifndef UNDER_CE
     95 int MyStringCollate(const char *s1, const char *s2);
     96 int MyStringCollateNoCase(const char *s1, const char *s2);
     97 #endif
     98 int MyStringCollate(const wchar_t *s1, const wchar_t *s2);
     99 int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2);
    100 */
    101 
    102 int MyStringCompare(const char *s1, const char  *s2);
    103 int MyStringCompare(const wchar_t *s1, const wchar_t *s2);
    104 
    105 // int MyStringCompareNoCase(const char *s1, const char  *s2);
    106 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2);
    107 
    108 template <class T>
    109 class CStringBase
    110 {
    111   void TrimLeftWithCharSet(const CStringBase &charSet)
    112   {
    113     const T *p = _chars;
    114     while (charSet.Find(*p) >= 0 && (*p != 0))
    115       p = GetNextCharPointer(p);
    116     Delete(0, (int)(p - _chars));
    117   }
    118   void TrimRightWithCharSet(const CStringBase &charSet)
    119   {
    120     const T *p = _chars;
    121     const T *pLast = NULL;
    122     while (*p != 0)
    123     {
    124       if (charSet.Find(*p) >= 0)
    125       {
    126         if (pLast == NULL)
    127           pLast = p;
    128       }
    129       else
    130         pLast = NULL;
    131       p = GetNextCharPointer(p);
    132     }
    133     if (pLast != NULL)
    134     {
    135       int i = (int)(pLast - _chars);
    136       Delete(i, _length - i);
    137     }
    138 
    139   }
    140   void MoveItems(int destIndex, int srcIndex)
    141   {
    142     memmove(_chars + destIndex, _chars + srcIndex,
    143         sizeof(T) * (_length - srcIndex + 1));
    144   }
    145 
    146   void InsertSpace(int &index, int size)
    147   {
    148     CorrectIndex(index);
    149     GrowLength(size);
    150     MoveItems(index + size, index);
    151   }
    152 
    153   static const T *GetNextCharPointer(const T *p)
    154     { return MyStringGetNextCharPointer(p); }
    155   static const T *GetPrevCharPointer(const T *base, const T *p)
    156     { return MyStringGetPrevCharPointer(base, p); }
    157 protected:
    158   T *_chars;
    159   int _length;
    160   int _capacity;
    161 
    162   void SetCapacity(int newCapacity)
    163   {
    164     int realCapacity = newCapacity + 1;
    165     if (realCapacity == _capacity)
    166       return;
    167     /*
    168     const int kMaxStringSize = 0x20000000;
    169     if (newCapacity > kMaxStringSize || newCapacity < _length)
    170       throw 1052337;
    171     */
    172     T *newBuffer = new T[realCapacity];
    173     if (_capacity > 0)
    174     {
    175       for (int i = 0; i < _length; i++)
    176         newBuffer[i] = _chars[i];
    177       delete []_chars;
    178     }
    179     _chars = newBuffer;
    180     _chars[_length] = 0;
    181     _capacity = realCapacity;
    182   }
    183 
    184   void GrowLength(int n)
    185   {
    186     int freeSize = _capacity - _length - 1;
    187     if (n <= freeSize)
    188       return;
    189     int delta;
    190     if (_capacity > 64)
    191       delta = _capacity / 2;
    192     else if (_capacity > 8)
    193       delta = 16;
    194     else
    195       delta = 4;
    196     if (freeSize + delta < n)
    197       delta = n - freeSize;
    198     SetCapacity(_capacity + delta);
    199   }
    200 
    201   void CorrectIndex(int &index) const
    202   {
    203     if (index > _length)
    204       index = _length;
    205   }
    206 
    207 public:
    208   CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); }
    209   CStringBase(T c):  _chars(0), _length(0), _capacity(0)
    210   {
    211     SetCapacity(1);
    212     _chars[0] = c;
    213     _chars[1] = 0;
    214     _length = 1;
    215   }
    216   CStringBase(const T *chars): _chars(0), _length(0), _capacity(0)
    217   {
    218     int length = MyStringLen(chars);
    219     SetCapacity(length);
    220     MyStringCopy(_chars, chars); // can be optimized by memove()
    221     _length = length;
    222   }
    223   CStringBase(const CStringBase &s):  _chars(0), _length(0), _capacity(0)
    224   {
    225     SetCapacity(s._length);
    226     MyStringCopy(_chars, s._chars);
    227     _length = s._length;
    228   }
    229   ~CStringBase() {  delete []_chars; }
    230 
    231   operator const T*() const { return _chars;}
    232 
    233   T Back() const { return _chars[_length - 1]; }
    234 
    235   // The minimum size of the character buffer in characters.
    236   // This value does not include space for a null terminator.
    237   T* GetBuffer(int minBufLength)
    238   {
    239     if (minBufLength >= _capacity)
    240       SetCapacity(minBufLength);
    241     return _chars;
    242   }
    243   void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
    244   void ReleaseBuffer(int newLength)
    245   {
    246     /*
    247     if (newLength >= _capacity)
    248       throw 282217;
    249     */
    250     _chars[newLength] = 0;
    251     _length = newLength;
    252   }
    253 
    254   CStringBase& operator=(T c)
    255   {
    256     Empty();
    257     SetCapacity(1);
    258     _chars[0] = c;
    259     _chars[1] = 0;
    260     _length = 1;
    261     return *this;
    262   }
    263   CStringBase& operator=(const T *chars)
    264   {
    265     Empty();
    266     int length = MyStringLen(chars);
    267     SetCapacity(length);
    268     MyStringCopy(_chars, chars);
    269     _length = length;
    270     return *this;
    271   }
    272   CStringBase& operator=(const CStringBase& s)
    273   {
    274     if (&s == this)
    275       return *this;
    276     Empty();
    277     SetCapacity(s._length);
    278     MyStringCopy(_chars, s._chars);
    279     _length = s._length;
    280     return *this;
    281   }
    282 
    283   CStringBase& operator+=(T c)
    284   {
    285     GrowLength(1);
    286     _chars[_length] = c;
    287     _chars[++_length] = 0;
    288     return *this;
    289   }
    290   CStringBase& operator+=(const T *s)
    291   {
    292     int len = MyStringLen(s);
    293     GrowLength(len);
    294     MyStringCopy(_chars + _length, s);
    295     _length += len;
    296     return *this;
    297   }
    298   CStringBase& operator+=(const CStringBase &s)
    299   {
    300     GrowLength(s._length);
    301     MyStringCopy(_chars + _length, s._chars);
    302     _length += s._length;
    303     return *this;
    304   }
    305   void Empty()
    306   {
    307     _length = 0;
    308     _chars[0] = 0;
    309   }
    310   int Length() const { return _length; }
    311   bool IsEmpty() const { return (_length == 0); }
    312 
    313   CStringBase Mid(int startIndex) const
    314     { return Mid(startIndex, _length - startIndex); }
    315   CStringBase Mid(int startIndex, int count) const
    316   {
    317     if (startIndex + count > _length)
    318       count = _length - startIndex;
    319 
    320     if (startIndex == 0 && startIndex + count == _length)
    321       return *this;
    322 
    323     CStringBase<T> result;
    324     result.SetCapacity(count);
    325     // MyStringNCopy(result._chars, _chars + startIndex, count);
    326     for (int i = 0; i < count; i++)
    327       result._chars[i] = _chars[startIndex + i];
    328     result._chars[count] = 0;
    329     result._length = count;
    330     return result;
    331   }
    332   CStringBase Left(int count) const
    333     { return Mid(0, count); }
    334   CStringBase Right(int count) const
    335   {
    336     if (count > _length)
    337       count = _length;
    338     return Mid(_length - count, count);
    339   }
    340 
    341   void MakeUpper()
    342     { MyStringUpper(_chars); }
    343   void MakeLower()
    344     { MyStringLower(_chars); }
    345 
    346   int Compare(const CStringBase& s) const
    347     { return MyStringCompare(_chars, s._chars); }
    348 
    349   int Compare(const T *s) const
    350     { return MyStringCompare(_chars, s); }
    351 
    352   int CompareNoCase(const CStringBase& s) const
    353     { return MyStringCompareNoCase(_chars, s._chars); }
    354 
    355   int CompareNoCase(const T *s) const
    356     { return MyStringCompareNoCase(_chars, s); }
    357 
    358   /*
    359   int Collate(const CStringBase& s) const
    360     { return MyStringCollate(_chars, s._chars); }
    361   int CollateNoCase(const CStringBase& s) const
    362     { return MyStringCollateNoCase(_chars, s._chars); }
    363   */
    364 
    365   int Find(T c) const { return Find(c, 0); }
    366   int Find(T c, int startIndex) const
    367   {
    368     const T *p = _chars + startIndex;
    369     for (;;)
    370     {
    371       if (*p == c)
    372         return (int)(p - _chars);
    373       if (*p == 0)
    374         return -1;
    375       p = GetNextCharPointer(p);
    376     }
    377   }
    378   int Find(const CStringBase &s) const { return Find(s, 0); }
    379   int Find(const CStringBase &s, int startIndex) const
    380   {
    381     if (s.IsEmpty())
    382       return startIndex;
    383     for (; startIndex < _length; startIndex++)
    384     {
    385       int j;
    386       for (j = 0; j < s._length && startIndex + j < _length; j++)
    387         if (_chars[startIndex+j] != s._chars[j])
    388           break;
    389       if (j == s._length)
    390         return startIndex;
    391     }
    392     return -1;
    393   }
    394   int ReverseFind(T c) const
    395   {
    396     if (_length == 0)
    397       return -1;
    398     const T *p = _chars + _length - 1;
    399     for (;;)
    400     {
    401       if (*p == c)
    402         return (int)(p - _chars);
    403       if (p == _chars)
    404         return -1;
    405       p = GetPrevCharPointer(_chars, p);
    406     }
    407   }
    408   int FindOneOf(const CStringBase &s) const
    409   {
    410     for (int i = 0; i < _length; i++)
    411       if (s.Find(_chars[i]) >= 0)
    412         return i;
    413       return -1;
    414   }
    415 
    416   void TrimLeft(T c)
    417   {
    418     const T *p = _chars;
    419     while (c == *p)
    420       p = GetNextCharPointer(p);
    421     Delete(0, p - _chars);
    422   }
    423   private:
    424   CStringBase GetTrimDefaultCharSet()
    425   {
    426     CStringBase<T> charSet;
    427     charSet += (T)' ';
    428     charSet += (T)'\n';
    429     charSet += (T)'\t';
    430     return charSet;
    431   }
    432   public:
    433 
    434   void TrimLeft()
    435   {
    436     TrimLeftWithCharSet(GetTrimDefaultCharSet());
    437   }
    438   void TrimRight()
    439   {
    440     TrimRightWithCharSet(GetTrimDefaultCharSet());
    441   }
    442   void TrimRight(T c)
    443   {
    444     const T *p = _chars;
    445     const T *pLast = NULL;
    446     while (*p != 0)
    447     {
    448       if (*p == c)
    449       {
    450         if (pLast == NULL)
    451           pLast = p;
    452       }
    453       else
    454         pLast = NULL;
    455       p = GetNextCharPointer(p);
    456     }
    457     if (pLast != NULL)
    458     {
    459       int i = pLast - _chars;
    460       Delete(i, _length - i);
    461     }
    462   }
    463   void Trim()
    464   {
    465     TrimRight();
    466     TrimLeft();
    467   }
    468 
    469   int Insert(int index, T c)
    470   {
    471     InsertSpace(index, 1);
    472     _chars[index] = c;
    473     _length++;
    474     return _length;
    475   }
    476   int Insert(int index, const CStringBase &s)
    477   {
    478     CorrectIndex(index);
    479     if (s.IsEmpty())
    480       return _length;
    481     int numInsertChars = s.Length();
    482     InsertSpace(index, numInsertChars);
    483     for (int i = 0; i < numInsertChars; i++)
    484       _chars[index + i] = s[i];
    485     _length += numInsertChars;
    486     return _length;
    487   }
    488 
    489   // !!!!!!!!!!!!!!! test it if newChar = '\0'
    490   int Replace(T oldChar, T newChar)
    491   {
    492     if (oldChar == newChar)
    493       return 0;
    494     int number  = 0;
    495     int pos  = 0;
    496     while (pos < Length())
    497     {
    498       pos = Find(oldChar, pos);
    499       if (pos < 0)
    500         break;
    501       _chars[pos] = newChar;
    502       pos++;
    503       number++;
    504     }
    505     return number;
    506   }
    507   int Replace(const CStringBase &oldString, const CStringBase &newString)
    508   {
    509     if (oldString.IsEmpty())
    510       return 0;
    511     if (oldString == newString)
    512       return 0;
    513     int oldStringLength = oldString.Length();
    514     int newStringLength = newString.Length();
    515     int number  = 0;
    516     int pos  = 0;
    517     while (pos < _length)
    518     {
    519       pos = Find(oldString, pos);
    520       if (pos < 0)
    521         break;
    522       Delete(pos, oldStringLength);
    523       Insert(pos, newString);
    524       pos += newStringLength;
    525       number++;
    526     }
    527     return number;
    528   }
    529   int Delete(int index, int count = 1)
    530   {
    531     if (index + count > _length)
    532       count = _length - index;
    533     if (count > 0)
    534     {
    535       MoveItems(index, index + count);
    536       _length -= count;
    537     }
    538     return _length;
    539   }
    540   void DeleteBack() { Delete(_length - 1); }
    541 };
    542 
    543 template <class T>
    544 CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)
    545 {
    546   CStringBase<T> result(s1);
    547   result += s2;
    548   return result;
    549 }
    550 
    551 template <class T>
    552 CStringBase<T> operator+(const CStringBase<T>& s, T c)
    553 {
    554   CStringBase<T> result(s);
    555   result += c;
    556   return result;
    557 }
    558 
    559 template <class T>
    560 CStringBase<T> operator+(T c, const CStringBase<T>& s)
    561 {
    562   CStringBase<T> result(c);
    563   result += s;
    564   return result;
    565 }
    566 
    567 template <class T>
    568 CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)
    569 {
    570   CStringBase<T> result(s);
    571   result += chars;
    572   return result;
    573 }
    574 
    575 template <class T>
    576 CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)
    577 {
    578   CStringBase<T> result(chars);
    579   result += s;
    580   return result;
    581 }
    582 
    583 template <class T>
    584 bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)
    585   { return (s1.Compare(s2) == 0); }
    586 
    587 template <class T>
    588 bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)
    589   { return (s1.Compare(s2) < 0); }
    590 
    591 template <class T>
    592 bool operator==(const T *s1, const CStringBase<T>& s2)
    593   { return (s2.Compare(s1) == 0); }
    594 
    595 template <class T>
    596 bool operator==(const CStringBase<T>& s1, const T *s2)
    597   { return (s1.Compare(s2) == 0); }
    598 
    599 template <class T>
    600 bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)
    601   { return (s1.Compare(s2) != 0); }
    602 
    603 template <class T>
    604 bool operator!=(const T *s1, const CStringBase<T>& s2)
    605   { return (s2.Compare(s1) != 0); }
    606 
    607 template <class T>
    608 bool operator!=(const CStringBase<T>& s1, const T *s2)
    609   { return (s1.Compare(s2) != 0); }
    610 
    611 typedef CStringBase<char> AString;
    612 typedef CStringBase<wchar_t> UString;
    613 
    614 typedef CObjectVector<AString> AStringVector;
    615 typedef CObjectVector<UString> UStringVector;
    616 
    617 #ifdef _UNICODE
    618   typedef UString CSysString;
    619 #else
    620   typedef AString CSysString;
    621 #endif
    622 
    623 typedef CObjectVector<CSysString> CSysStringVector;
    624 
    625 #endif
    626