xref: /third_party/lzma/CPP/Common/MyString.h (revision 370b324c)
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
26class 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
55inline bool IsPathSepar(char    c) { return IS_PATH_SEPAR(c); }
56inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); }
57
58inline unsigned MyStringLen(const char *s)
59{
60  unsigned i;
61  for (i = 0; s[i] != 0; i++);
62  return i;
63}
64
65inline void MyStringCopy(char *dest, const char *src)
66{
67  while ((*dest++ = *src++) != 0);
68}
69
70inline 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
83inline 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
90inline unsigned MyStringLen(const wchar_t *s)
91{
92  unsigned i;
93  for (i = 0; s[i] != 0; i++);
94  return i;
95}
96
97inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
98{
99  while ((*dest++ = *src++) != 0);
100}
101
102inline 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/*
111inline 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
125int FindCharPosInString(const char *s, char c) throw();
126int 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
139inline 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/*
147inline 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
155inline char MyCharLower_Ascii(char c)
156{
157  if (c >= 'A' && c <= 'Z')
158    return (char)((unsigned char)c + 0x20);
159  return c;
160}
161
162inline 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
169wchar_t MyCharUpper_WIN(wchar_t c) throw();
170
171inline 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/*
188wchar_t MyCharLower_WIN(wchar_t c) throw();
189
190inline 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();
212void MyStringLower_Ascii(char *s) throw();
213void 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
217bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
218
219bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
220bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
221bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw();
222bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw();
223bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw();
224bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();
225
226#define MyStringCompare(s1, s2) wcscmp(s1, s2)
227int 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
232bool StringsAreEqual_Ascii(const char *u, const char *a) throw();
233bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();
234bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();
235bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();
236bool 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
268class AString
269{
270  char *_chars;
271  unsigned _len;
272  unsigned _limit;
273
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
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
320public:
321  explicit AString();
322  explicit AString(char c);
323  explicit AString(const char *s);
324  AString(const AString &s);
325  ~AString() { MY_STRING_DELETE(_chars) }
326
327  unsigned Len() const { return _len; }
328  bool IsEmpty() const { return _len == 0; }
329  void Empty() { _len = 0; _chars[0] = 0; }
330
331  operator const char *() const { return _chars; }
332  char *Ptr_non_const() const { return _chars; }
333  const char *Ptr() const { return _chars; }
334  const char *Ptr(unsigned pos) const { return _chars + pos; }
335  const char *Ptr(int pos) const { return _chars + (unsigned)pos; }
336  const char *RightPtr(unsigned num) const { return _chars + _len - num; }
337  char Back() const { return _chars[(size_t)_len - 1]; }
338
339  void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
340
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 */
345  char *GetBuf(unsigned minLen)
346  {
347    if (minLen > _limit)
348      ReAlloc2(minLen);
349    return _chars;
350  }
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
361  void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
362  void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
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
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();
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
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
411  AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
412  AString Left(unsigned count) const { return AString(count, *this); }
413  // void MakeUpper() { MyStringUpper(_chars); }
414  // void MakeLower() { MyStringLower(_chars); }
415  void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
416
417
418  bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; }
419  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); }
424  bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
425  bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
426
427  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  }
436  int Find(char c) const { return FindCharPosInString(_chars, c); }
437  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  }
442  int Find(char c, int startIndex) const
443  {
444    return Find(c, (unsigned)startIndex);
445  }
446
447  int ReverseFind(char c) const throw();
448  int ReverseFind_Dot() const throw() { return ReverseFind('.'); }
449  int ReverseFind_PathSepar() const throw();
450
451  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();
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();
475  void DeleteBack() { _chars[--_len] = 0; }
476  void DeleteFrom(unsigned index)
477  {
478    if (index < _len)
479    {
480      _len = index;
481      _chars[index] = 0;
482    }
483  }
484  void DeleteFrom(int index)
485  {
486    DeleteFrom((unsigned)index);
487  }
488
489
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
501class AString_Wipe: public AString
502{
503  Z7_CLASS_NO_COPY(AString_Wipe)
504public:
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; }
509  ~AString_Wipe() { Wipe_and_Empty(); }
510};
511
512
513bool operator<(const AString &s1, const AString &s2);
514bool operator>(const AString &s1, const AString &s2);
515
516/*
517bool operator==(const AString &s1, const AString &s2);
518bool operator==(const AString &s1, const char    *s2);
519bool operator==(const char    *s1, const AString &s2);
520
521bool operator!=(const AString &s1, const AString &s2);
522bool operator!=(const AString &s1, const char    *s2);
523bool operator!=(const char    *s1, const AString &s2);
524*/
525
526inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }
527inline bool operator==(const AString &s1, const char    *s2) { return strcmp(s1, s2) == 0; }
528inline bool operator==(const char    *s1, const AString &s2) { return strcmp(s1, s2) == 0; }
529
530inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }
531inline bool operator!=(const AString &s1, const char    *s2) { return strcmp(s1, s2) != 0; }
532inline bool operator!=(const char    *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
533
534// ---------- forbidden functions ----------
535
536void operator==(char c1, const AString &s2);
537void operator==(const AString &s1, char c2);
538
539void operator+(char c, const AString &s); // this function can be OK, but we don't use it
540
541void operator+(const AString &s, int c);
542void operator+(const AString &s, unsigned c);
543void operator+(int c, const AString &s);
544void operator+(unsigned c, const AString &s);
545void operator-(const AString &s, int c);
546void operator-(const AString &s, unsigned c);
547
548
549class UString
550{
551  wchar_t *_chars;
552  unsigned _len;
553  unsigned _limit;
554
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
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
603public:
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);
611  ~UString() { MY_STRING_DELETE(_chars) }
612
613  unsigned Len() const { return _len; }
614  bool IsEmpty() const { return _len == 0; }
615  void Empty() { _len = 0; _chars[0] = 0; }
616
617  operator const wchar_t *() const { return _chars; }
618  wchar_t *Ptr_non_const() const { return _chars; }
619  const wchar_t *Ptr() const { return _chars; }
620  const wchar_t *Ptr(int pos) const { return _chars + (unsigned)pos; }
621  const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
622  const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
623  wchar_t Back() const { return _chars[(size_t)_len - 1]; }
624
625  void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
626
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
637  wchar_t *GetBuf(unsigned minLen)
638  {
639    if (minLen > _limit)
640      ReAlloc2(minLen);
641    return _chars;
642  }
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
653  void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
654  void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
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);
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);
669  UString &operator=(const AString &s) { return operator=(s.Ptr()); }
670
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
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();
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);
694  UString &operator+=(const AString &s) { return operator+=(s.Ptr()); }
695
696  void Add_UInt32(UInt32 v);
697  void Add_UInt64(UInt64 v);
698
699  UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
700  UString Left(unsigned count) const { return UString(count, *this); }
701  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); }
706  void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
707
708  bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
709  bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
710  bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
711  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); }
715  bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }
716  bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); }
717  bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
718
719  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  }
728  int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
729  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();
736  int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); }
737  int ReverseFind_PathSepar() const throw();
738
739  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();
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
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();
764  void DeleteBack() { _chars[--_len] = 0; }
765  void DeleteFrom(int 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
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
786class UString_Wipe: public UString
787{
788  Z7_CLASS_NO_COPY(UString_Wipe)
789public:
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; }
794  ~UString_Wipe() { Wipe_and_Empty(); }
795};
796
797
798bool operator<(const UString &s1, const UString &s2);
799bool operator>(const UString &s1, const UString &s2);
800
801inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }
802inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }
803inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }
804
805inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }
806inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }
807inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
808
809
810// ---------- forbidden functions ----------
811
812void operator==(wchar_t c1, const UString &s2);
813void operator==(const UString &s1, wchar_t c2);
814
815void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it
816
817void operator+(const AString &s1, const UString &s2);
818void operator+(const UString &s1, const AString &s2);
819
820void operator+(const UString &s1, const char *s2);
821void operator+(const char *s1, const UString &s2);
822
823void operator+(const UString &s, char c);
824void operator+(const UString &s, unsigned char c);
825void operator+(char c, const UString &s);
826void operator+(unsigned char c, const UString &s);
827void operator-(const UString &s1, wchar_t c);
828
829#ifdef _WIN32
830// can we forbid these functions, if wchar_t is 32-bit ?
831void operator+(const UString &s, int c);
832void operator+(const UString &s, unsigned c);
833void operator+(int c, const UString &s);
834void operator+(unsigned c, const UString &s);
835void operator-(const UString &s1, int c);
836void operator-(const UString &s1, unsigned c);
837#endif
838
839
840
841
842
843
844
845class 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
872public:
873  UString2(): _chars(NULL), _len(0) {}
874  UString2(const wchar_t *s);
875  UString2(const UString2 &s);
876  ~UString2() { if (_chars) { MY_STRING_DELETE(_chars) } }
877
878  unsigned Len() const { return _len; }
879  bool IsEmpty() const { return _len == 0; }
880  // void Empty() { _len = 0; _chars[0] = 0; }
881
882  // operator const wchar_t *() const { return _chars; }
883  const wchar_t *GetRawPtr() const { return _chars; }
884
885  int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
886
887  wchar_t *GetBuf(unsigned minLen)
888  {
889    if (!_chars || minLen > _len)
890      ReAlloc2(minLen);
891    return _chars;
892  }
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
900bool operator==(const UString2 &s1, const UString2 &s2);
901bool operator==(const UString2 &s1, const wchar_t *s2);
902bool operator==(const wchar_t *s1, const UString2 &s2);
903
904inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); }
905inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); }
906inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); }
907
908
909// ---------- forbidden functions ----------
910
911void operator==(wchar_t c1, const UString2 &s2);
912void operator==(const UString2 &s1, wchar_t c2);
913bool operator<(const UString2 &s1, const UString2 &s2);
914bool operator>(const UString2 &s1, const UString2 &s2);
915
916void operator+(const UString2 &s1, const UString2 &s2);
917void operator+(const UString2 &s1, const wchar_t *s2);
918void operator+(const wchar_t *s1, const UString2 &s2);
919void operator+(wchar_t c, const UString2 &s);
920void operator+(const UString2 &s, wchar_t c);
921void operator+(const UString2 &s, char c);
922void operator+(const UString2 &s, unsigned char c);
923void operator+(char c, const UString2 &s);
924void operator+(unsigned char c, const UString2 &s);
925void operator-(const UString2 &s1, wchar_t c);
926
927
928
929
930
931
932typedef CObjectVector<AString> AStringVector;
933typedef CObjectVector<UString> UStringVector;
934
935#ifdef _UNICODE
936  typedef UString CSysString;
937#else
938  typedef AString CSysString;
939#endif
940
941typedef 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:
979    FString(const AString &s): AString(s.Ptr()) {}
980    FString(const FString &s): AString(s.Ptr()) {}
981    FString(const char *s): AString(s) {}
982    FString() {}
983    FString &operator=(const FString &s)  { AString::operator=((const AString &)s); return *this; }
984    FString &operator=(char c) { AString::operator=(c); return *this; }
985    FString &operator+=(char c) { AString::operator+=(c); return *this; }
986    FString &operator+=(const FString &s) { AString::operator+=((const AString &)s); return *this; }
987    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
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  }
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
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
1031typedef const FChar *CFSTR;
1032
1033typedef CObjectVector<FString> FStringVector;
1034
1035
1036class CStringFinder
1037{
1038  AString _temp;
1039public:
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
1045void 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