1 // Common/MyString.cpp
2
3 #include "StdAfx.h"
4
5 #ifdef _WIN32
6 #include <wchar.h>
7 #else
8 #include <ctype.h>
9 #endif
10
11 #include "IntToString.h"
12
13 #if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING)
14 #include "StringConvert.h"
15 #endif
16
17 #include "MyString.h"
18
19 #define MY_STRING_NEW(_T_, _size_) new _T_[_size_]
20 // #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_)))
21
22 /*
23 inline const char* MyStringGetNextCharPointer(const char *p) throw()
24 {
25 #if defined(_WIN32) && !defined(UNDER_CE)
26 return CharNextA(p);
27 #else
28 return p + 1;
29 #endif
30 }
31 */
32
33 #define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, (_size_))
34 #define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, (_size_))
35
36
FindCharPosInString(const char * s,char c)37 int FindCharPosInString(const char *s, char c) throw()
38 {
39 for (const char *p = s;; p++)
40 {
41 if (*p == c)
42 return (int)(p - s);
43 if (*p == 0)
44 return -1;
45 // MyStringGetNextCharPointer(p);
46 }
47 }
48
FindCharPosInString(const wchar_t * s,wchar_t c)49 int FindCharPosInString(const wchar_t *s, wchar_t c) throw()
50 {
51 for (const wchar_t *p = s;; p++)
52 {
53 if (*p == c)
54 return (int)(p - s);
55 if (*p == 0)
56 return -1;
57 }
58 }
59
60 /*
61 void MyStringUpper_Ascii(char *s) throw()
62 {
63 for (;;)
64 {
65 const char c = *s;
66 if (c == 0)
67 return;
68 *s++ = MyCharUpper_Ascii(c);
69 }
70 }
71
72 void MyStringUpper_Ascii(wchar_t *s) throw()
73 {
74 for (;;)
75 {
76 const wchar_t c = *s;
77 if (c == 0)
78 return;
79 *s++ = MyCharUpper_Ascii(c);
80 }
81 }
82 */
83
MyStringLower_Ascii(char * s)84 void MyStringLower_Ascii(char *s) throw()
85 {
86 for (;;)
87 {
88 const char c = *s;
89 if (c == 0)
90 return;
91 *s++ = MyCharLower_Ascii(c);
92 }
93 }
94
MyStringLower_Ascii(wchar_t * s)95 void MyStringLower_Ascii(wchar_t *s) throw()
96 {
97 for (;;)
98 {
99 const wchar_t c = *s;
100 if (c == 0)
101 return;
102 *s++ = MyCharLower_Ascii(c);
103 }
104 }
105
106 #ifdef _WIN32
107
108 #ifdef _UNICODE
109
110 // wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
111 // wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
112 // for WinCE - FString - char
113 // const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; }
114
115 #else
116
117 // const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); }
118 // char * MyStringUpper(char *s) { return CharUpperA(s); }
119 // char * MyStringLower(char *s) { return CharLowerA(s); }
120
MyCharUpper_WIN(wchar_t c)121 wchar_t MyCharUpper_WIN(wchar_t c) throw()
122 {
123 wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
124 if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
125 return (wchar_t)(unsigned)(UINT_PTR)res;
126 const int kBufSize = 4;
127 char s[kBufSize + 1];
128 int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
129 if (numChars == 0 || numChars > kBufSize)
130 return c;
131 s[numChars] = 0;
132 ::CharUpperA(s);
133 ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
134 return c;
135 }
136
137 /*
138 wchar_t MyCharLower_WIN(wchar_t c)
139 {
140 wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
141 if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
142 return (wchar_t)(unsigned)(UINT_PTR)res;
143 const int kBufSize = 4;
144 char s[kBufSize + 1];
145 int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
146 if (numChars == 0 || numChars > kBufSize)
147 return c;
148 s[numChars] = 0;
149 ::CharLowerA(s);
150 ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
151 return c;
152 }
153 */
154
155 /*
156 wchar_t * MyStringUpper(wchar_t *s)
157 {
158 if (s == 0)
159 return 0;
160 wchar_t *res = CharUpperW(s);
161 if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
162 return res;
163 AString a = UnicodeStringToMultiByte(s);
164 a.MakeUpper();
165 MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
166 return s;
167 }
168 */
169
170 /*
171 wchar_t * MyStringLower(wchar_t *s)
172 {
173 if (s == 0)
174 return 0;
175 wchar_t *res = CharLowerW(s);
176 if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
177 return res;
178 AString a = UnicodeStringToMultiByte(s);
179 a.MakeLower();
180 MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
181 return s;
182 }
183 */
184
185 #endif
186
187 #endif
188
IsString1PrefixedByString2(const char * s1,const char * s2)189 bool IsString1PrefixedByString2(const char *s1, const char *s2) throw()
190 {
191 for (;;)
192 {
193 const char c2 = *s2++; if (c2 == 0) return true;
194 const char c1 = *s1++; if (c1 != c2) return false;
195 }
196 }
197
StringsAreEqualNoCase(const wchar_t * s1,const wchar_t * s2)198 bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw()
199 {
200 for (;;)
201 {
202 const wchar_t c1 = *s1++;
203 const wchar_t c2 = *s2++;
204 if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false;
205 if (c1 == 0) return true;
206 }
207 }
208
209 // ---------- ASCII ----------
210
IsPrefixedBy_Ascii_NoCase(const char * s) const211 bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
212 {
213 const char *s1 = _chars;
214 for (;;)
215 {
216 const char c2 = *s++;
217 if (c2 == 0)
218 return true;
219 const char c1 = *s1++;
220 if (MyCharLower_Ascii(c1) !=
221 MyCharLower_Ascii(c2))
222 return false;
223 }
224 }
225
IsPrefixedBy_Ascii_NoCase(const char * s) const226 bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
227 {
228 const wchar_t *s1 = _chars;
229 for (;;)
230 {
231 const char c2 = *s++;
232 if (c2 == 0)
233 return true;
234 const wchar_t c1 = *s1++;
235 if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
236 return false;
237 }
238 }
239
StringsAreEqual_Ascii(const char * u,const char * a)240 bool StringsAreEqual_Ascii(const char *u, const char *a) throw()
241 {
242 for (;;)
243 {
244 const char c = *a;
245 if (c != *u)
246 return false;
247 if (c == 0)
248 return true;
249 a++;
250 u++;
251 }
252 }
253
StringsAreEqual_Ascii(const wchar_t * u,const char * a)254 bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw()
255 {
256 for (;;)
257 {
258 const unsigned char c = (unsigned char)*a;
259 if (c != *u)
260 return false;
261 if (c == 0)
262 return true;
263 a++;
264 u++;
265 }
266 }
267
StringsAreEqualNoCase_Ascii(const char * s1,const char * s2)268 bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw()
269 {
270 for (;;)
271 {
272 const char c1 = *s1++;
273 const char c2 = *s2++;
274 if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
275 return false;
276 if (c1 == 0)
277 return true;
278 }
279 }
280
StringsAreEqualNoCase_Ascii(const wchar_t * s1,const wchar_t * s2)281 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw()
282 {
283 for (;;)
284 {
285 const wchar_t c1 = *s1++;
286 const wchar_t c2 = *s2++;
287 if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
288 return false;
289 if (c1 == 0)
290 return true;
291 }
292 }
293
StringsAreEqualNoCase_Ascii(const wchar_t * s1,const char * s2)294 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw()
295 {
296 for (;;)
297 {
298 const wchar_t c1 = *s1++;
299 const char c2 = *s2++;
300 if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)))
301 return false;
302 if (c1 == 0)
303 return true;
304 }
305 }
306
IsString1PrefixedByString2(const wchar_t * s1,const wchar_t * s2)307 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()
308 {
309 for (;;)
310 {
311 const wchar_t c2 = *s2++; if (c2 == 0) return true;
312 const wchar_t c1 = *s1++; if (c1 != c2) return false;
313 }
314 }
315
IsString1PrefixedByString2(const wchar_t * s1,const char * s2)316 bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw()
317 {
318 for (;;)
319 {
320 const unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true;
321 const wchar_t c1 = *s1++; if (c1 != c2) return false;
322 }
323 }
324
IsString1PrefixedByString2_NoCase_Ascii(const char * s1,const char * s2)325 bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw()
326 {
327 for (;;)
328 {
329 const char c2 = *s2++; if (c2 == 0) return true;
330 const char c1 = *s1++;
331 if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
332 return false;
333 }
334 }
335
IsString1PrefixedByString2_NoCase_Ascii(const wchar_t * s1,const char * s2)336 bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw()
337 {
338 for (;;)
339 {
340 const char c2 = *s2++; if (c2 == 0) return true;
341 const wchar_t c1 = *s1++;
342 if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
343 return false;
344 }
345 }
346
IsString1PrefixedByString2_NoCase(const wchar_t * s1,const wchar_t * s2)347 bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()
348 {
349 for (;;)
350 {
351 const wchar_t c2 = *s2++; if (c2 == 0) return true;
352 const wchar_t c1 = *s1++;
353 if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2))
354 return false;
355 }
356 }
357
358 // NTFS order: uses upper case
MyStringCompareNoCase(const wchar_t * s1,const wchar_t * s2)359 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()
360 {
361 for (;;)
362 {
363 const wchar_t c1 = *s1++;
364 const wchar_t c2 = *s2++;
365 if (c1 != c2)
366 {
367 const wchar_t u1 = MyCharUpper(c1);
368 const wchar_t u2 = MyCharUpper(c2);
369 if (u1 < u2) return -1;
370 if (u1 > u2) return 1;
371 }
372 if (c1 == 0) return 0;
373 }
374 }
375
376 /*
377 int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)
378 {
379 for (; num != 0; num--)
380 {
381 wchar_t c1 = *s1++;
382 wchar_t c2 = *s2++;
383 if (c1 != c2)
384 {
385 wchar_t u1 = MyCharUpper(c1);
386 wchar_t u2 = MyCharUpper(c2);
387 if (u1 < u2) return -1;
388 if (u1 > u2) return 1;
389 }
390 if (c1 == 0) return 0;
391 }
392 return 0;
393 }
394 */
395
396 // ---------- AString ----------
397
InsertSpace(unsigned & index,unsigned size)398 void AString::InsertSpace(unsigned &index, unsigned size)
399 {
400 Grow(size);
401 MoveItems(index + size, index);
402 }
403
404 #define k_Alloc_Len_Limit (0x40000000 - 2)
405 // #define k_Alloc_Len_Limit (((unsigned)1 << (sizeof(unsigned) * 8 - 2)) - 2)
406
ReAlloc(unsigned newLimit)407 void AString::ReAlloc(unsigned newLimit)
408 {
409 // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, (size_t)_len + 1);
410 char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1);
411 memcpy(newBuf, _chars, (size_t)_len + 1);
412 MY_STRING_DELETE(_chars)
413 _chars = newBuf;
414 _limit = newLimit;
415 }
416
417 #define THROW_STRING_ALLOC_EXCEPTION { throw 20130220; }
418
419 #define CHECK_STRING_ALLOC_LEN(len) \
420 { if ((len) > k_Alloc_Len_Limit) THROW_STRING_ALLOC_EXCEPTION }
421
ReAlloc2(unsigned newLimit)422 void AString::ReAlloc2(unsigned newLimit)
423 {
424 CHECK_STRING_ALLOC_LEN(newLimit)
425 // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, 0);
426 char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1);
427 newBuf[0] = 0;
428 MY_STRING_DELETE(_chars)
429 _chars = newBuf;
430 _limit = newLimit;
431 _len = 0;
432 }
433
SetStartLen(unsigned len)434 void AString::SetStartLen(unsigned len)
435 {
436 _chars = NULL;
437 _chars = MY_STRING_NEW_char((size_t)len + 1);
438 _len = len;
439 _limit = len;
440 }
441
442 Z7_NO_INLINE
Grow_1()443 void AString::Grow_1()
444 {
445 unsigned next = _len;
446 next += next / 2;
447 next += 16;
448 next &= ~(unsigned)15;
449 next--;
450 if (next < _len || next > k_Alloc_Len_Limit)
451 next = k_Alloc_Len_Limit;
452 if (next <= _len)
453 THROW_STRING_ALLOC_EXCEPTION
454 ReAlloc(next);
455 // Grow(1);
456 }
457
Grow(unsigned n)458 void AString::Grow(unsigned n)
459 {
460 const unsigned freeSize = _limit - _len;
461 if (n <= freeSize)
462 return;
463 unsigned next = _len + n;
464 next += next / 2;
465 next += 16;
466 next &= ~(unsigned)15;
467 next--;
468 if (next < _len || next > k_Alloc_Len_Limit)
469 next = k_Alloc_Len_Limit;
470 if (next <= _len || next - _len < n)
471 THROW_STRING_ALLOC_EXCEPTION
472 ReAlloc(next);
473 }
474
AString(unsigned num,const char * s)475 AString::AString(unsigned num, const char *s)
476 {
477 unsigned len = MyStringLen(s);
478 if (num > len)
479 num = len;
480 SetStartLen(num);
481 memcpy(_chars, s, num);
482 _chars[num] = 0;
483 }
484
AString(unsigned num,const AString & s)485 AString::AString(unsigned num, const AString &s)
486 {
487 if (num > s._len)
488 num = s._len;
489 SetStartLen(num);
490 memcpy(_chars, s._chars, num);
491 _chars[num] = 0;
492 }
493
AString(const AString & s,char c)494 AString::AString(const AString &s, char c)
495 {
496 SetStartLen(s.Len() + 1);
497 char *chars = _chars;
498 unsigned len = s.Len();
499 memcpy(chars, s, len);
500 chars[len] = c;
501 chars[(size_t)len + 1] = 0;
502 }
503
AString(const char * s1,unsigned num1,const char * s2,unsigned num2)504 AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)
505 {
506 SetStartLen(num1 + num2);
507 char *chars = _chars;
508 memcpy(chars, s1, num1);
509 memcpy(chars + num1, s2, num2 + 1);
510 }
511
operator +(const AString & s1,const AString & s2)512 AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }
operator +(const AString & s1,const char * s2)513 AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
operator +(const char * s1,const AString & s2)514 AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }
515
516 static const unsigned kStartStringCapacity = 4;
517
AString()518 AString::AString()
519 {
520 _chars = NULL;
521 _chars = MY_STRING_NEW_char(kStartStringCapacity);
522 _len = 0;
523 _limit = kStartStringCapacity - 1;
524 _chars[0] = 0;
525 }
526
AString(char c)527 AString::AString(char c)
528 {
529 SetStartLen(1);
530 char *chars = _chars;
531 chars[0] = c;
532 chars[1] = 0;
533 }
534
AString(const char * s)535 AString::AString(const char *s)
536 {
537 SetStartLen(MyStringLen(s));
538 MyStringCopy(_chars, s);
539 }
540
AString(const AString & s)541 AString::AString(const AString &s)
542 {
543 SetStartLen(s._len);
544 MyStringCopy(_chars, s._chars);
545 }
546
operator =(char c)547 AString &AString::operator=(char c)
548 {
549 if (1 > _limit)
550 {
551 char *newBuf = MY_STRING_NEW_char(1 + 1);
552 MY_STRING_DELETE(_chars)
553 _chars = newBuf;
554 _limit = 1;
555 }
556 _len = 1;
557 char *chars = _chars;
558 chars[0] = c;
559 chars[1] = 0;
560 return *this;
561 }
562
operator =(const char * s)563 AString &AString::operator=(const char *s)
564 {
565 unsigned len = MyStringLen(s);
566 if (len > _limit)
567 {
568 char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
569 MY_STRING_DELETE(_chars)
570 _chars = newBuf;
571 _limit = len;
572 }
573 _len = len;
574 MyStringCopy(_chars, s);
575 return *this;
576 }
577
operator =(const AString & s)578 AString &AString::operator=(const AString &s)
579 {
580 if (&s == this)
581 return *this;
582 unsigned len = s._len;
583 if (len > _limit)
584 {
585 char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
586 MY_STRING_DELETE(_chars)
587 _chars = newBuf;
588 _limit = len;
589 }
590 _len = len;
591 MyStringCopy(_chars, s._chars);
592 return *this;
593 }
594
SetFromWStr_if_Ascii(const wchar_t * s)595 void AString::SetFromWStr_if_Ascii(const wchar_t *s)
596 {
597 unsigned len = 0;
598 {
599 for (;; len++)
600 {
601 wchar_t c = s[len];
602 if (c == 0)
603 break;
604 if (c >= 0x80)
605 return;
606 }
607 }
608 if (len > _limit)
609 {
610 char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
611 MY_STRING_DELETE(_chars)
612 _chars = newBuf;
613 _limit = len;
614 }
615 _len = len;
616 char *dest = _chars;
617 unsigned i;
618 for (i = 0; i < len; i++)
619 dest[i] = (char)s[i];
620 dest[i] = 0;
621 }
622
623 /*
624 void AString::SetFromBstr_if_Ascii(BSTR s)
625 {
626 unsigned len = ::SysStringLen(s);
627 {
628 for (unsigned i = 0; i < len; i++)
629 if (s[i] <= 0 || s[i] >= 0x80)
630 return;
631 }
632 if (len > _limit)
633 {
634 char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
635 MY_STRING_DELETE(_chars)
636 _chars = newBuf;
637 _limit = len;
638 }
639 _len = len;
640 char *dest = _chars;
641 unsigned i;
642 for (i = 0; i < len; i++)
643 dest[i] = (char)s[i];
644 dest[i] = 0;
645 }
646 */
647
Add_Char(char c)648 void AString::Add_Char(char c) { operator+=(c); }
Add_Space()649 void AString::Add_Space() { operator+=(' '); }
Add_Space_if_NotEmpty()650 void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
Add_LF()651 void AString::Add_LF() { operator+=('\n'); }
Add_Slash()652 void AString::Add_Slash() { operator+=('/'); }
Add_Dot()653 void AString::Add_Dot() { operator+=('.'); }
Add_Minus()654 void AString::Add_Minus() { operator+=('-'); }
Add_Colon()655 void AString::Add_Colon() { operator+=(':'); }
656
operator +=(const char * s)657 AString &AString::operator+=(const char *s)
658 {
659 unsigned len = MyStringLen(s);
660 Grow(len);
661 MyStringCopy(_chars + _len, s);
662 _len += len;
663 return *this;
664 }
665
Add_OptSpaced(const char * s)666 void AString::Add_OptSpaced(const char *s)
667 {
668 Add_Space_if_NotEmpty();
669 (*this) += s;
670 }
671
operator +=(const AString & s)672 AString &AString::operator+=(const AString &s)
673 {
674 Grow(s._len);
675 MyStringCopy(_chars + _len, s._chars);
676 _len += s._len;
677 return *this;
678 }
679
Add_UInt32(UInt32 v)680 void AString::Add_UInt32(UInt32 v)
681 {
682 Grow(10);
683 _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);
684 }
685
Add_UInt64(UInt64 v)686 void UString::Add_UInt64(UInt64 v)
687 {
688 Grow(20);
689 _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);
690 }
691
AddFrom(const char * s,unsigned len)692 void AString::AddFrom(const char *s, unsigned len) // no check
693 {
694 if (len != 0)
695 {
696 Grow(len);
697 memcpy(_chars + _len, s, len);
698 len += _len;
699 _chars[len] = 0;
700 _len = len;
701 }
702 }
703
SetFrom(const char * s,unsigned len)704 void AString::SetFrom(const char *s, unsigned len) // no check
705 {
706 if (len > _limit)
707 {
708 CHECK_STRING_ALLOC_LEN(len)
709 char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
710 MY_STRING_DELETE(_chars)
711 _chars = newBuf;
712 _limit = len;
713 }
714 if (len != 0)
715 memcpy(_chars, s, len);
716 _chars[len] = 0;
717 _len = len;
718 }
719
SetFrom_Chars_SizeT(const char * s,size_t len)720 void AString::SetFrom_Chars_SizeT(const char *s, size_t len)
721 {
722 CHECK_STRING_ALLOC_LEN(len)
723 SetFrom(s, (unsigned)len);
724 }
725
SetFrom_CalcLen(const char * s,unsigned len)726 void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check
727 {
728 unsigned i;
729 for (i = 0; i < len; i++)
730 if (s[i] == 0)
731 break;
732 SetFrom(s, i);
733 }
734
Find(const char * s,unsigned startIndex) const735 int AString::Find(const char *s, unsigned startIndex) const throw()
736 {
737 const char *fs = strstr(_chars + startIndex, s);
738 if (!fs)
739 return -1;
740 return (int)(fs - _chars);
741
742 /*
743 if (s[0] == 0)
744 return startIndex;
745 unsigned len = MyStringLen(s);
746 const char *p = _chars + startIndex;
747 for (;; p++)
748 {
749 const char c = *p;
750 if (c != s[0])
751 {
752 if (c == 0)
753 return -1;
754 continue;
755 }
756 unsigned i;
757 for (i = 1; i < len; i++)
758 if (p[i] != s[i])
759 break;
760 if (i == len)
761 return (int)(p - _chars);
762 }
763 */
764 }
765
ReverseFind(char c) const766 int AString::ReverseFind(char c) const throw()
767 {
768 if (_len == 0)
769 return -1;
770 const char *p = _chars + _len - 1;
771 for (;;)
772 {
773 if (*p == c)
774 return (int)(p - _chars);
775 if (p == _chars)
776 return -1;
777 p--; // p = GetPrevCharPointer(_chars, p);
778 }
779 }
780
ReverseFind_PathSepar() const781 int AString::ReverseFind_PathSepar() const throw()
782 {
783 if (_len == 0)
784 return -1;
785 const char *p = _chars + _len - 1;
786 for (;;)
787 {
788 const char c = *p;
789 if (IS_PATH_SEPAR(c))
790 return (int)(p - _chars);
791 if (p == _chars)
792 return -1;
793 p--;
794 }
795 }
796
TrimLeft()797 void AString::TrimLeft() throw()
798 {
799 const char *p = _chars;
800 for (;; p++)
801 {
802 char c = *p;
803 if (c != ' ' && c != '\n' && c != '\t')
804 break;
805 }
806 unsigned pos = (unsigned)(p - _chars);
807 if (pos != 0)
808 {
809 MoveItems(0, pos);
810 _len -= pos;
811 }
812 }
813
TrimRight()814 void AString::TrimRight() throw()
815 {
816 const char *p = _chars;
817 unsigned i;
818 for (i = _len; i != 0; i--)
819 {
820 char c = p[(size_t)i - 1];
821 if (c != ' ' && c != '\n' && c != '\t')
822 break;
823 }
824 if (i != _len)
825 {
826 _chars[i] = 0;
827 _len = i;
828 }
829 }
830
InsertAtFront(char c)831 void AString::InsertAtFront(char c)
832 {
833 if (_limit == _len)
834 Grow_1();
835 MoveItems(1, 0);
836 _chars[0] = c;
837 _len++;
838 }
839
840 /*
841 void AString::Insert(unsigned index, char c)
842 {
843 InsertSpace(index, 1);
844 _chars[index] = c;
845 _len++;
846 }
847 */
848
Insert(unsigned index,const char * s)849 void AString::Insert(unsigned index, const char *s)
850 {
851 unsigned num = MyStringLen(s);
852 if (num != 0)
853 {
854 InsertSpace(index, num);
855 memcpy(_chars + index, s, num);
856 _len += num;
857 }
858 }
859
Insert(unsigned index,const AString & s)860 void AString::Insert(unsigned index, const AString &s)
861 {
862 unsigned num = s.Len();
863 if (num != 0)
864 {
865 InsertSpace(index, num);
866 memcpy(_chars + index, s, num);
867 _len += num;
868 }
869 }
870
RemoveChar(char ch)871 void AString::RemoveChar(char ch) throw()
872 {
873 char *src = _chars;
874
875 for (;;)
876 {
877 char c = *src++;
878 if (c == 0)
879 return;
880 if (c == ch)
881 break;
882 }
883
884 char *dest = src - 1;
885
886 for (;;)
887 {
888 char c = *src++;
889 if (c == 0)
890 break;
891 if (c != ch)
892 *dest++ = c;
893 }
894
895 *dest = 0;
896 _len = (unsigned)(dest - _chars);
897 }
898
899 // !!!!!!!!!!!!!!! test it if newChar = '\0'
Replace(char oldChar,char newChar)900 void AString::Replace(char oldChar, char newChar) throw()
901 {
902 if (oldChar == newChar)
903 return; // 0;
904 // unsigned number = 0;
905 int pos = 0;
906 char *chars = _chars;
907 while ((unsigned)pos < _len)
908 {
909 pos = Find(oldChar, (unsigned)pos);
910 if (pos < 0)
911 break;
912 chars[(unsigned)pos] = newChar;
913 pos++;
914 // number++;
915 }
916 return; // number;
917 }
918
Replace(const AString & oldString,const AString & newString)919 void AString::Replace(const AString &oldString, const AString &newString)
920 {
921 if (oldString.IsEmpty())
922 return; // 0;
923 if (oldString == newString)
924 return; // 0;
925 const unsigned oldLen = oldString.Len();
926 const unsigned newLen = newString.Len();
927 // unsigned number = 0;
928 int pos = 0;
929 while ((unsigned)pos < _len)
930 {
931 pos = Find(oldString, (unsigned)pos);
932 if (pos < 0)
933 break;
934 Delete((unsigned)pos, oldLen);
935 Insert((unsigned)pos, newString);
936 pos += newLen;
937 // number++;
938 }
939 // return number;
940 }
941
Delete(unsigned index)942 void AString::Delete(unsigned index) throw()
943 {
944 MoveItems(index, index + 1);
945 _len--;
946 }
947
Delete(unsigned index,unsigned count)948 void AString::Delete(unsigned index, unsigned count) throw()
949 {
950 if (index + count > _len)
951 count = _len - index;
952 if (count > 0)
953 {
954 MoveItems(index, index + count);
955 _len -= count;
956 }
957 }
958
DeleteFrontal(unsigned num)959 void AString::DeleteFrontal(unsigned num) throw()
960 {
961 if (num != 0)
962 {
963 MoveItems(0, num);
964 _len -= num;
965 }
966 }
967
968 /*
969 AString operator+(const AString &s1, const AString &s2)
970 {
971 AString result(s1);
972 result += s2;
973 return result;
974 }
975
976 AString operator+(const AString &s, const char *chars)
977 {
978 AString result(s);
979 result += chars;
980 return result;
981 }
982
983 AString operator+(const char *chars, const AString &s)
984 {
985 AString result(chars);
986 result += s;
987 return result;
988 }
989
990 AString operator+(const AString &s, char c)
991 {
992 AString result(s);
993 result += c;
994 return result;
995 }
996 */
997
998 /*
999 AString operator+(char c, const AString &s)
1000 {
1001 AString result(c);
1002 result += s;
1003 return result;
1004 }
1005 */
1006
1007
1008
1009
1010 // ---------- UString ----------
1011
InsertSpace(unsigned index,unsigned size)1012 void UString::InsertSpace(unsigned index, unsigned size)
1013 {
1014 Grow(size);
1015 MoveItems(index + size, index);
1016 }
1017
ReAlloc(unsigned newLimit)1018 void UString::ReAlloc(unsigned newLimit)
1019 {
1020 // MY_STRING_REALLOC(_chars, wchar_t, (size_t)newLimit + 1, (size_t)_len + 1);
1021 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);
1022 wmemcpy(newBuf, _chars, _len + 1);
1023 MY_STRING_DELETE(_chars)
1024 _chars = newBuf;
1025 _limit = newLimit;
1026 }
1027
ReAlloc2(unsigned newLimit)1028 void UString::ReAlloc2(unsigned newLimit)
1029 {
1030 CHECK_STRING_ALLOC_LEN(newLimit)
1031 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
1032 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);
1033 newBuf[0] = 0;
1034 MY_STRING_DELETE(_chars)
1035 _chars = newBuf;
1036 _limit = newLimit;
1037 _len = 0;
1038 }
1039
SetStartLen(unsigned len)1040 void UString::SetStartLen(unsigned len)
1041 {
1042 _chars = NULL;
1043 _chars = MY_STRING_NEW_wchar_t((size_t)len + 1);
1044 _len = len;
1045 _limit = len;
1046 }
1047
1048 Z7_NO_INLINE
Grow_1()1049 void UString::Grow_1()
1050 {
1051 unsigned next = _len;
1052 next += next / 2;
1053 next += 16;
1054 next &= ~(unsigned)15;
1055 next--;
1056 if (next < _len || next > k_Alloc_Len_Limit)
1057 next = k_Alloc_Len_Limit;
1058 if (next <= _len)
1059 THROW_STRING_ALLOC_EXCEPTION
1060 ReAlloc(next);
1061 }
1062
Grow(unsigned n)1063 void UString::Grow(unsigned n)
1064 {
1065 const unsigned freeSize = _limit - _len;
1066 if (n <= freeSize)
1067 return;
1068 unsigned next = _len + n;
1069 next += next / 2;
1070 next += 16;
1071 next &= ~(unsigned)15;
1072 next--;
1073 if (next < _len || next > k_Alloc_Len_Limit)
1074 next = k_Alloc_Len_Limit;
1075 if (next <= _len || next - _len < n)
1076 THROW_STRING_ALLOC_EXCEPTION
1077 ReAlloc(next - 1);
1078 }
1079
1080
UString(unsigned num,const wchar_t * s)1081 UString::UString(unsigned num, const wchar_t *s)
1082 {
1083 unsigned len = MyStringLen(s);
1084 if (num > len)
1085 num = len;
1086 SetStartLen(num);
1087 wmemcpy(_chars, s, num);
1088 _chars[num] = 0;
1089 }
1090
1091
UString(unsigned num,const UString & s)1092 UString::UString(unsigned num, const UString &s)
1093 {
1094 if (num > s._len)
1095 num = s._len;
1096 SetStartLen(num);
1097 wmemcpy(_chars, s._chars, num);
1098 _chars[num] = 0;
1099 }
1100
UString(const UString & s,wchar_t c)1101 UString::UString(const UString &s, wchar_t c)
1102 {
1103 SetStartLen(s.Len() + 1);
1104 wchar_t *chars = _chars;
1105 unsigned len = s.Len();
1106 wmemcpy(chars, s, len);
1107 chars[len] = c;
1108 chars[(size_t)len + 1] = 0;
1109 }
1110
UString(const wchar_t * s1,unsigned num1,const wchar_t * s2,unsigned num2)1111 UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)
1112 {
1113 SetStartLen(num1 + num2);
1114 wchar_t *chars = _chars;
1115 wmemcpy(chars, s1, num1);
1116 wmemcpy(chars + num1, s2, num2 + 1);
1117 }
1118
operator +(const UString & s1,const UString & s2)1119 UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }
operator +(const UString & s1,const wchar_t * s2)1120 UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); }
operator +(const wchar_t * s1,const UString & s2)1121 UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }
1122
UString()1123 UString::UString()
1124 {
1125 _chars = NULL;
1126 _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity);
1127 _len = 0;
1128 _limit = kStartStringCapacity - 1;
1129 _chars[0] = 0;
1130 }
1131
UString(wchar_t c)1132 UString::UString(wchar_t c)
1133 {
1134 SetStartLen(1);
1135 wchar_t *chars = _chars;
1136 chars[0] = c;
1137 chars[1] = 0;
1138 }
1139
UString(char c)1140 UString::UString(char c)
1141 {
1142 SetStartLen(1);
1143 wchar_t *chars = _chars;
1144 chars[0] = (unsigned char)c;
1145 chars[1] = 0;
1146 }
1147
UString(const wchar_t * s)1148 UString::UString(const wchar_t *s)
1149 {
1150 const unsigned len = MyStringLen(s);
1151 SetStartLen(len);
1152 wmemcpy(_chars, s, len + 1);
1153 }
1154
UString(const char * s)1155 UString::UString(const char *s)
1156 {
1157 const unsigned len = MyStringLen(s);
1158 SetStartLen(len);
1159 wchar_t *chars = _chars;
1160 for (unsigned i = 0; i < len; i++)
1161 chars[i] = (unsigned char)s[i];
1162 chars[len] = 0;
1163 }
1164
UString(const AString & s)1165 UString::UString(const AString &s)
1166 {
1167 const unsigned len = s.Len();
1168 SetStartLen(len);
1169 wchar_t *chars = _chars;
1170 const char *s2 = s.Ptr();
1171 for (unsigned i = 0; i < len; i++)
1172 chars[i] = (unsigned char)s2[i];
1173 chars[len] = 0;
1174 }
1175
UString(const UString & s)1176 UString::UString(const UString &s)
1177 {
1178 SetStartLen(s._len);
1179 wmemcpy(_chars, s._chars, s._len + 1);
1180 }
1181
operator =(wchar_t c)1182 UString &UString::operator=(wchar_t c)
1183 {
1184 if (1 > _limit)
1185 {
1186 wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
1187 MY_STRING_DELETE(_chars)
1188 _chars = newBuf;
1189 _limit = 1;
1190 }
1191 _len = 1;
1192 wchar_t *chars = _chars;
1193 chars[0] = c;
1194 chars[1] = 0;
1195 return *this;
1196 }
1197
operator =(const wchar_t * s)1198 UString &UString::operator=(const wchar_t *s)
1199 {
1200 unsigned len = MyStringLen(s);
1201 if (len > _limit)
1202 {
1203 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1204 MY_STRING_DELETE(_chars)
1205 _chars = newBuf;
1206 _limit = len;
1207 }
1208 _len = len;
1209 wmemcpy(_chars, s, len + 1);
1210 return *this;
1211 }
1212
operator =(const UString & s)1213 UString &UString::operator=(const UString &s)
1214 {
1215 if (&s == this)
1216 return *this;
1217 unsigned len = s._len;
1218 if (len > _limit)
1219 {
1220 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1221 MY_STRING_DELETE(_chars)
1222 _chars = newBuf;
1223 _limit = len;
1224 }
1225 _len = len;
1226 wmemcpy(_chars, s._chars, len + 1);
1227 return *this;
1228 }
1229
SetFrom(const wchar_t * s,unsigned len)1230 void UString::SetFrom(const wchar_t *s, unsigned len) // no check
1231 {
1232 if (len > _limit)
1233 {
1234 CHECK_STRING_ALLOC_LEN(len)
1235 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1236 MY_STRING_DELETE(_chars)
1237 _chars = newBuf;
1238 _limit = len;
1239 }
1240 if (len != 0)
1241 wmemcpy(_chars, s, len);
1242 _chars[len] = 0;
1243 _len = len;
1244 }
1245
SetFromBstr(LPCOLESTR s)1246 void UString::SetFromBstr(LPCOLESTR s)
1247 {
1248 unsigned len = ::SysStringLen((BSTR)(void *)(s));
1249
1250 /*
1251 #if WCHAR_MAX > 0xffff
1252 size_t num_wchars = 0;
1253 for (size_t i = 0; i < len;)
1254 {
1255 wchar_t c = s[i++];
1256 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1257 {
1258 wchar_t c2 = s[i];
1259 if (c2 >= 0xdc00 && c2 < 0xe000)
1260 {
1261 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1262 i++;
1263 }
1264 }
1265 num_wchars++;
1266 }
1267 len = num_wchars;
1268 #endif
1269 */
1270
1271 if (len > _limit)
1272 {
1273 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1274 MY_STRING_DELETE(_chars)
1275 _chars = newBuf;
1276 _limit = len;
1277 }
1278 _len = len;
1279
1280 /*
1281 #if WCHAR_MAX > 0xffff
1282
1283 wchar_t *chars = _chars;
1284 for (size_t i = 0; i <= len; i++)
1285 {
1286 wchar_t c = *s++;
1287 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1288 {
1289 wchar_t c2 = *s;
1290 if (c2 >= 0xdc00 && c2 < 0xe000)
1291 {
1292 s++;
1293 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1294 }
1295 }
1296 chars[i] = c;
1297 }
1298
1299 #else
1300 */
1301
1302 // if (s)
1303 wmemcpy(_chars, s, len + 1);
1304
1305 // #endif
1306 }
1307
operator =(const char * s)1308 UString &UString::operator=(const char *s)
1309 {
1310 unsigned len = MyStringLen(s);
1311 if (len > _limit)
1312 {
1313 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1314 MY_STRING_DELETE(_chars)
1315 _chars = newBuf;
1316 _limit = len;
1317 }
1318 wchar_t *chars = _chars;
1319 for (unsigned i = 0; i < len; i++)
1320 chars[i] = (unsigned char)s[i];
1321 chars[len] = 0;
1322 _len = len;
1323 return *this;
1324 }
1325
Add_Char(char c)1326 void UString::Add_Char(char c) { operator+=((wchar_t)(unsigned char)c); }
1327 // void UString::Add_WChar(wchar_t c) { operator+=(c); }
Add_Dot()1328 void UString::Add_Dot() { operator+=(L'.'); }
Add_Space()1329 void UString::Add_Space() { operator+=(L' '); }
Add_Minus()1330 void UString::Add_Minus() { operator+=(L'-'); }
Add_Colon()1331 void UString::Add_Colon() { operator+=(L':'); }
Add_LF()1332 void UString::Add_LF() { operator+=(L'\n'); }
Add_Space_if_NotEmpty()1333 void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
1334
operator +=(const wchar_t * s)1335 UString &UString::operator+=(const wchar_t *s)
1336 {
1337 unsigned len = MyStringLen(s);
1338 Grow(len);
1339 wmemcpy(_chars + _len, s, len + 1);
1340 _len += len;
1341 return *this;
1342 }
1343
operator +=(const UString & s)1344 UString &UString::operator+=(const UString &s)
1345 {
1346 Grow(s._len);
1347 wmemcpy(_chars + _len, s._chars, s._len + 1);
1348 _len += s._len;
1349 return *this;
1350 }
1351
operator +=(const char * s)1352 UString &UString::operator+=(const char *s)
1353 {
1354 unsigned len = MyStringLen(s);
1355 Grow(len);
1356 wchar_t *chars = _chars + _len;
1357 for (unsigned i = 0; i < len; i++)
1358 chars[i] = (unsigned char)s[i];
1359 chars[len] = 0;
1360 _len += len;
1361 return *this;
1362 }
1363
1364
Add_UInt32(UInt32 v)1365 void UString::Add_UInt32(UInt32 v)
1366 {
1367 Grow(10);
1368 _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);
1369 }
1370
Add_UInt64(UInt64 v)1371 void AString::Add_UInt64(UInt64 v)
1372 {
1373 Grow(20);
1374 _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);
1375 }
1376
1377
Find(const wchar_t * s,unsigned startIndex) const1378 int UString::Find(const wchar_t *s, unsigned startIndex) const throw()
1379 {
1380 const wchar_t *fs = wcsstr(_chars + startIndex, s);
1381 if (!fs)
1382 return -1;
1383 return (int)(fs - _chars);
1384
1385 /*
1386 if (s[0] == 0)
1387 return startIndex;
1388 unsigned len = MyStringLen(s);
1389 const wchar_t *p = _chars + startIndex;
1390 for (;; p++)
1391 {
1392 const wchar_t c = *p;
1393 if (c != s[0])
1394 {
1395 if (c == 0)
1396 return -1;
1397 continue;
1398 }
1399 unsigned i;
1400 for (i = 1; i < len; i++)
1401 if (p[i] != s[i])
1402 break;
1403 if (i == len)
1404 return (int)(p - _chars);
1405 }
1406 */
1407 }
1408
ReverseFind(wchar_t c) const1409 int UString::ReverseFind(wchar_t c) const throw()
1410 {
1411 if (_len == 0)
1412 return -1;
1413 const wchar_t *p = _chars + _len;
1414 do
1415 {
1416 if (*(--p) == c)
1417 return (int)(p - _chars);
1418 }
1419 while (p != _chars);
1420 return -1;
1421 }
1422
ReverseFind_PathSepar() const1423 int UString::ReverseFind_PathSepar() const throw()
1424 {
1425 const wchar_t *p = _chars + _len;
1426 while (p != _chars)
1427 {
1428 const wchar_t c = *(--p);
1429 if (IS_PATH_SEPAR(c))
1430 return (int)(p - _chars);
1431 }
1432 return -1;
1433 }
1434
TrimLeft()1435 void UString::TrimLeft() throw()
1436 {
1437 const wchar_t *p = _chars;
1438 for (;; p++)
1439 {
1440 wchar_t c = *p;
1441 if (c != ' ' && c != '\n' && c != '\t')
1442 break;
1443 }
1444 unsigned pos = (unsigned)(p - _chars);
1445 if (pos != 0)
1446 {
1447 MoveItems(0, pos);
1448 _len -= pos;
1449 }
1450 }
1451
TrimRight()1452 void UString::TrimRight() throw()
1453 {
1454 const wchar_t *p = _chars;
1455 unsigned i;
1456 for (i = _len; i != 0; i--)
1457 {
1458 wchar_t c = p[(size_t)i - 1];
1459 if (c != ' ' && c != '\n' && c != '\t')
1460 break;
1461 }
1462 if (i != _len)
1463 {
1464 _chars[i] = 0;
1465 _len = i;
1466 }
1467 }
1468
InsertAtFront(wchar_t c)1469 void UString::InsertAtFront(wchar_t c)
1470 {
1471 if (_limit == _len)
1472 Grow_1();
1473 MoveItems(1, 0);
1474 _chars[0] = c;
1475 _len++;
1476 }
1477
1478 /*
1479 void UString::Insert_wchar_t(unsigned index, wchar_t c)
1480 {
1481 InsertSpace(index, 1);
1482 _chars[index] = c;
1483 _len++;
1484 }
1485 */
1486
Insert(unsigned index,const wchar_t * s)1487 void UString::Insert(unsigned index, const wchar_t *s)
1488 {
1489 unsigned num = MyStringLen(s);
1490 if (num != 0)
1491 {
1492 InsertSpace(index, num);
1493 wmemcpy(_chars + index, s, num);
1494 _len += num;
1495 }
1496 }
1497
Insert(unsigned index,const UString & s)1498 void UString::Insert(unsigned index, const UString &s)
1499 {
1500 unsigned num = s.Len();
1501 if (num != 0)
1502 {
1503 InsertSpace(index, num);
1504 wmemcpy(_chars + index, s, num);
1505 _len += num;
1506 }
1507 }
1508
RemoveChar(wchar_t ch)1509 void UString::RemoveChar(wchar_t ch) throw()
1510 {
1511 wchar_t *src = _chars;
1512
1513 for (;;)
1514 {
1515 wchar_t c = *src++;
1516 if (c == 0)
1517 return;
1518 if (c == ch)
1519 break;
1520 }
1521
1522 wchar_t *dest = src - 1;
1523
1524 for (;;)
1525 {
1526 wchar_t c = *src++;
1527 if (c == 0)
1528 break;
1529 if (c != ch)
1530 *dest++ = c;
1531 }
1532
1533 *dest = 0;
1534 _len = (unsigned)(dest - _chars);
1535 }
1536
1537 // !!!!!!!!!!!!!!! test it if newChar = '\0'
Replace(wchar_t oldChar,wchar_t newChar)1538 void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
1539 {
1540 if (oldChar == newChar)
1541 return; // 0;
1542 // unsigned number = 0;
1543 int pos = 0;
1544 wchar_t *chars = _chars;
1545 while ((unsigned)pos < _len)
1546 {
1547 pos = Find(oldChar, (unsigned)pos);
1548 if (pos < 0)
1549 break;
1550 chars[(unsigned)pos] = newChar;
1551 pos++;
1552 // number++;
1553 }
1554 return; // number;
1555 }
1556
Replace(const UString & oldString,const UString & newString)1557 void UString::Replace(const UString &oldString, const UString &newString)
1558 {
1559 if (oldString.IsEmpty())
1560 return; // 0;
1561 if (oldString == newString)
1562 return; // 0;
1563 unsigned oldLen = oldString.Len();
1564 unsigned newLen = newString.Len();
1565 // unsigned number = 0;
1566 int pos = 0;
1567 while ((unsigned)pos < _len)
1568 {
1569 pos = Find(oldString, (unsigned)pos);
1570 if (pos < 0)
1571 break;
1572 Delete((unsigned)pos, oldLen);
1573 Insert((unsigned)pos, newString);
1574 pos += newLen;
1575 // number++;
1576 }
1577 // return number;
1578 }
1579
Delete(unsigned index)1580 void UString::Delete(unsigned index) throw()
1581 {
1582 MoveItems(index, index + 1);
1583 _len--;
1584 }
1585
Delete(unsigned index,unsigned count)1586 void UString::Delete(unsigned index, unsigned count) throw()
1587 {
1588 if (index + count > _len)
1589 count = _len - index;
1590 if (count > 0)
1591 {
1592 MoveItems(index, index + count);
1593 _len -= count;
1594 }
1595 }
1596
DeleteFrontal(unsigned num)1597 void UString::DeleteFrontal(unsigned num) throw()
1598 {
1599 if (num != 0)
1600 {
1601 MoveItems(0, num);
1602 _len -= num;
1603 }
1604 }
1605
1606
1607 // ---------- UString2 ----------
1608
ReAlloc2(unsigned newLimit)1609 void UString2::ReAlloc2(unsigned newLimit)
1610 {
1611 // wrong (_len) is allowed after this function
1612 CHECK_STRING_ALLOC_LEN(newLimit)
1613 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
1614 if (_chars)
1615 {
1616 MY_STRING_DELETE(_chars)
1617 _chars = NULL;
1618 // _len = 0;
1619 }
1620 _chars = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);
1621 _chars[0] = 0;
1622 // _len = newLimit;
1623 }
1624
SetStartLen(unsigned len)1625 void UString2::SetStartLen(unsigned len)
1626 {
1627 _chars = NULL;
1628 _chars = MY_STRING_NEW_wchar_t((size_t)len + 1);
1629 _len = len;
1630 }
1631
1632
1633 /*
1634 UString2::UString2(wchar_t c)
1635 {
1636 SetStartLen(1);
1637 wchar_t *chars = _chars;
1638 chars[0] = c;
1639 chars[1] = 0;
1640 }
1641 */
1642
UString2(const wchar_t * s)1643 UString2::UString2(const wchar_t *s)
1644 {
1645 const unsigned len = MyStringLen(s);
1646 SetStartLen(len);
1647 wmemcpy(_chars, s, len + 1);
1648 }
1649
UString2(const UString2 & s)1650 UString2::UString2(const UString2 &s): _chars(NULL), _len(0)
1651 {
1652 if (s._chars)
1653 {
1654 SetStartLen(s._len);
1655 wmemcpy(_chars, s._chars, s._len + 1);
1656 }
1657 }
1658
1659 /*
1660 UString2 &UString2::operator=(wchar_t c)
1661 {
1662 if (1 > _len)
1663 {
1664 wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
1665 if (_chars)
1666 MY_STRING_DELETE(_chars)
1667 _chars = newBuf;
1668 }
1669 _len = 1;
1670 wchar_t *chars = _chars;
1671 chars[0] = c;
1672 chars[1] = 0;
1673 return *this;
1674 }
1675 */
1676
operator =(const wchar_t * s)1677 UString2 &UString2::operator=(const wchar_t *s)
1678 {
1679 unsigned len = MyStringLen(s);
1680 if (len > _len)
1681 {
1682 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1683 if (_chars)
1684 MY_STRING_DELETE(_chars)
1685 _chars = newBuf;
1686 }
1687 _len = len;
1688 MyStringCopy(_chars, s);
1689 return *this;
1690 }
1691
SetFromAscii(const char * s)1692 void UString2::SetFromAscii(const char *s)
1693 {
1694 unsigned len = MyStringLen(s);
1695 if (len > _len)
1696 {
1697 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1698 if (_chars)
1699 MY_STRING_DELETE(_chars)
1700 _chars = newBuf;
1701 }
1702 wchar_t *chars = _chars;
1703 for (unsigned i = 0; i < len; i++)
1704 chars[i] = (unsigned char)s[i];
1705 chars[len] = 0;
1706 _len = len;
1707 }
1708
operator =(const UString2 & s)1709 UString2 &UString2::operator=(const UString2 &s)
1710 {
1711 if (&s == this)
1712 return *this;
1713 unsigned len = s._len;
1714 if (len > _len)
1715 {
1716 wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1717 if (_chars)
1718 MY_STRING_DELETE(_chars)
1719 _chars = newBuf;
1720 }
1721 _len = len;
1722 MyStringCopy(_chars, s._chars);
1723 return *this;
1724 }
1725
operator ==(const UString2 & s1,const UString2 & s2)1726 bool operator==(const UString2 &s1, const UString2 &s2)
1727 {
1728 return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);
1729 }
1730
operator ==(const UString2 & s1,const wchar_t * s2)1731 bool operator==(const UString2 &s1, const wchar_t *s2)
1732 {
1733 if (s1.IsEmpty())
1734 return (*s2 == 0);
1735 return wcscmp(s1.GetRawPtr(), s2) == 0;
1736 }
1737
operator ==(const wchar_t * s1,const UString2 & s2)1738 bool operator==(const wchar_t *s1, const UString2 &s2)
1739 {
1740 if (s2.IsEmpty())
1741 return (*s1 == 0);
1742 return wcscmp(s1, s2.GetRawPtr()) == 0;
1743 }
1744
1745
1746
1747 // ----------------------------------------
1748
1749 /*
1750 int MyStringCompareNoCase(const char *s1, const char *s2)
1751 {
1752 return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
1753 }
1754 */
1755
1756 #if !defined(USE_UNICODE_FSTRING) || !defined(_UNICODE)
1757
GetCurrentCodePage()1758 static inline UINT GetCurrentCodePage()
1759 {
1760 #if defined(UNDER_CE) || !defined(_WIN32)
1761 return CP_ACP;
1762 #else
1763 return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1764 #endif
1765 }
1766
1767 #endif
1768
1769 #ifdef USE_UNICODE_FSTRING
1770
1771 #ifndef _UNICODE
1772
fs2fas(CFSTR s)1773 AString fs2fas(CFSTR s)
1774 {
1775 return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1776 }
1777
fas2fs(const char * s)1778 FString fas2fs(const char *s)
1779 {
1780 return MultiByteToUnicodeString(s, GetCurrentCodePage());
1781 }
1782
fas2fs(const AString & s)1783 FString fas2fs(const AString &s)
1784 {
1785 return MultiByteToUnicodeString(s, GetCurrentCodePage());
1786 }
1787
1788 #endif // _UNICODE
1789
1790 #else // USE_UNICODE_FSTRING
1791
fs2us(const FChar * s)1792 UString fs2us(const FChar *s)
1793 {
1794 return MultiByteToUnicodeString(s, GetCurrentCodePage());
1795 }
1796
fs2us(const FString & s)1797 UString fs2us(const FString &s)
1798 {
1799 return MultiByteToUnicodeString(s, GetCurrentCodePage());
1800 }
1801
us2fs(const wchar_t * s)1802 FString us2fs(const wchar_t *s)
1803 {
1804 return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1805 }
1806
1807 #endif // USE_UNICODE_FSTRING
1808
1809
FindWord_In_LowCaseAsciiList_NoCase(const char * p,const wchar_t * str)1810 bool CStringFinder::FindWord_In_LowCaseAsciiList_NoCase(const char *p, const wchar_t *str)
1811 {
1812 _temp.Empty();
1813 for (;;)
1814 {
1815 const wchar_t c = *str++;
1816 if (c == 0)
1817 break;
1818 if (c <= 0x20 || c > 0x7f)
1819 return false;
1820 _temp.Add_Char((char)MyCharLower_Ascii((char)c));
1821 }
1822
1823 while (*p != 0)
1824 {
1825 const char *s2 = _temp.Ptr();
1826 char c, c2;
1827 do
1828 {
1829 c = *p++;
1830 c2 = *s2++;
1831 }
1832 while (c == c2);
1833
1834 if (c == ' ')
1835 {
1836 if (c2 == 0)
1837 return true;
1838 continue;
1839 }
1840
1841 while (*p++ != ' ');
1842 }
1843
1844 return false;
1845 }
1846
1847
SplitString(const UString & srcString,UStringVector & destStrings)1848 void SplitString(const UString &srcString, UStringVector &destStrings)
1849 {
1850 destStrings.Clear();
1851 unsigned len = srcString.Len();
1852 if (len == 0)
1853 return;
1854 UString s;
1855 for (unsigned i = 0; i < len; i++)
1856 {
1857 const wchar_t c = srcString[i];
1858 if (c == ' ')
1859 {
1860 if (!s.IsEmpty())
1861 {
1862 destStrings.Add(s);
1863 s.Empty();
1864 }
1865 }
1866 else
1867 s += c;
1868 }
1869 if (!s.IsEmpty())
1870 destStrings.Add(s);
1871 }
1872