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