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>
MyStringLen(const T * s)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>
MyStringCopy(T * dest,const T * src)19 inline T * MyStringCopy(T *dest, const T *src)
20 {
21   T *destStart = dest;
22   while ((*dest++ = *src++) != 0);
23   return destStart;
24 }
25 
MyStringGetNextCharPointer(wchar_t * p)26 inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)
27   { return (p + 1); }
MyStringGetNextCharPointer(const wchar_t * p)28 inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)
29   { return (p + 1); }
MyStringGetPrevCharPointer(const wchar_t *,wchar_t * p)30 inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)
31   { return (p - 1); }
MyStringGetPrevCharPointer(const wchar_t *,const wchar_t * p)32 inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)
33   { return (p - 1); }
34 
35 #ifdef _WIN32
36 
MyStringGetNextCharPointer(const char * p)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 
MyStringGetPrevCharPointer(const char * base,const char * p)46 inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)
47   { return CharPrevA(base, p); }
48 
MyCharUpper(char c)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
MyCharUpper(wchar_t c)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
MyCharLower(wchar_t c)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 
MyCharLower(char c)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 
MyStringUpper(char * s)72 inline char * MyStringUpper(char *s) { return CharUpperA(s); }
73 #ifdef _UNICODE
MyStringUpper(wchar_t * s)74 inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
75 #else
76 wchar_t * MyStringUpper(wchar_t *s);
77 #endif
78 
MyStringLower(char * s)79 inline char * MyStringLower(char *s) { return CharLowerA(s); }
80 #ifdef _UNICODE
MyStringLower(wchar_t * s)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 {
TrimLeftWithCharSet(const CStringBase & charSet)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   }
TrimRightWithCharSet(const CStringBase & charSet)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   }
MoveItems(int destIndex,int srcIndex)140   void MoveItems(int destIndex, int srcIndex)
141   {
142     memmove(_chars + destIndex, _chars + srcIndex,
143         sizeof(T) * (_length - srcIndex + 1));
144   }
145 
InsertSpace(int & index,int size)146   void InsertSpace(int &index, int size)
147   {
148     CorrectIndex(index);
149     GrowLength(size);
150     MoveItems(index + size, index);
151   }
152 
GetNextCharPointer(const T * p)153   static const T *GetNextCharPointer(const T *p)
154     { return MyStringGetNextCharPointer(p); }
GetPrevCharPointer(const T * base,const T * 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 
SetCapacity(int newCapacity)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 
GrowLength(int n)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 
CorrectIndex(int & index)201   void CorrectIndex(int &index) const
202   {
203     if (index > _length)
204       index = _length;
205   }
206 
207 public:
CStringBase()208   CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); }
CStringBase(T c)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   }
CStringBase(const T * chars)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   }
CStringBase(const CStringBase & s)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   }
~CStringBase()229   ~CStringBase() {  delete []_chars; }
230 
231   operator const T*() const { return _chars;}
232 
Back()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.
GetBuffer(int minBufLength)237   T* GetBuffer(int minBufLength)
238   {
239     if (minBufLength >= _capacity)
240       SetCapacity(minBufLength);
241     return _chars;
242   }
ReleaseBuffer()243   void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
ReleaseBuffer(int newLength)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   }
Empty()305   void Empty()
306   {
307     _length = 0;
308     _chars[0] = 0;
309   }
Length()310   int Length() const { return _length; }
IsEmpty()311   bool IsEmpty() const { return (_length == 0); }
312 
Mid(int startIndex)313   CStringBase Mid(int startIndex) const
314     { return Mid(startIndex, _length - startIndex); }
Mid(int startIndex,int count)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   }
Left(int count)332   CStringBase Left(int count) const
333     { return Mid(0, count); }
Right(int count)334   CStringBase Right(int count) const
335   {
336     if (count > _length)
337       count = _length;
338     return Mid(_length - count, count);
339   }
340 
MakeUpper()341   void MakeUpper()
342     { MyStringUpper(_chars); }
MakeLower()343   void MakeLower()
344     { MyStringLower(_chars); }
345 
Compare(const CStringBase & s)346   int Compare(const CStringBase& s) const
347     { return MyStringCompare(_chars, s._chars); }
348 
Compare(const T * s)349   int Compare(const T *s) const
350     { return MyStringCompare(_chars, s); }
351 
CompareNoCase(const CStringBase & s)352   int CompareNoCase(const CStringBase& s) const
353     { return MyStringCompareNoCase(_chars, s._chars); }
354 
CompareNoCase(const T * s)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 
Find(T c)365   int Find(T c) const { return Find(c, 0); }
Find(T c,int startIndex)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   }
Find(const CStringBase & s)378   int Find(const CStringBase &s) const { return Find(s, 0); }
Find(const CStringBase & s,int startIndex)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   }
ReverseFind(T c)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   }
FindOneOf(const CStringBase & s)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 
TrimLeft(T c)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:
GetTrimDefaultCharSet()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 
TrimLeft()434   void TrimLeft()
435   {
436     TrimLeftWithCharSet(GetTrimDefaultCharSet());
437   }
TrimRight()438   void TrimRight()
439   {
440     TrimRightWithCharSet(GetTrimDefaultCharSet());
441   }
TrimRight(T c)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   }
Trim()463   void Trim()
464   {
465     TrimRight();
466     TrimLeft();
467   }
468 
Insert(int index,T c)469   int Insert(int index, T c)
470   {
471     InsertSpace(index, 1);
472     _chars[index] = c;
473     _length++;
474     return _length;
475   }
Insert(int index,const CStringBase & s)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'
Replace(T oldChar,T newChar)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   }
Replace(const CStringBase & oldString,const CStringBase & newString)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   }
DeleteBack()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