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
285 Z7_NO_INLINE
286 void Grow_1();
287 void Grow(unsigned n);
288
289 AString(unsigned num, const char *s);
290 AString(unsigned num, const AString &s);
291 AString(const AString &s, char c); // it's for String + char
292 AString(const char *s1, unsigned num1, const char *s2, unsigned num2);
293
294 friend AString operator+(const AString &s, char c) { return AString(s, c); }
295 // friend AString operator+(char c, const AString &s); // is not supported
296
297 friend AString operator+(const AString &s1, const AString &s2);
298 friend AString operator+(const AString &s1, const char *s2);
299 friend AString operator+(const char *s1, const AString &s2);
300
301 // ---------- forbidden functions ----------
302
303 #ifdef MY_NATIVE_WCHAR_T_DEFINED
304 FORBID_STRING_OPS_AString(wchar_t)
305 #endif
306
307 FORBID_STRING_OPS_AString(signed char)
308 FORBID_STRING_OPS_AString(unsigned char)
309 FORBID_STRING_OPS_AString(short)
310 FORBID_STRING_OPS_AString(unsigned short)
311 FORBID_STRING_OPS_AString(int)
312 FORBID_STRING_OPS_AString(unsigned)
313 FORBID_STRING_OPS_AString(long)
314 FORBID_STRING_OPS_AString(unsigned long)
315
316 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
317 AString(const FString &s);
318 AString &operator=(const FString &s);
319 AString &operator+=(const FString &s);
320 #endif
321
322 public:
323 explicit AString();
324 explicit AString(char c);
325 explicit AString(const char *s);
326 AString(const AString &s);
~AString()327 ~AString() { MY_STRING_DELETE(_chars) }
328
Len()329 unsigned Len() const { return _len; }
IsEmpty()330 bool IsEmpty() const { return _len == 0; }
Empty()331 void Empty() { _len = 0; _chars[0] = 0; }
332
333 operator const char *() const { return _chars; }
Ptr_non_const()334 char *Ptr_non_const() const { return _chars; }
Ptr()335 const char *Ptr() const { return _chars; }
Ptr(unsigned pos)336 const char *Ptr(unsigned pos) const { return _chars + pos; }
Ptr(int pos)337 const char *Ptr(int pos) const { return _chars + (unsigned)pos; }
RightPtr(unsigned num)338 const char *RightPtr(unsigned num) const { return _chars + _len - num; }
Back()339 char Back() const { return _chars[(size_t)_len - 1]; }
340
ReplaceOneCharAtPos(unsigned pos,char c)341 void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
342
GetBuf()343 char *GetBuf() { return _chars; }
344 /* GetBuf(minLen): provides the buffer that can store
345 at least (minLen) characters and additional null terminator.
346 9.35: GetBuf doesn't preserve old characters and terminator */
GetBuf(unsigned minLen)347 char *GetBuf(unsigned minLen)
348 {
349 if (minLen > _limit)
350 ReAlloc2(minLen);
351 return _chars;
352 }
GetBuf_SetEnd(unsigned minLen)353 char *GetBuf_SetEnd(unsigned minLen)
354 {
355 if (minLen > _limit)
356 ReAlloc2(minLen);
357 char *chars = _chars;
358 chars[minLen] = 0;
359 _len = minLen;
360 return chars;
361 }
362
ReleaseBuf_SetLen(unsigned newLen)363 void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
ReleaseBuf_SetEnd(unsigned newLen)364 void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
ReleaseBuf_CalcLen(unsigned maxLen)365 void ReleaseBuf_CalcLen(unsigned maxLen)
366 {
367 char *chars = _chars;
368 chars[maxLen] = 0;
369 _len = MyStringLen(chars);
370 }
371
372 AString &operator=(char c);
373 AString &operator=(const char *s);
374 AString &operator=(const AString &s);
375 void SetFromWStr_if_Ascii(const wchar_t *s);
376 // void SetFromBstr_if_Ascii(BSTR s);
377
378 // private:
379 Z7_FORCE_INLINE
380 AString &operator+=(char c)
381 {
382 if (_limit == _len)
383 Grow_1();
384 unsigned len = _len;
385 char *chars = _chars;
386 chars[len++] = c;
387 chars[len] = 0;
388 _len = len;
389 return *this;
390 }
391 public:
392 void Add_Space();
393 void Add_Space_if_NotEmpty();
394 void Add_OptSpaced(const char *s);
395 void Add_Char(char c);
396 void Add_LF();
397 void Add_Slash();
398 void Add_Dot();
399 void Add_Minus();
400 void Add_Colon();
Add_PathSepar()401 void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }
402
403 AString &operator+=(const char *s);
404 AString &operator+=(const AString &s);
405
406 void Add_UInt32(UInt32 v);
407 void Add_UInt64(UInt64 v);
408
409 void AddFrom(const char *s, unsigned len); // no check
410 void SetFrom(const char *s, unsigned len); // no check
411 void SetFrom_Chars_SizeT(const char* s, size_t len); // no check
SetFrom(const char * s,int len)412 void SetFrom(const char* s, int len) // no check
413 {
414 SetFrom(s, (unsigned)len); // no check
415 }
416 void SetFrom_CalcLen(const char *s, unsigned len);
417
Mid(unsigned startIndex,unsigned count)418 AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
Left(unsigned count)419 AString Left(unsigned count) const { return AString(count, *this); }
420 // void MakeUpper() { MyStringUpper(_chars); }
421 // void MakeLower() { MyStringLower(_chars); }
MakeLower_Ascii()422 void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
423
424
IsEqualTo(const char * s)425 bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; }
IsEqualTo_Ascii_NoCase(const char * s)426 bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
427 // int Compare(const char *s) const { return MyStringCompare(_chars, s); }
428 // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }
429 // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }
430 // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
IsPrefixedBy(const char * s)431 bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
432 bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
433
IsAscii()434 bool IsAscii() const
435 {
436 unsigned len = Len();
437 const char *s = _chars;
438 for (unsigned i = 0; i < len; i++)
439 if ((unsigned char)s[i] >= 0x80)
440 return false;
441 return true;
442 }
Find(char c)443 int Find(char c) const { return FindCharPosInString(_chars, c); }
Find(char c,unsigned startIndex)444 int Find(char c, unsigned startIndex) const
445 {
446 const int pos = FindCharPosInString(_chars + startIndex, c);
447 return pos < 0 ? -1 : (int)startIndex + pos;
448 }
Find(char c,int startIndex)449 int Find(char c, int startIndex) const
450 {
451 return Find(c, (unsigned)startIndex);
452 }
453
454 int ReverseFind(char c) const throw();
ReverseFind_Dot()455 int ReverseFind_Dot() const throw() { return ReverseFind('.'); }
456 int ReverseFind_PathSepar() const throw();
457
Find(const char * s)458 int Find(const char *s) const { return Find(s, 0); }
459 int Find(const char *s, unsigned startIndex) const throw();
460
461 void TrimLeft() throw();
462 void TrimRight() throw();
Trim()463 void Trim()
464 {
465 TrimRight();
466 TrimLeft();
467 }
468
469 void InsertAtFront(char c);
470 // void Insert(unsigned index, char c);
471 void Insert(unsigned index, const char *s);
472 void Insert(unsigned index, const AString &s);
473
474 void RemoveChar(char ch) throw();
475
476 void Replace(char oldChar, char newChar) throw();
477 void Replace(const AString &oldString, const AString &newString);
478
479 void Delete(unsigned index) throw();
480 void Delete(unsigned index, unsigned count) throw();
481 void DeleteFrontal(unsigned num) throw();
DeleteBack()482 void DeleteBack() { _chars[--_len] = 0; }
DeleteFrom(unsigned index)483 void DeleteFrom(unsigned index)
484 {
485 if (index < _len)
486 {
487 _len = index;
488 _chars[index] = 0;
489 }
490 }
DeleteFrom(int index)491 void DeleteFrom(int index)
492 {
493 DeleteFrom((unsigned)index);
494 }
495
496
Wipe_and_Empty()497 void Wipe_and_Empty()
498 {
499 if (_chars)
500 {
501 memset(_chars, 0, (_limit + 1) * sizeof(*_chars));
502 _len = 0;
503 }
504 }
505 };
506
507
508 class AString_Wipe: public AString
509 {
Z7_CLASS_NO_COPY(AString_Wipe)510 Z7_CLASS_NO_COPY(AString_Wipe)
511 public:
512 AString_Wipe(): AString() {}
513 // AString_Wipe(const AString &s): AString(s) {}
514 // AString_Wipe &operator=(const AString &s) { AString::operator=(s); return *this; }
515 // AString_Wipe &operator=(const char *s) { AString::operator=(s); return *this; }
~AString_Wipe()516 ~AString_Wipe() { Wipe_and_Empty(); }
517 };
518
519
520 bool operator<(const AString &s1, const AString &s2);
521 bool operator>(const AString &s1, const AString &s2);
522
523 /*
524 bool operator==(const AString &s1, const AString &s2);
525 bool operator==(const AString &s1, const char *s2);
526 bool operator==(const char *s1, const AString &s2);
527
528 bool operator!=(const AString &s1, const AString &s2);
529 bool operator!=(const AString &s1, const char *s2);
530 bool operator!=(const char *s1, const AString &s2);
531 */
532
533 inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }
534 inline bool operator==(const AString &s1, const char *s2) { return strcmp(s1, s2) == 0; }
535 inline bool operator==(const char *s1, const AString &s2) { return strcmp(s1, s2) == 0; }
536
537 inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }
538 inline bool operator!=(const AString &s1, const char *s2) { return strcmp(s1, s2) != 0; }
539 inline bool operator!=(const char *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
540
541 // ---------- forbidden functions ----------
542
543 void operator==(char c1, const AString &s2);
544 void operator==(const AString &s1, char c2);
545
546 void operator+(char c, const AString &s); // this function can be OK, but we don't use it
547
548 void operator+(const AString &s, int c);
549 void operator+(const AString &s, unsigned c);
550 void operator+(int c, const AString &s);
551 void operator+(unsigned c, const AString &s);
552 void operator-(const AString &s, int c);
553 void operator-(const AString &s, unsigned c);
554
555
556 class UString
557 {
558 wchar_t *_chars;
559 unsigned _len;
560 unsigned _limit;
561
MoveItems(unsigned dest,unsigned src)562 void MoveItems(unsigned dest, unsigned src)
563 {
564 memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t));
565 }
566
567 void InsertSpace(unsigned index, unsigned size);
568
569 void ReAlloc(unsigned newLimit);
570 void ReAlloc2(unsigned newLimit);
571 void SetStartLen(unsigned len);
572 void Grow_1();
573 void Grow(unsigned n);
574
575 UString(unsigned num, const wchar_t *s); // for Mid
576 UString(unsigned num, const UString &s); // for Left
577 UString(const UString &s, wchar_t c); // it's for String + char
578 UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2);
579
580 friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); }
581 // friend UString operator+(wchar_t c, const UString &s); // is not supported
582
583 friend UString operator+(const UString &s1, const UString &s2);
584 friend UString operator+(const UString &s1, const wchar_t *s2);
585 friend UString operator+(const wchar_t *s1, const UString &s2);
586
587 // ---------- forbidden functions ----------
588
589 FORBID_STRING_OPS_UString(signed char)
590 FORBID_STRING_OPS_UString(unsigned char)
591 FORBID_STRING_OPS_UString(short)
592
593 #ifdef MY_NATIVE_WCHAR_T_DEFINED
594 FORBID_STRING_OPS_UString(unsigned short)
595 #endif
596
597 FORBID_STRING_OPS_UString(int)
598 FORBID_STRING_OPS_UString(unsigned)
599 FORBID_STRING_OPS_UString(long)
600 FORBID_STRING_OPS_UString(unsigned long)
601
602 FORBID_STRING_OPS_2(UString, char)
603
604 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
605 UString(const FString &s);
606 UString &operator=(const FString &s);
607 UString &operator+=(const FString &s);
608 #endif
609
610 public:
611 UString();
612 explicit UString(wchar_t c);
613 explicit UString(char c);
614 explicit UString(const char *s);
615 explicit UString(const AString &s);
616 UString(const wchar_t *s);
617 UString(const UString &s);
~UString()618 ~UString() { MY_STRING_DELETE(_chars) }
619
Len()620 unsigned Len() const { return _len; }
IsEmpty()621 bool IsEmpty() const { return _len == 0; }
Empty()622 void Empty() { _len = 0; _chars[0] = 0; }
623
624 operator const wchar_t *() const { return _chars; }
Ptr_non_const()625 wchar_t *Ptr_non_const() const { return _chars; }
Ptr()626 const wchar_t *Ptr() const { return _chars; }
Ptr(int pos)627 const wchar_t *Ptr(int pos) const { return _chars + (unsigned)pos; }
Ptr(unsigned pos)628 const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
RightPtr(unsigned num)629 const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
Back()630 wchar_t Back() const { return _chars[(size_t)_len - 1]; }
631
ReplaceOneCharAtPos(unsigned pos,wchar_t c)632 void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
633
GetBuf()634 wchar_t *GetBuf() { return _chars; }
635
636 /*
637 wchar_t *GetBuf_GetMaxAvail(unsigned &availBufLen)
638 {
639 availBufLen = _limit;
640 return _chars;
641 }
642 */
643
GetBuf(unsigned minLen)644 wchar_t *GetBuf(unsigned minLen)
645 {
646 if (minLen > _limit)
647 ReAlloc2(minLen);
648 return _chars;
649 }
GetBuf_SetEnd(unsigned minLen)650 wchar_t *GetBuf_SetEnd(unsigned minLen)
651 {
652 if (minLen > _limit)
653 ReAlloc2(minLen);
654 wchar_t *chars = _chars;
655 chars[minLen] = 0;
656 _len = minLen;
657 return chars;
658 }
659
ReleaseBuf_SetLen(unsigned newLen)660 void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
ReleaseBuf_SetEnd(unsigned newLen)661 void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
ReleaseBuf_CalcLen(unsigned maxLen)662 void ReleaseBuf_CalcLen(unsigned maxLen)
663 {
664 wchar_t *chars = _chars;
665 chars[maxLen] = 0;
666 _len = MyStringLen(chars);
667 }
668
669 UString &operator=(wchar_t c);
670 UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); }
671 UString &operator=(const wchar_t *s);
672 UString &operator=(const UString &s);
673 void SetFrom(const wchar_t *s, unsigned len); // no check
674 void SetFromBstr(LPCOLESTR s);
675 UString &operator=(const char *s);
676 UString &operator=(const AString &s) { return operator=(s.Ptr()); }
677
678 // private:
679 Z7_FORCE_INLINE
680 UString &operator+=(wchar_t c)
681 {
682 if (_limit == _len)
683 Grow_1();
684 unsigned len = _len;
685 wchar_t *chars = _chars;
686 chars[len++] = c;
687 chars[len] = 0;
688 _len = len;
689 return *this;
690 }
691
692 private:
693 UString &operator+=(char c); // { return (*this)+=((wchar_t)(unsigned char)c); }
694 public:
695 void Add_Char(char c);
696 // void Add_WChar(wchar_t c);
697 void Add_Space();
698 void Add_Space_if_NotEmpty();
699 void Add_LF();
700 void Add_Dot();
701 void Add_Minus();
702 void Add_Colon();
Add_PathSepar()703 void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); }
704
705 UString &operator+=(const wchar_t *s);
706 UString &operator+=(const UString &s);
707 UString &operator+=(const char *s);
708 UString &operator+=(const AString &s) { return operator+=(s.Ptr()); }
709
710 void Add_UInt32(UInt32 v);
711 void Add_UInt64(UInt64 v);
712
Mid(unsigned startIndex,unsigned count)713 UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
Left(unsigned count)714 UString Left(unsigned count) const { return UString(count, *this); }
Left(int count)715 UString Left(int count) const { return Left((unsigned)count); }
716
717 // void MakeUpper() { MyStringUpper(_chars); }
718 // void MakeUpper() { MyStringUpper_Ascii(_chars); }
719 // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); }
MakeLower_Ascii()720 void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
721
IsEqualTo(const char * s)722 bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
IsEqualTo_NoCase(const wchar_t * s)723 bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
IsEqualTo_Ascii_NoCase(const char * s)724 bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
Compare(const wchar_t * s)725 int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
726 // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }
727 // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }
728 // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
IsPrefixedBy(const wchar_t * s)729 bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }
IsPrefixedBy_NoCase(const wchar_t * s)730 bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); }
731 bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
732
IsAscii()733 bool IsAscii() const
734 {
735 unsigned len = Len();
736 const wchar_t *s = _chars;
737 for (unsigned i = 0; i < len; i++)
738 if (s[i] >= 0x80)
739 return false;
740 return true;
741 }
Find(wchar_t c)742 int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
Find(wchar_t c,unsigned startIndex)743 int Find(wchar_t c, unsigned startIndex) const
744 {
745 int pos = FindCharPosInString(_chars + startIndex, c);
746 return pos < 0 ? -1 : (int)startIndex + pos;
747 }
748
749 int ReverseFind(wchar_t c) const throw();
ReverseFind_Dot()750 int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); }
751 int ReverseFind_PathSepar() const throw();
752
Find(const wchar_t * s)753 int Find(const wchar_t *s) const { return Find(s, 0); }
754 int Find(const wchar_t *s, unsigned startIndex) const throw();
755
756 void TrimLeft() throw();
757 void TrimRight() throw();
Trim()758 void Trim()
759 {
760 TrimRight();
761 TrimLeft();
762 }
763
764 void InsertAtFront(wchar_t c);
765 // void Insert_wchar_t(unsigned index, wchar_t c);
766 void Insert(unsigned index, const wchar_t *s);
767 void Insert(unsigned index, const UString &s);
768
769 void RemoveChar(wchar_t ch) throw();
770
771 void Replace(wchar_t oldChar, wchar_t newChar) throw();
772 void Replace(const UString &oldString, const UString &newString);
773
Delete(int index)774 void Delete(int index) throw() { Delete((unsigned)index); }
775 void Delete(unsigned index) throw();
776 void Delete(unsigned index, unsigned count) throw();
777 void DeleteFrontal(unsigned num) throw();
DeleteBack()778 void DeleteBack() { _chars[--_len] = 0; }
DeleteFrom(int index)779 void DeleteFrom(int index) { DeleteFrom((unsigned)index); }
DeleteFrom(unsigned index)780 void DeleteFrom(unsigned index)
781 {
782 if (index < _len)
783 {
784 _len = index;
785 _chars[index] = 0;
786 }
787 }
788
Wipe_and_Empty()789 void Wipe_and_Empty()
790 {
791 if (_chars)
792 {
793 memset(_chars, 0, (_limit + 1) * sizeof(*_chars));
794 _len = 0;
795 }
796 }
797 };
798
799
800 class UString_Wipe: public UString
801 {
Z7_CLASS_NO_COPY(UString_Wipe)802 Z7_CLASS_NO_COPY(UString_Wipe)
803 public:
804 UString_Wipe(): UString() {}
805 // UString_Wipe(const UString &s): UString(s) {}
806 // UString_Wipe &operator=(const UString &s) { UString::operator=(s); return *this; }
807 // UString_Wipe &operator=(const wchar_t *s) { UString::operator=(s); return *this; }
~UString_Wipe()808 ~UString_Wipe() { Wipe_and_Empty(); }
809 };
810
811
812 bool operator<(const UString &s1, const UString &s2);
813 bool operator>(const UString &s1, const UString &s2);
814
815 inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }
816 inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }
817 inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }
818
819 inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }
820 inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }
821 inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
822
823
824 // ---------- forbidden functions ----------
825
826 void operator==(wchar_t c1, const UString &s2);
827 void operator==(const UString &s1, wchar_t c2);
828
829 void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it
830
831 void operator+(const AString &s1, const UString &s2);
832 void operator+(const UString &s1, const AString &s2);
833
834 void operator+(const UString &s1, const char *s2);
835 void operator+(const char *s1, const UString &s2);
836
837 void operator+(const UString &s, char c);
838 void operator+(const UString &s, unsigned char c);
839 void operator+(char c, const UString &s);
840 void operator+(unsigned char c, const UString &s);
841 void operator-(const UString &s1, wchar_t c);
842
843 #ifdef _WIN32
844 // can we forbid these functions, if wchar_t is 32-bit ?
845 void operator+(const UString &s, int c);
846 void operator+(const UString &s, unsigned c);
847 void operator+(int c, const UString &s);
848 void operator+(unsigned c, const UString &s);
849 void operator-(const UString &s1, int c);
850 void operator-(const UString &s1, unsigned c);
851 #endif
852
853
854
855
856
857
858
859 class UString2
860 {
861 wchar_t *_chars;
862 unsigned _len;
863
864 void ReAlloc2(unsigned newLimit);
865 void SetStartLen(unsigned len);
866
867 // ---------- forbidden functions ----------
868
869 FORBID_STRING_OPS_UString2(char)
870 FORBID_STRING_OPS_UString2(signed char)
871 FORBID_STRING_OPS_UString2(unsigned char)
872 FORBID_STRING_OPS_UString2(short)
873
874 UString2 &operator=(wchar_t c);
875
876 UString2(const AString &s);
877 UString2 &operator=(const AString &s);
878 UString2 &operator+=(const AString &s);
879
880 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
881 UString2(const FString &s);
882 UString2 &operator=(const FString &s);
883 UString2 &operator+=(const FString &s);
884 #endif
885
886 public:
UString2()887 UString2(): _chars(NULL), _len(0) {}
888 UString2(const wchar_t *s);
889 UString2(const UString2 &s);
~UString2()890 ~UString2() { if (_chars) { MY_STRING_DELETE(_chars) } }
891
Len()892 unsigned Len() const { return _len; }
IsEmpty()893 bool IsEmpty() const { return _len == 0; }
894 // void Empty() { _len = 0; _chars[0] = 0; }
895
896 // operator const wchar_t *() const { return _chars; }
GetRawPtr()897 const wchar_t *GetRawPtr() const { return _chars; }
898
Compare(const wchar_t * s)899 int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
900
GetBuf(unsigned minLen)901 wchar_t *GetBuf(unsigned minLen)
902 {
903 if (!_chars || minLen > _len)
904 ReAlloc2(minLen);
905 return _chars;
906 }
ReleaseBuf_SetLen(unsigned newLen)907 void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
908
909 UString2 &operator=(const wchar_t *s);
910 UString2 &operator=(const UString2 &s);
911 void SetFromAscii(const char *s);
912 };
913
914 bool operator==(const UString2 &s1, const UString2 &s2);
915 bool operator==(const UString2 &s1, const wchar_t *s2);
916 bool operator==(const wchar_t *s1, const UString2 &s2);
917
918 inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); }
919 inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); }
920 inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); }
921
922
923 // ---------- forbidden functions ----------
924
925 void operator==(wchar_t c1, const UString2 &s2);
926 void operator==(const UString2 &s1, wchar_t c2);
927 bool operator<(const UString2 &s1, const UString2 &s2);
928 bool operator>(const UString2 &s1, const UString2 &s2);
929
930 void operator+(const UString2 &s1, const UString2 &s2);
931 void operator+(const UString2 &s1, const wchar_t *s2);
932 void operator+(const wchar_t *s1, const UString2 &s2);
933 void operator+(wchar_t c, const UString2 &s);
934 void operator+(const UString2 &s, wchar_t c);
935 void operator+(const UString2 &s, char c);
936 void operator+(const UString2 &s, unsigned char c);
937 void operator+(char c, const UString2 &s);
938 void operator+(unsigned char c, const UString2 &s);
939 void operator-(const UString2 &s1, wchar_t c);
940
941
942
943
944
945
946 typedef CObjectVector<AString> AStringVector;
947 typedef CObjectVector<UString> UStringVector;
948
949 #ifdef _UNICODE
950 typedef UString CSysString;
951 #else
952 typedef AString CSysString;
953 #endif
954
955 typedef CObjectVector<CSysString> CSysStringVector;
956
957
958 // ---------- FString ----------
959
960 #ifndef DEBUG_FSTRING_INHERITS_ASTRING
961 #ifdef _WIN32
962 #define USE_UNICODE_FSTRING
963 #endif
964 #endif
965
966 #ifdef USE_UNICODE_FSTRING
967
968 #define MY_FTEXT(quote) L##quote
969
970 typedef wchar_t FChar;
971 typedef UString FString;
972
973 #define fs2us(_x_) (_x_)
974 #define us2fs(_x_) (_x_)
975 FString fas2fs(const char *s);
976 FString fas2fs(const AString &s);
977 AString fs2fas(const FChar *s);
978
979 #else // USE_UNICODE_FSTRING
980
981 #define MY_FTEXT(quote) quote
982
983 typedef char FChar;
984
985 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
986
987 class FString: public AString
988 {
989 // FString &operator=(const char *s);
990 FString &operator=(const AString &s);
991 // FString &operator+=(const AString &s);
992 public:
FString(const AString & s)993 FString(const AString &s): AString(s.Ptr()) {}
FString(const FString & s)994 FString(const FString &s): AString(s.Ptr()) {}
FString(const char * s)995 FString(const char *s): AString(s) {}
FString()996 FString() {}
997 FString &operator=(const FString &s) { AString::operator=((const AString &)s); return *this; }
998 FString &operator=(char c) { AString::operator=(c); return *this; }
999 FString &operator+=(char c) { AString::operator+=(c); return *this; }
1000 FString &operator+=(const FString &s) { AString::operator+=((const AString &)s); return *this; }
Left(unsigned count)1001 FString Left(unsigned count) const { return FString(AString::Left(count)); }
1002 };
1003 void operator+(const AString &s1, const FString &s2);
1004 void operator+(const FString &s1, const AString &s2);
1005
1006 inline FString operator+(const FString &s1, const FString &s2)
1007 {
1008 AString s =(const AString &)s1 + (const AString &)s2;
1009 return FString(s.Ptr());
1010 // return FString((const AString &)s1 + (const AString &)s2);
1011 }
1012 inline FString operator+(const FString &s1, const FChar *s2)
1013 {
1014 return s1 + (FString)s2;
1015 }
1016 /*
1017 inline FString operator+(const FChar *s1, const FString &s2)
1018 {
1019 return (FString)s1 + s2;
1020 }
1021 */
1022
fas2fs(const char * s)1023 inline FString fas2fs(const char *s) { return FString(s); }
1024
1025 #else // DEBUG_FSTRING_INHERITS_ASTRING
1026 typedef AString FString;
1027 #define fas2fs(_x_) (_x_)
1028 #endif // DEBUG_FSTRING_INHERITS_ASTRING
1029
1030 UString fs2us(const FChar *s);
1031 UString fs2us(const FString &s);
1032 FString us2fs(const wchar_t *s);
1033 #define fs2fas(_x_) (_x_)
1034
1035 #endif // USE_UNICODE_FSTRING
1036
1037 #define FTEXT(quote) MY_FTEXT(quote)
1038
1039 #define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)
1040 #define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)
1041
1042 // #define FCHAR_ANY_MASK FTEXT('*')
1043 // #define FSTRING_ANY_MASK FTEXT("*")
1044
1045 typedef const FChar *CFSTR;
1046
1047 typedef CObjectVector<FString> FStringVector;
1048
1049
1050 class CStringFinder
1051 {
1052 AString _temp;
1053 public:
1054 // list - is list of low case Ascii strings separated by space " ".
1055 // the function returns true, if it can find exact word (str) in (list).
1056 bool FindWord_In_LowCaseAsciiList_NoCase(const char *list, const wchar_t *str);
1057 };
1058
1059 void SplitString(const UString &srcString, UStringVector &destStrings);
1060
1061 #endif
1062
1063
1064
1065 #if defined(_WIN32)
1066 // #include <wchar.h>
1067 // WCHAR_MAX is defined as ((wchar_t)-1)
1068 #define Z7_WCHART_IS_16BIT 1
1069 #elif (defined(WCHAR_MAX) && (WCHAR_MAX <= 0xffff)) \
1070 || (defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ == 2))
1071 #define Z7_WCHART_IS_16BIT 1
1072 #endif
1073
1074 #if WCHAR_PATH_SEPARATOR == L'\\'
1075 // WSL scheme
1076 #define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT ((wchar_t)((unsigned)(0xF000) + (unsigned)'\\'))
1077 // #define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT '_'
1078 #endif
1079