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