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 "MyWindows.h"
14 #include "MyTypes.h"
15 #include "MyVector.h"
16 
17 
18 #ifdef _MSC_VER
19   #ifdef _NATIVE_WCHAR_T_DEFINED
20     #define MY_NATIVE_WCHAR_T_DEFINED
21   #endif
22 #else
23     #define MY_NATIVE_WCHAR_T_DEFINED
24 #endif
25 
26 /*
27   native support for wchar_t:
28  _MSC_VER == 1600 : /Zc:wchar_t is not supported
29  _MSC_VER == 1310 (VS2003)
30  ? _MSC_VER == 1400 (VS2005) : wchar_t <- unsigned short
31               /Zc:wchar_t  : wchar_t <- __wchar_t, _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED
32  _MSC_VER > 1400 (VS2008+)
33               /Zc:wchar_t[-]
34               /Zc:wchar_t is on by default
35 */
36 
37 #ifdef _WIN32
38 #define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/')
39 #else
40 #define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR)
41 #endif
42 
IsPathSepar(char c)43 inline bool IsPathSepar(char    c) { return IS_PATH_SEPAR(c); }
IsPathSepar(wchar_t c)44 inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); }
45 
MyStringLen(const char * s)46 inline unsigned MyStringLen(const char *s)
47 {
48   unsigned i;
49   for (i = 0; s[i] != 0; i++);
50   return i;
51 }
52 
MyStringCopy(char * dest,const char * src)53 inline void MyStringCopy(char *dest, const char *src)
54 {
55   while ((*dest++ = *src++) != 0);
56 }
57 
MyStpCpy(char * dest,const char * src)58 inline char *MyStpCpy(char *dest, const char *src)
59 {
60   for (;;)
61   {
62     char c = *src;
63     *dest = c;
64     if (c == 0)
65       return dest;
66     src++;
67     dest++;
68   }
69 }
70 
MyStringLen(const wchar_t * s)71 inline unsigned MyStringLen(const wchar_t *s)
72 {
73   unsigned i;
74   for (i = 0; s[i] != 0; i++);
75   return i;
76 }
77 
MyStringCopy(wchar_t * dest,const wchar_t * src)78 inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
79 {
80   while ((*dest++ = *src++) != 0);
81 }
82 
MyStringCat(wchar_t * dest,const wchar_t * src)83 inline void MyStringCat(wchar_t *dest, const wchar_t *src)
84 {
85   MyStringCopy(dest + MyStringLen(dest), src);
86 }
87 
88 
89 /*
90 inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src)
91 {
92   for (;;)
93   {
94     wchar_t c = *src;
95     *dest = c;
96     if (c == 0)
97       return dest;
98     src++;
99     dest++;
100   }
101 }
102 */
103 
104 int FindCharPosInString(const char *s, char c) throw();
105 int FindCharPosInString(const wchar_t *s, wchar_t c) throw();
106 
107 #ifdef _WIN32
108   #ifndef _UNICODE
109     #define STRING_UNICODE_THROW
110   #endif
111 #endif
112 
113 #ifndef STRING_UNICODE_THROW
114   #define STRING_UNICODE_THROW throw()
115 #endif
116 
117 
MyCharUpper_Ascii(char c)118 inline char MyCharUpper_Ascii(char c)
119 {
120   if (c >= 'a' && c <= 'z')
121     return (char)((unsigned char)c - 0x20);
122   return c;
123 }
124 
125 /*
126 inline wchar_t MyCharUpper_Ascii(wchar_t c)
127 {
128   if (c >= 'a' && c <= 'z')
129     return (wchar_t)(c - 0x20);
130   return c;
131 }
132 */
133 
MyCharLower_Ascii(char c)134 inline char MyCharLower_Ascii(char c)
135 {
136   if (c >= 'A' && c <= 'Z')
137     return (char)((unsigned char)c + 0x20);
138   return c;
139 }
140 
MyCharLower_Ascii(wchar_t c)141 inline wchar_t MyCharLower_Ascii(wchar_t c)
142 {
143   if (c >= 'A' && c <= 'Z')
144     return (wchar_t)(c + 0x20);
145   return c;
146 }
147 
148 wchar_t MyCharUpper_WIN(wchar_t c) throw();
149 
MyCharUpper(wchar_t c)150 inline wchar_t MyCharUpper(wchar_t c) throw()
151 {
152   if (c < 'a') return c;
153   if (c <= 'z') return (wchar_t)(c - 0x20);
154   if (c <= 0x7F) return c;
155   #ifdef _WIN32
156     #ifdef _UNICODE
157       return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
158     #else
159       return (wchar_t)MyCharUpper_WIN(c);
160     #endif
161   #else
162     return (wchar_t)towupper(c);
163   #endif
164 }
165 
166 /*
167 wchar_t MyCharLower_WIN(wchar_t c) throw();
168 
169 inline wchar_t MyCharLower(wchar_t c) throw()
170 {
171   if (c < 'A') return c;
172   if (c <= 'Z') return (wchar_t)(c + 0x20);
173   if (c <= 0x7F) return c;
174   #ifdef _WIN32
175     #ifdef _UNICODE
176       return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
177     #else
178       return (wchar_t)MyCharLower_WIN(c);
179     #endif
180   #else
181     return (wchar_t)tolower(c);
182   #endif
183 }
184 */
185 
186 // char *MyStringUpper(char *s) throw();
187 // char *MyStringLower(char *s) throw();
188 
189 // void MyStringUpper_Ascii(char *s) throw();
190 // void MyStringUpper_Ascii(wchar_t *s) throw();
191 void MyStringLower_Ascii(char *s) throw();
192 void MyStringLower_Ascii(wchar_t *s) throw();
193 // wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW;
194 // wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW;
195 
196 bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
197 
198 bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
199 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
200 bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw();
201 bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw();
202 bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();
203 
204 #define MyStringCompare(s1, s2) wcscmp(s1, s2)
205 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();
206 // int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();
207 
208 // ---------- ASCII ----------
209 // char values in ASCII strings must be less then 128
210 bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();
211 bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();
212 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();
213 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw();
214 
215 #define MY_STRING_DELETE(_p_) delete []_p_;
216 // #define MY_STRING_DELETE(_p_) my_delete(_p_);
217 
218 
219 #define FORBID_STRING_OPS_2(cls, t) \
220   void Find(t) const; \
221   void Find(t, unsigned startIndex) const; \
222   void ReverseFind(t) const; \
223   void InsertAtFront(t); \
224   void RemoveChar(t); \
225   void Replace(t, t); \
226 
227 #define FORBID_STRING_OPS(cls, t) \
228   explicit cls(t); \
229   explicit cls(const t *); \
230   cls &operator=(t); \
231   cls &operator=(const t *); \
232   cls &operator+=(t); \
233   cls &operator+=(const t *); \
234   FORBID_STRING_OPS_2(cls, t); \
235 
236 /*
237   cls &operator+(t); \
238   cls &operator+(const t *); \
239 */
240 
241 #define FORBID_STRING_OPS_AString(t) FORBID_STRING_OPS(AString, t)
242 #define FORBID_STRING_OPS_UString(t) FORBID_STRING_OPS(UString, t)
243 #define FORBID_STRING_OPS_UString2(t) FORBID_STRING_OPS(UString2, t)
244 
245 class AString
246 {
247   char *_chars;
248   unsigned _len;
249   unsigned _limit;
250 
MoveItems(unsigned dest,unsigned src)251   void MoveItems(unsigned dest, unsigned src)
252   {
253     memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char));
254   }
255 
256   void InsertSpace(unsigned &index, unsigned size);
257 
258   void ReAlloc(unsigned newLimit);
259   void ReAlloc2(unsigned newLimit);
260   void SetStartLen(unsigned len);
261   void Grow_1();
262   void Grow(unsigned n);
263 
264   AString(unsigned num, const char *s);
265   AString(unsigned num, const AString &s);
266   AString(const AString &s, char c); // it's for String + char
267   AString(const char *s1, unsigned num1, const char *s2, unsigned num2);
268 
269   friend AString operator+(const AString &s, char c) { return AString(s, c); } ;
270   // friend AString operator+(char c, const AString &s); // is not supported
271 
272   friend AString operator+(const AString &s1, const AString &s2);
273   friend AString operator+(const AString &s1, const char    *s2);
274   friend AString operator+(const char    *s1, const AString &s2);
275 
276   // ---------- forbidden functions ----------
277 
278   #ifdef MY_NATIVE_WCHAR_T_DEFINED
279   FORBID_STRING_OPS_AString(wchar_t)
280   #endif
281 
282   FORBID_STRING_OPS_AString(signed char)
283   FORBID_STRING_OPS_AString(unsigned char)
284   FORBID_STRING_OPS_AString(short)
285   FORBID_STRING_OPS_AString(unsigned short)
286   FORBID_STRING_OPS_AString(int)
287   FORBID_STRING_OPS_AString(unsigned)
288   FORBID_STRING_OPS_AString(long)
289   FORBID_STRING_OPS_AString(unsigned long)
290 
291 public:
292   explicit AString();
293   explicit AString(char c);
294   explicit AString(const char *s);
295   AString(const AString &s);
~AString()296   ~AString() { MY_STRING_DELETE(_chars); }
297 
Len()298   unsigned Len() const { return _len; }
IsEmpty()299   bool IsEmpty() const { return _len == 0; }
Empty()300   void Empty() { _len = 0; _chars[0] = 0; }
301 
302   operator const char *() const { return _chars; }
Ptr()303   const char *Ptr() const { return _chars; }
Ptr(unsigned pos)304   const char *Ptr(unsigned pos) const { return _chars + pos; }
RightPtr(unsigned num)305   const char *RightPtr(unsigned num) const { return _chars + _len - num; }
Back()306   char Back() const { return _chars[(size_t)_len - 1]; }
307 
ReplaceOneCharAtPos(unsigned pos,char c)308   void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
309 
GetBuf()310   char *GetBuf() { return _chars; }
311   /* GetBuf(minLen): provides the buffer that can store
312      at least (minLen) characters and additional null terminator.
313      9.35: GetBuf doesn't preserve old characters and terminator */
GetBuf(unsigned minLen)314   char *GetBuf(unsigned minLen)
315   {
316     if (minLen > _limit)
317       ReAlloc2(minLen);
318     return _chars;
319   }
GetBuf_SetEnd(unsigned minLen)320   char *GetBuf_SetEnd(unsigned minLen)
321   {
322     if (minLen > _limit)
323       ReAlloc2(minLen);
324     char *chars = _chars;
325     chars[minLen] = 0;
326     _len = minLen;
327     return chars;
328   }
329 
ReleaseBuf_SetLen(unsigned newLen)330   void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
ReleaseBuf_SetEnd(unsigned newLen)331   void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
ReleaseBuf_CalcLen(unsigned maxLen)332   void ReleaseBuf_CalcLen(unsigned maxLen)
333   {
334     char *chars = _chars;
335     chars[maxLen] = 0;
336     _len = MyStringLen(chars);
337   }
338 
339   AString &operator=(char c);
340   AString &operator=(const char *s);
341   AString &operator=(const AString &s);
342   void SetFromWStr_if_Ascii(const wchar_t *s);
343   // void SetFromBstr_if_Ascii(BSTR s);
344 
345   AString &operator+=(char c)
346   {
347     if (_limit == _len)
348       Grow_1();
349     unsigned len = _len;
350     char *chars = _chars;
351     chars[len++] = c;
352     chars[len] = 0;
353     _len = len;
354     return *this;
355   }
356 
357   void Add_Space();
358   void Add_Space_if_NotEmpty();
359   void Add_OptSpaced(const char *s);
360   void Add_LF();
Add_PathSepar()361   void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }
362 
363   AString &operator+=(const char *s);
364   AString &operator+=(const AString &s);
365 
366   void Add_UInt32(UInt32 v);
367 
368   void SetFrom(const char *s, unsigned len); // no check
369   void SetFrom_CalcLen(const char *s, unsigned len);
370 
Mid(unsigned startIndex,unsigned count)371   AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
Left(unsigned count)372   AString Left(unsigned count) const { return AString(count, *this); }
373 
374   // void MakeUpper() { MyStringUpper(_chars); }
375   // void MakeLower() { MyStringLower(_chars); }
MakeLower_Ascii()376   void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
377 
378 
IsEqualTo(const char * s)379   bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; }
IsEqualTo_Ascii_NoCase(const char * s)380   bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
381   // int Compare(const char *s) const { return MyStringCompare(_chars, s); }
382   // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }
383   // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }
384   // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
IsPrefixedBy(const char * s)385   bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
386   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
387 
IsAscii()388   bool IsAscii() const
389   {
390     unsigned len = Len();
391     const char *s = _chars;
392     for (unsigned i = 0; i < len; i++)
393       if ((unsigned char)s[i] >= 0x80)
394         return false;
395     return true;
396   }
Find(char c)397   int Find(char c) const { return FindCharPosInString(_chars, c); }
Find(char c,unsigned startIndex)398   int Find(char c, unsigned startIndex) const
399   {
400     int pos = FindCharPosInString(_chars + startIndex, c);
401     return pos < 0 ? -1 : (int)startIndex + pos;
402   }
403 
404   int ReverseFind(char c) const throw();
ReverseFind_Dot()405   int ReverseFind_Dot() const throw() { return ReverseFind('.'); }
406   int ReverseFind_PathSepar() const throw();
407 
Find(const char * s)408   int Find(const char *s) const { return Find(s, 0); }
409   int Find(const char *s, unsigned startIndex) const throw();
410 
411   void TrimLeft() throw();
412   void TrimRight() throw();
Trim()413   void Trim()
414   {
415     TrimRight();
416     TrimLeft();
417   }
418 
419   void InsertAtFront(char c);
420   // void Insert(unsigned index, char c);
421   void Insert(unsigned index, const char *s);
422   void Insert(unsigned index, const AString &s);
423 
424   void RemoveChar(char ch) throw();
425 
426   void Replace(char oldChar, char newChar) throw();
427   void Replace(const AString &oldString, const AString &newString);
428 
429   void Delete(unsigned index) throw();
430   void Delete(unsigned index, unsigned count) throw();
431   void DeleteFrontal(unsigned num) throw();
DeleteBack()432   void DeleteBack() { _chars[--_len] = 0; }
DeleteFrom(unsigned index)433   void DeleteFrom(unsigned index)
434   {
435     if (index < _len)
436     {
437       _len = index;
438       _chars[index] = 0;
439     }
440   }
441 };
442 
443 bool operator<(const AString &s1, const AString &s2);
444 bool operator>(const AString &s1, const AString &s2);
445 
446 /*
447 bool operator==(const AString &s1, const AString &s2);
448 bool operator==(const AString &s1, const char    *s2);
449 bool operator==(const char    *s1, const AString &s2);
450 
451 bool operator!=(const AString &s1, const AString &s2);
452 bool operator!=(const AString &s1, const char    *s2);
453 bool operator!=(const char    *s1, const AString &s2);
454 */
455 
456 inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }
457 inline bool operator==(const AString &s1, const char    *s2) { return strcmp(s1, s2) == 0; }
458 inline bool operator==(const char    *s1, const AString &s2) { return strcmp(s1, s2) == 0; }
459 
460 inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }
461 inline bool operator!=(const AString &s1, const char    *s2) { return strcmp(s1, s2) != 0; }
462 inline bool operator!=(const char    *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
463 
464 // ---------- forbidden functions ----------
465 
466 void operator==(char c1, const AString &s2);
467 void operator==(const AString &s1, char c2);
468 
469 void operator+(char c, const AString &s); // this function can be OK, but we don't use it
470 
471 void operator+(const AString &s, int c);
472 void operator+(const AString &s, unsigned c);
473 void operator+(int c, const AString &s);
474 void operator+(unsigned c, const AString &s);
475 void operator-(const AString &s, int c);
476 void operator-(const AString &s, unsigned c);
477 
478 
479 class UString
480 {
481   wchar_t *_chars;
482   unsigned _len;
483   unsigned _limit;
484 
MoveItems(unsigned dest,unsigned src)485   void MoveItems(unsigned dest, unsigned src)
486   {
487     memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t));
488   }
489 
490   void InsertSpace(unsigned index, unsigned size);
491 
492   void ReAlloc(unsigned newLimit);
493   void ReAlloc2(unsigned newLimit);
494   void SetStartLen(unsigned len);
495   void Grow_1();
496   void Grow(unsigned n);
497 
498   UString(unsigned num, const wchar_t *s); // for Mid
499   UString(unsigned num, const UString &s); // for Left
500   UString(const UString &s, wchar_t c); // it's for String + char
501   UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2);
502 
503   friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ;
504   // friend UString operator+(wchar_t c, const UString &s); // is not supported
505 
506   friend UString operator+(const UString &s1, const UString &s2);
507   friend UString operator+(const UString &s1, const wchar_t *s2);
508   friend UString operator+(const wchar_t *s1, const UString &s2);
509 
510   // ---------- forbidden functions ----------
511 
512   FORBID_STRING_OPS_UString(signed char)
513   FORBID_STRING_OPS_UString(unsigned char)
514   FORBID_STRING_OPS_UString(short)
515 
516   #ifdef MY_NATIVE_WCHAR_T_DEFINED
517   FORBID_STRING_OPS_UString(unsigned short)
518   #endif
519 
520   FORBID_STRING_OPS_UString(int)
521   FORBID_STRING_OPS_UString(unsigned)
522   FORBID_STRING_OPS_UString(long)
523   FORBID_STRING_OPS_UString(unsigned long)
524 
525   FORBID_STRING_OPS_2(UString, char)
526 
527 public:
528   UString();
529   explicit UString(wchar_t c);
530   explicit UString(char c);
531   explicit UString(const char *s);
532   // UString(const AString &s);
533   UString(const wchar_t *s);
534   UString(const UString &s);
~UString()535   ~UString() { MY_STRING_DELETE(_chars); }
536 
Len()537   unsigned Len() const { return _len; }
IsEmpty()538   bool IsEmpty() const { return _len == 0; }
Empty()539   void Empty() { _len = 0; _chars[0] = 0; }
540 
541   operator const wchar_t *() const { return _chars; }
Ptr()542   const wchar_t *Ptr() const { return _chars; }
Ptr(unsigned pos)543   const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
RightPtr(unsigned num)544   const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
Back()545   wchar_t Back() const { return _chars[(size_t)_len - 1]; }
546 
ReplaceOneCharAtPos(unsigned pos,wchar_t c)547   void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
548 
GetBuf()549   wchar_t *GetBuf() { return _chars; }
550 
GetBuf(unsigned minLen)551   wchar_t *GetBuf(unsigned minLen)
552   {
553     if (minLen > _limit)
554       ReAlloc2(minLen);
555     return _chars;
556   }
GetBuf_SetEnd(unsigned minLen)557   wchar_t *GetBuf_SetEnd(unsigned minLen)
558   {
559     if (minLen > _limit)
560       ReAlloc2(minLen);
561     wchar_t *chars = _chars;
562     chars[minLen] = 0;
563     _len = minLen;
564     return chars;
565   }
566 
ReleaseBuf_SetLen(unsigned newLen)567   void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
ReleaseBuf_SetEnd(unsigned newLen)568   void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
ReleaseBuf_CalcLen(unsigned maxLen)569   void ReleaseBuf_CalcLen(unsigned maxLen)
570   {
571     wchar_t *chars = _chars;
572     chars[maxLen] = 0;
573     _len = MyStringLen(chars);
574   }
575 
576   UString &operator=(wchar_t c);
577   UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); }
578   UString &operator=(const wchar_t *s);
579   UString &operator=(const UString &s);
580   void SetFrom(const wchar_t *s, unsigned len); // no check
581   void SetFromBstr(BSTR s);
582   UString &operator=(const char *s);
583   UString &operator=(const AString &s) { return operator=(s.Ptr()); }
584 
585   UString &operator+=(wchar_t c)
586   {
587     if (_limit == _len)
588       Grow_1();
589     unsigned len = _len;
590     wchar_t *chars = _chars;
591     chars[len++] = c;
592     chars[len] = 0;
593     _len = len;
594     return *this;
595   }
596 
597   UString &operator+=(char c) { return (*this)+=((wchar_t)(unsigned char)c); }
598 
599   void Add_Space();
600   void Add_Space_if_NotEmpty();
601   void Add_LF();
Add_PathSepar()602   void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); }
603 
604   UString &operator+=(const wchar_t *s);
605   UString &operator+=(const UString &s);
606   UString &operator+=(const char *s);
607   UString &operator+=(const AString &s) { return operator+=(s.Ptr()); }
608 
609   void Add_UInt32(UInt32 v);
610 
Mid(unsigned startIndex,unsigned count)611   UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
Left(unsigned count)612   UString Left(unsigned count) const { return UString(count, *this); }
613 
614   // void MakeUpper() { MyStringUpper(_chars); }
615   // void MakeUpper() { MyStringUpper_Ascii(_chars); }
616   // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); }
MakeLower_Ascii()617   void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
618 
IsEqualTo(const char * s)619   bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
IsEqualTo_NoCase(const wchar_t * s)620   bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
IsEqualTo_Ascii_NoCase(const char * s)621   bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
Compare(const wchar_t * s)622   int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
623   // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }
624   // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }
625   // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
IsPrefixedBy(const wchar_t * s)626   bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }
IsPrefixedBy_NoCase(const wchar_t * s)627   bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); }
628   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
629 
IsAscii()630   bool IsAscii() const
631   {
632     unsigned len = Len();
633     const wchar_t *s = _chars;
634     for (unsigned i = 0; i < len; i++)
635       if (s[i] >= 0x80)
636         return false;
637     return true;
638   }
Find(wchar_t c)639   int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
Find(wchar_t c,unsigned startIndex)640   int Find(wchar_t c, unsigned startIndex) const
641   {
642     int pos = FindCharPosInString(_chars + startIndex, c);
643     return pos < 0 ? -1 : (int)startIndex + pos;
644   }
645 
646   int ReverseFind(wchar_t c) const throw();
ReverseFind_Dot()647   int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); }
648   int ReverseFind_PathSepar() const throw();
649 
Find(const wchar_t * s)650   int Find(const wchar_t *s) const { return Find(s, 0); }
651   int Find(const wchar_t *s, unsigned startIndex) const throw();
652 
653   void TrimLeft() throw();
654   void TrimRight() throw();
Trim()655   void Trim()
656   {
657     TrimRight();
658     TrimLeft();
659   }
660 
661   void InsertAtFront(wchar_t c);
662   // void Insert(unsigned index, wchar_t c);
663   void Insert(unsigned index, const wchar_t *s);
664   void Insert(unsigned index, const UString &s);
665 
666   void RemoveChar(wchar_t ch) throw();
667 
668   void Replace(wchar_t oldChar, wchar_t newChar) throw();
669   void Replace(const UString &oldString, const UString &newString);
670 
671   void Delete(unsigned index) throw();
672   void Delete(unsigned index, unsigned count) throw();
673   void DeleteFrontal(unsigned num) throw();
DeleteBack()674   void DeleteBack() { _chars[--_len] = 0; }
DeleteFrom(unsigned index)675   void DeleteFrom(unsigned index)
676   {
677     if (index < _len)
678     {
679       _len = index;
680       _chars[index] = 0;
681     }
682   }
683 };
684 
685 bool operator<(const UString &s1, const UString &s2);
686 bool operator>(const UString &s1, const UString &s2);
687 
688 inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }
689 inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }
690 inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }
691 
692 inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }
693 inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }
694 inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
695 
696 
697 // ---------- forbidden functions ----------
698 
699 void operator==(wchar_t c1, const UString &s2);
700 void operator==(const UString &s1, wchar_t c2);
701 
702 void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it
703 
704 void operator+(const AString &s1, const UString &s2);
705 void operator+(const UString &s1, const AString &s2);
706 
707 void operator+(const UString &s1, const char *s2);
708 void operator+(const char *s1, const UString &s2);
709 
710 void operator+(const UString &s, char c);
711 void operator+(const UString &s, unsigned char c);
712 void operator+(char c, const UString &s);
713 void operator+(unsigned char c, const UString &s);
714 void operator-(const UString &s1, wchar_t c);
715 
716 #ifdef _WIN32
717 // can we forbid these functions, if wchar_t is 32-bit ?
718 void operator+(const UString &s, int c);
719 void operator+(const UString &s, unsigned c);
720 void operator+(int c, const UString &s);
721 void operator+(unsigned c, const UString &s);
722 void operator-(const UString &s1, int c);
723 void operator-(const UString &s1, unsigned c);
724 #endif
725 
726 
727 
728 
729 
730 
731 
732 class UString2
733 {
734   wchar_t *_chars;
735   unsigned _len;
736 
737   void ReAlloc2(unsigned newLimit);
738   void SetStartLen(unsigned len);
739 
740   // ---------- forbidden functions ----------
741 
742   FORBID_STRING_OPS_UString2(char)
743   FORBID_STRING_OPS_UString2(signed char)
744   FORBID_STRING_OPS_UString2(unsigned char)
745   FORBID_STRING_OPS_UString2(short)
746 
747   UString2 &operator=(wchar_t c);
748   UString2(wchar_t c);
749 
750 public:
UString2()751   UString2(): _chars(NULL), _len(0) {}
752   UString2(const wchar_t *s);
753   UString2(const UString2 &s);
~UString2()754   ~UString2() { if (_chars) MY_STRING_DELETE(_chars); }
755 
Len()756   unsigned Len() const { return _len; }
IsEmpty()757   bool IsEmpty() const { return _len == 0; }
758   // void Empty() { _len = 0; _chars[0] = 0; }
759 
760   // operator const wchar_t *() const { return _chars; }
GetRawPtr()761   const wchar_t *GetRawPtr() const { return _chars; }
762 
Compare(const wchar_t * s)763   int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
764 
GetBuf(unsigned minLen)765   wchar_t *GetBuf(unsigned minLen)
766   {
767     if (!_chars || minLen > _len)
768       ReAlloc2(minLen);
769     return _chars;
770   }
ReleaseBuf_SetLen(unsigned newLen)771   void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
772 
773   UString2 &operator=(const wchar_t *s);
774   UString2 &operator=(const UString2 &s);
775   void SetFromAscii(const char *s);
776 };
777 
778 bool operator==(const UString2 &s1, const UString2 &s2);
779 bool operator==(const UString2 &s1, const wchar_t *s2);
780 bool operator==(const wchar_t *s1, const UString2 &s2);
781 
782 inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); }
783 inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); }
784 inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); }
785 
786 
787 // ---------- forbidden functions ----------
788 
789 void operator==(wchar_t c1, const UString2 &s2);
790 void operator==(const UString2 &s1, wchar_t c2);
791 bool operator<(const UString2 &s1, const UString2 &s2);
792 bool operator>(const UString2 &s1, const UString2 &s2);
793 
794 void operator+(const UString2 &s1, const UString2 &s2);
795 void operator+(const UString2 &s1, const wchar_t *s2);
796 void operator+(const wchar_t *s1, const UString2 &s2);
797 void operator+(wchar_t c, const UString2 &s);
798 void operator+(const UString2 &s, wchar_t c);
799 void operator+(const UString2 &s, char c);
800 void operator+(const UString2 &s, unsigned char c);
801 void operator+(char c, const UString2 &s);
802 void operator+(unsigned char c, const UString2 &s);
803 void operator-(const UString2 &s1, wchar_t c);
804 
805 
806 
807 
808 
809 
810 typedef CObjectVector<AString> AStringVector;
811 typedef CObjectVector<UString> UStringVector;
812 
813 #ifdef _UNICODE
814   typedef UString CSysString;
815 #else
816   typedef AString CSysString;
817 #endif
818 
819 typedef CObjectVector<CSysString> CSysStringVector;
820 
821 
822 // ---------- FString ----------
823 
824 #ifdef _WIN32
825   #define USE_UNICODE_FSTRING
826 #endif
827 
828 #ifdef USE_UNICODE_FSTRING
829 
830   #define __FTEXT(quote) L##quote
831 
832   typedef wchar_t FChar;
833   typedef UString FString;
834 
835   #define fs2us(_x_) (_x_)
836   #define us2fs(_x_) (_x_)
837   FString fas2fs(const char *s);
838   FString fas2fs(const AString &s);
839   AString fs2fas(const FChar *s);
840 
841 #else
842 
843   #define __FTEXT(quote) quote
844 
845   typedef char FChar;
846   typedef AString FString;
847 
848   UString fs2us(const FChar *s);
849   UString fs2us(const FString &s);
850   FString us2fs(const wchar_t *s);
851   #define fas2fs(_x_) (_x_)
852   #define fs2fas(_x_) (_x_)
853 
854 #endif
855 
856 #define FTEXT(quote) __FTEXT(quote)
857 
858 #define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)
859 #define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)
860 
861 // #define FCHAR_ANY_MASK FTEXT('*')
862 // #define FSTRING_ANY_MASK FTEXT("*")
863 
864 typedef const FChar *CFSTR;
865 
866 typedef CObjectVector<FString> FStringVector;
867 
868 #endif
869