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