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 #ifndef _WIN32
      9 #include <wctype.h>
     10 #include <wchar.h>
     11 #endif
     12 
     13 #include "MyTypes.h"
     14 #include "MyVector.h"
     15 
     16 inline unsigned MyStringLen(const char *s)
     17 {
     18   unsigned i;
     19   for (i = 0; s[i] != 0; i++);
     20   return i;
     21 }
     22 
     23 inline void MyStringCopy(char *dest, const char *src)
     24 {
     25   while ((*dest++ = *src++) != 0);
     26 }
     27 
     28 inline char *MyStpCpy(char *dest, const char *src)
     29 {
     30   for (;;)
     31   {
     32     char c = *src;
     33     *dest = c;
     34     if (c == 0)
     35       return dest;
     36     src++;
     37     dest++;
     38   }
     39 }
     40 
     41 inline unsigned MyStringLen(const wchar_t *s)
     42 {
     43   unsigned i;
     44   for (i = 0; s[i] != 0; i++);
     45   return i;
     46 }
     47 
     48 inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
     49 {
     50   while ((*dest++ = *src++) != 0);
     51 }
     52 
     53 int FindCharPosInString(const char *s, char c) throw();
     54 int FindCharPosInString(const wchar_t *s, wchar_t c) throw();
     55 
     56 #ifdef _WIN32
     57   #ifndef _UNICODE
     58     #define STRING_UNICODE_THROW
     59   #endif
     60 #endif
     61 
     62 #ifndef STRING_UNICODE_THROW
     63   #define STRING_UNICODE_THROW throw()
     64 #endif
     65 
     66 /*
     67 inline char MyCharUpper_Ascii(char c)
     68 {
     69   if (c >= 'a' && c <= 'z')
     70     return (char)(c - 0x20);
     71   return c;
     72 }
     73 inline wchar_t MyCharUpper_Ascii(wchar_t c)
     74 {
     75   if (c >= 'a' && c <= 'z')
     76     return (wchar_t)(c - 0x20);
     77   return c;
     78 }
     79 */
     80 
     81 inline char MyCharLower_Ascii(char c)
     82 {
     83   if (c >= 'A' && c <= 'Z')
     84     return (char)(c + 0x20);
     85   return c;
     86 }
     87 
     88 inline wchar_t MyCharLower_Ascii(wchar_t c)
     89 {
     90   if (c >= 'A' && c <= 'Z')
     91     return (wchar_t)(c + 0x20);
     92   return c;
     93 }
     94 
     95 wchar_t MyCharUpper_WIN(wchar_t c) throw();
     96 
     97 inline wchar_t MyCharUpper(wchar_t c) throw()
     98 {
     99   if (c < 'a') return c;
    100   if (c <= 'z') return (wchar_t)(c - 0x20);
    101   if (c <= 0x7F) return c;
    102   #ifdef _WIN32
    103     #ifdef _UNICODE
    104       return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
    105     #else
    106       return (wchar_t)MyCharUpper_WIN(c);
    107     #endif
    108   #else
    109     return (wchar_t)towupper(c);
    110   #endif
    111 }
    112 
    113 /*
    114 wchar_t MyCharLower_WIN(wchar_t c) throw();
    115 
    116 inline wchar_t MyCharLower(wchar_t c) throw()
    117 {
    118   if (c < 'A') return c;
    119   if (c <= 'Z') return (wchar_t)(c + 0x20);
    120   if (c <= 0x7F) return c;
    121   #ifdef _WIN32
    122     #ifdef _UNICODE
    123       return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
    124     #else
    125       return (wchar_t)MyCharLower_WIN(c);
    126     #endif
    127   #else
    128     return (wchar_t)tolower(c);
    129   #endif
    130 }
    131 */
    132 
    133 // char *MyStringUpper(char *s) throw();
    134 // char *MyStringLower(char *s) throw();
    135 
    136 // void MyStringUpper_Ascii(wchar_t *s) throw();
    137 void MyStringLower_Ascii(wchar_t *s) throw();
    138 // wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW;
    139 // wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW;
    140 
    141 bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
    142 
    143 bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
    144 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
    145 
    146 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();
    147 int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();
    148 
    149 // ---------- ASCII ----------
    150 // char values in ASCII strings must be less then 128
    151 bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();
    152 bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();
    153 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();
    154 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw();
    155 
    156 #define MY_STRING_DELETE(_p_) delete []_p_;
    157 // #define MY_STRING_DELETE(_p_) my_delete(_p_);
    158 
    159 class AString
    160 {
    161   char *_chars;
    162   unsigned _len;
    163   unsigned _limit;
    164 
    165   void MoveItems(unsigned dest, unsigned src)
    166   {
    167     memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char));
    168   }
    169 
    170   void InsertSpace(unsigned &index, unsigned size);
    171 
    172   void ReAlloc(unsigned newLimit);
    173   void SetStartLen(unsigned len);
    174   void Grow_1();
    175   void Grow(unsigned n);
    176 
    177   // AString(unsigned num, const char *s);
    178   AString(unsigned num, const AString &s);
    179   AString(const AString &s, char c); // it's for String + char
    180   AString(const char *s1, unsigned num1, const char *s2, unsigned num2);
    181 
    182   friend AString operator+(const AString &s, char c) { return AString(s, c); } ;
    183   // friend AString operator+(char c, const AString &s); // is not supported
    184 
    185   friend AString operator+(const AString &s1, const AString &s2);
    186   friend AString operator+(const AString &s1, const char    *s2);
    187   friend AString operator+(const char    *s1, const AString &s2);
    188 
    189 public:
    190   AString();
    191   AString(char c);
    192   AString(const char *s);
    193   AString(const AString &s);
    194   ~AString() { MY_STRING_DELETE(_chars); }
    195 
    196   unsigned Len() const { return _len; }
    197   bool IsEmpty() const { return _len == 0; }
    198   void Empty() { _len = 0; _chars[0] = 0; }
    199 
    200   operator const char *() const { return _chars; }
    201   const char *Ptr() const { return _chars; }
    202   const char *Ptr(unsigned pos) const { return _chars + pos; }
    203   const char *RightPtr(unsigned num) const { return _chars + _len - num; }
    204   char Back() const { return _chars[_len - 1]; }
    205 
    206   void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
    207 
    208   // The minimum size of the character buffer in characters.
    209   // This value does not include space for a null terminator.
    210   char *GetBuffer(unsigned minBufLen)
    211   {
    212     if (minBufLen > _limit)
    213       ReAlloc(minBufLen);
    214     return _chars;
    215   }
    216   void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
    217   void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
    218 
    219   AString &operator=(char c);
    220   AString &operator=(const char *s);
    221   AString &operator=(const AString &s);
    222 
    223   AString &operator+=(char c)
    224   {
    225     if (_limit == _len)
    226       Grow_1();
    227     unsigned len = _len;
    228     char *chars = _chars;
    229     chars[len++] = c;
    230     chars[len] = 0;
    231     _len = len;
    232     return *this;
    233   }
    234 
    235   AString &operator+=(const char *s);
    236   AString &operator+=(const AString &s);
    237 
    238   void SetFrom(const char *s, unsigned len); // no check
    239   // AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
    240   AString Left(unsigned count) const { return AString(count, *this); }
    241 
    242   // void MakeUpper() { MyStringUpper(_chars); }
    243   // void MakeLower() { MyStringLower(_chars); }
    244 
    245 
    246   // int Compare(const char *s) const { return MyStringCompare(_chars, s); }
    247   // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }
    248   // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }
    249   // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
    250   bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
    251   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
    252 
    253   int Find(char c) const { return FindCharPosInString(_chars, c); }
    254   int Find(char c, unsigned startIndex) const
    255   {
    256     int pos = FindCharPosInString(_chars + startIndex, c);
    257     return pos < 0 ? -1 : (int)startIndex + pos;
    258   }
    259   int ReverseFind(char c) const throw();
    260   int Find(const AString &s) const { return Find(s, 0); }
    261   int Find(const AString &s, unsigned startIndex) const throw();
    262 
    263   void TrimLeft() throw();
    264   void TrimRight() throw();
    265   void Trim()
    266   {
    267     TrimRight();
    268     TrimLeft();
    269   }
    270 
    271   void InsertAtFront(char c);
    272   // void Insert(unsigned index, char c);
    273   void Insert(unsigned index, const char *s);
    274   void Insert(unsigned index, const AString &s);
    275 
    276   void RemoveChar(char ch) throw();
    277   void Replace(char oldChar, char newChar) throw();
    278   void Replace(const AString &oldString, const AString &newString);
    279 
    280   void Delete(unsigned index) throw();
    281   void Delete(unsigned index, unsigned count) throw();
    282   void DeleteFrontal(unsigned num) throw();
    283   void DeleteBack() { _chars[--_len] = 0; }
    284   void DeleteFrom(unsigned index)
    285   {
    286     if (index < _len)
    287     {
    288       _len = index;
    289       _chars[index] = 0;
    290     }
    291   }
    292 };
    293 
    294 bool operator<(const AString &s1, const AString &s2);
    295 bool operator>(const AString &s1, const AString &s2);
    296 
    297 /*
    298 bool operator==(const AString &s1, const AString &s2);
    299 bool operator==(const AString &s1, const char    *s2);
    300 bool operator==(const char    *s1, const AString &s2);
    301 
    302 bool operator!=(const AString &s1, const AString &s2);
    303 bool operator!=(const AString &s1, const char    *s2);
    304 bool operator!=(const char    *s1, const AString &s2);
    305 */
    306 
    307 inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }
    308 inline bool operator==(const AString &s1, const char    *s2) { return strcmp(s1, s2) == 0; }
    309 inline bool operator==(const char    *s1, const AString &s2) { return strcmp(s1, s2) == 0; }
    310 
    311 inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }
    312 inline bool operator!=(const AString &s1, const char    *s2) { return strcmp(s1, s2) != 0; }
    313 inline bool operator!=(const char    *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
    314 
    315 
    316 
    317 class UString
    318 {
    319   wchar_t *_chars;
    320   unsigned _len;
    321   unsigned _limit;
    322 
    323   void MoveItems(unsigned dest, unsigned src)
    324   {
    325     memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t));
    326   }
    327 
    328   void InsertSpace(unsigned index, unsigned size);
    329 
    330   void ReAlloc(unsigned newLimit);
    331   void SetStartLen(unsigned len);
    332   void Grow_1();
    333   void Grow(unsigned n);
    334 
    335   UString(unsigned num, const wchar_t *s); // for Mid
    336   UString(unsigned num, const UString &s); // for Left
    337   UString(const UString &s, wchar_t c); // it's for String + char
    338   UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2);
    339 
    340   friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ;
    341   // friend UString operator+(wchar_t c, const UString &s); // is not supported
    342 
    343   friend UString operator+(const UString &s1, const UString &s2);
    344   friend UString operator+(const UString &s1, const wchar_t *s2);
    345   friend UString operator+(const wchar_t *s1, const UString &s2);
    346 
    347 public:
    348   UString();
    349   UString(wchar_t c);
    350   UString(const wchar_t *s);
    351   UString(const UString &s);
    352   ~UString() { MY_STRING_DELETE(_chars); }
    353 
    354   unsigned Len() const { return _len; }
    355   bool IsEmpty() const { return _len == 0; }
    356   void Empty() { _len = 0; _chars[0] = 0; }
    357 
    358   operator const wchar_t *() const { return _chars; }
    359   const wchar_t *Ptr() const { return _chars; }
    360   const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
    361   const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
    362   wchar_t Back() const { return _chars[_len - 1]; }
    363 
    364   void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
    365 
    366   // The minimum size of the character buffer in characters.
    367   // This value does not include space for a null terminator.
    368   wchar_t *GetBuffer(unsigned minBufLen)
    369   {
    370     if (minBufLen > _limit)
    371       ReAlloc(minBufLen);
    372     return _chars;
    373   }
    374   void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
    375   void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
    376 
    377   UString &operator=(wchar_t c);
    378   UString &operator=(const wchar_t *s);
    379   UString &operator=(const UString &s);
    380 
    381   UString &operator+=(wchar_t c)
    382   {
    383     if (_limit == _len)
    384       Grow_1();
    385     unsigned len = _len;
    386     wchar_t *chars = _chars;
    387     chars[len++] = c;
    388     chars[len] = 0;
    389     _len = len;
    390     return *this;
    391   }
    392 
    393   UString &operator+=(const wchar_t *s);
    394   UString &operator+=(const UString &s);
    395 
    396   void SetFrom(const wchar_t *s, unsigned len); // no check
    397 
    398   void SetFromAscii(const char *s);
    399   void AddAsciiStr(const char *s);
    400 
    401   UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
    402   UString Left(unsigned count) const { return UString(count, *this); }
    403 
    404   // void MakeUpper() { MyStringUpper(_chars); }
    405   // void MakeUpper() { MyStringUpper_Ascii(_chars); }
    406   // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); }
    407   void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
    408 
    409   bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
    410   bool IsEqualToNoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
    411   int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
    412   // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }
    413   // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }
    414   // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
    415   bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); };
    416   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
    417 
    418   int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
    419   int Find(wchar_t c, unsigned startIndex) const
    420   {
    421     int pos = FindCharPosInString(_chars + startIndex, c);
    422     return pos < 0 ? -1 : (int)startIndex + pos;
    423   }
    424   int Find(const UString &s) const { return Find(s, 0); }
    425   int Find(const UString &s, unsigned startIndex) const throw();
    426   int ReverseFind(wchar_t c) const throw();
    427 
    428   void TrimLeft() throw();
    429   void TrimRight() throw();
    430   void Trim()
    431   {
    432     TrimRight();
    433     TrimLeft();
    434   }
    435 
    436   void InsertAtFront(wchar_t c);
    437   // void Insert(unsigned index, wchar_t c);
    438   void Insert(unsigned index, const wchar_t *s);
    439   void Insert(unsigned index, const UString &s);
    440 
    441   void RemoveChar(wchar_t ch) throw();
    442   void Replace(wchar_t oldChar, wchar_t newChar) throw();
    443   void Replace(const UString &oldString, const UString &newString);
    444 
    445   void Delete(unsigned index) throw();
    446   void Delete(unsigned index, unsigned count) throw();
    447   void DeleteFrontal(unsigned num) throw();
    448   void DeleteBack() { _chars[--_len] = 0; }
    449   void DeleteFrom(unsigned index)
    450   {
    451     if (index < _len)
    452     {
    453       _len = index;
    454       _chars[index] = 0;
    455     }
    456   }
    457 };
    458 
    459 bool operator<(const UString &s1, const UString &s2);
    460 bool operator>(const UString &s1, const UString &s2);
    461 
    462 inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }
    463 inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }
    464 inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }
    465 
    466 inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }
    467 inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }
    468 inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
    469 
    470 
    471 typedef CObjectVector<AString> AStringVector;
    472 typedef CObjectVector<UString> UStringVector;
    473 
    474 #ifdef _UNICODE
    475   typedef UString CSysString;
    476 #else
    477   typedef AString CSysString;
    478 #endif
    479 
    480 typedef CObjectVector<CSysString> CSysStringVector;
    481 
    482 
    483 // ---------- FString ----------
    484 
    485 #ifdef _WIN32
    486   #define USE_UNICODE_FSTRING
    487 #endif
    488 
    489 #ifdef USE_UNICODE_FSTRING
    490 
    491   #define __FTEXT(quote) L##quote
    492 
    493   typedef wchar_t FChar;
    494   typedef UString FString;
    495 
    496   #define fs2us(_x_) (_x_)
    497   #define us2fs(_x_) (_x_)
    498   FString fas2fs(const AString &s);
    499   AString fs2fas(const FChar *s);
    500 
    501 #else
    502 
    503   #define __FTEXT(quote) quote
    504 
    505   typedef char FChar;
    506   typedef AString FString;
    507 
    508   UString fs2us(const FString &s);
    509   FString us2fs(const wchar_t *s);
    510   #define fas2fs(_x_) (_x_)
    511   #define fs2fas(_x_) (_x_)
    512 
    513 #endif
    514 
    515 #define FTEXT(quote) __FTEXT(quote)
    516 
    517 #define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)
    518 #define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)
    519 #define FCHAR_ANY_MASK FTEXT('*')
    520 #define FSTRING_ANY_MASK FTEXT("*")
    521 typedef const FChar *CFSTR;
    522 
    523 typedef CObjectVector<FString> FStringVector;
    524 
    525 #endif
    526