xref: /third_party/lzma/CPP/Common/MyString.cpp (revision 370b324c)
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/*
23inline 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
37int 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
49int 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/*
61void MyStringUpper_Ascii(char *s) throw()
62{
63  for (;;)
64  {
65    char c = *s;
66    if (c == 0)
67      return;
68    *s++ = MyCharUpper_Ascii(c);
69  }
70}
71
72void MyStringUpper_Ascii(wchar_t *s) throw()
73{
74  for (;;)
75  {
76    wchar_t c = *s;
77    if (c == 0)
78      return;
79    *s++ = MyCharUpper_Ascii(c);
80  }
81}
82*/
83
84void MyStringLower_Ascii(char *s) throw()
85{
86  for (;;)
87  {
88    char c = *s;
89    if (c == 0)
90      return;
91    *s++ = MyCharLower_Ascii(c);
92  }
93}
94
95void MyStringLower_Ascii(wchar_t *s) throw()
96{
97  for (;;)
98  {
99    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
121wchar_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/*
138wchar_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/*
156wchar_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/*
171wchar_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
189bool IsString1PrefixedByString2(const char *s1, const char *s2) throw()
190{
191  for (;;)
192  {
193    const unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true;
194    const unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false;
195  }
196}
197
198bool 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
211bool 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
226bool 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
240bool 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
254bool 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
268bool 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
281bool 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
294bool 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
307bool 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
316bool 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
325bool 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
336bool 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
347bool 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
359int 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/*
377int 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
398void 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
406void AString::ReAlloc(unsigned newLimit)
407{
408  // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, (size_t)_len + 1);
409  char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1);
410  memcpy(newBuf, _chars, (size_t)_len + 1);
411  MY_STRING_DELETE(_chars)
412  _chars = newBuf;
413  _limit = newLimit;
414}
415
416void AString::ReAlloc2(unsigned newLimit)
417{
418  if (newLimit > k_Alloc_Len_Limit) throw 20130220;
419  // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, 0);
420  char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1);
421  newBuf[0] = 0;
422  MY_STRING_DELETE(_chars)
423  _chars = newBuf;
424  _limit = newLimit;
425  _len = 0;
426}
427
428void AString::SetStartLen(unsigned len)
429{
430  _chars = NULL;
431  _chars = MY_STRING_NEW_char((size_t)len + 1);
432  _len = len;
433  _limit = len;
434}
435
436void AString::Grow_1()
437{
438  unsigned next = _len;
439  next += next / 2;
440  next += 16;
441  next &= ~(unsigned)15;
442  next--;
443  if (next < _len || next > k_Alloc_Len_Limit)
444    next = k_Alloc_Len_Limit;
445  if (next <= _len)
446    throw 20130220;
447  ReAlloc(next);
448  // Grow(1);
449}
450
451void AString::Grow(unsigned n)
452{
453  const unsigned freeSize = _limit - _len;
454  if (n <= freeSize)
455    return;
456  unsigned next = _len + n;
457  next += next / 2;
458  next += 16;
459  next &= ~(unsigned)15;
460  next--;
461  if (next < _len || next > k_Alloc_Len_Limit)
462    next = k_Alloc_Len_Limit;
463  if (next <= _len || next - _len < n)
464    throw 20130220;
465  ReAlloc(next);
466}
467
468AString::AString(unsigned num, const char *s)
469{
470  unsigned len = MyStringLen(s);
471  if (num > len)
472    num = len;
473  SetStartLen(num);
474  memcpy(_chars, s, num);
475  _chars[num] = 0;
476}
477
478AString::AString(unsigned num, const AString &s)
479{
480  if (num > s._len)
481    num = s._len;
482  SetStartLen(num);
483  memcpy(_chars, s._chars, num);
484  _chars[num] = 0;
485}
486
487AString::AString(const AString &s, char c)
488{
489  SetStartLen(s.Len() + 1);
490  char *chars = _chars;
491  unsigned len = s.Len();
492  memcpy(chars, s, len);
493  chars[len] = c;
494  chars[(size_t)len + 1] = 0;
495}
496
497AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)
498{
499  SetStartLen(num1 + num2);
500  char *chars = _chars;
501  memcpy(chars, s1, num1);
502  memcpy(chars + num1, s2, num2 + 1);
503}
504
505AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }
506AString operator+(const AString &s1, const char    *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
507AString operator+(const char    *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }
508
509static const unsigned kStartStringCapacity = 4;
510
511AString::AString()
512{
513  _chars = NULL;
514  _chars = MY_STRING_NEW_char(kStartStringCapacity);
515  _len = 0;
516  _limit = kStartStringCapacity - 1;
517  _chars[0] = 0;
518}
519
520AString::AString(char c)
521{
522  SetStartLen(1);
523  char *chars = _chars;
524  chars[0] = c;
525  chars[1] = 0;
526}
527
528AString::AString(const char *s)
529{
530  SetStartLen(MyStringLen(s));
531  MyStringCopy(_chars, s);
532}
533
534AString::AString(const AString &s)
535{
536  SetStartLen(s._len);
537  MyStringCopy(_chars, s._chars);
538}
539
540AString &AString::operator=(char c)
541{
542  if (1 > _limit)
543  {
544    char *newBuf = MY_STRING_NEW_char(1 + 1);
545    MY_STRING_DELETE(_chars)
546    _chars = newBuf;
547    _limit = 1;
548  }
549  _len = 1;
550  char *chars = _chars;
551  chars[0] = c;
552  chars[1] = 0;
553  return *this;
554}
555
556AString &AString::operator=(const char *s)
557{
558  unsigned len = MyStringLen(s);
559  if (len > _limit)
560  {
561    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
562    MY_STRING_DELETE(_chars)
563    _chars = newBuf;
564    _limit = len;
565  }
566  _len = len;
567  MyStringCopy(_chars, s);
568  return *this;
569}
570
571AString &AString::operator=(const AString &s)
572{
573  if (&s == this)
574    return *this;
575  unsigned len = s._len;
576  if (len > _limit)
577  {
578    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
579    MY_STRING_DELETE(_chars)
580    _chars = newBuf;
581    _limit = len;
582  }
583  _len = len;
584  MyStringCopy(_chars, s._chars);
585  return *this;
586}
587
588void AString::SetFromWStr_if_Ascii(const wchar_t *s)
589{
590  unsigned len = 0;
591  {
592    for (;; len++)
593    {
594      wchar_t c = s[len];
595      if (c == 0)
596        break;
597      if (c >= 0x80)
598        return;
599    }
600  }
601  if (len > _limit)
602  {
603    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
604    MY_STRING_DELETE(_chars)
605    _chars = newBuf;
606    _limit = len;
607  }
608  _len = len;
609  char *dest = _chars;
610  unsigned i;
611  for (i = 0; i < len; i++)
612    dest[i] = (char)s[i];
613  dest[i] = 0;
614}
615
616/*
617void AString::SetFromBstr_if_Ascii(BSTR s)
618{
619  unsigned len = ::SysStringLen(s);
620  {
621    for (unsigned i = 0; i < len; i++)
622      if (s[i] <= 0 || s[i] >= 0x80)
623        return;
624  }
625  if (len > _limit)
626  {
627    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
628    MY_STRING_DELETE(_chars)
629    _chars = newBuf;
630    _limit = len;
631  }
632  _len = len;
633  char *dest = _chars;
634  unsigned i;
635  for (i = 0; i < len; i++)
636    dest[i] = (char)s[i];
637  dest[i] = 0;
638}
639*/
640
641void AString::Add_Space() { operator+=(' '); }
642void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
643void AString::Add_LF() { operator+=('\n'); }
644void AString::Add_Slash() { operator+=('/'); }
645void AString::Add_Dot() { operator+=('.'); }
646void AString::Add_Minus() { operator+=('-'); }
647
648AString &AString::operator+=(const char *s)
649{
650  unsigned len = MyStringLen(s);
651  Grow(len);
652  MyStringCopy(_chars + _len, s);
653  _len += len;
654  return *this;
655}
656
657void AString::Add_OptSpaced(const char *s)
658{
659  Add_Space_if_NotEmpty();
660  (*this) += s;
661}
662
663AString &AString::operator+=(const AString &s)
664{
665  Grow(s._len);
666  MyStringCopy(_chars + _len, s._chars);
667  _len += s._len;
668  return *this;
669}
670
671void AString::Add_UInt32(UInt32 v)
672{
673  Grow(10);
674  _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);
675}
676
677void UString::Add_UInt64(UInt64 v)
678{
679  Grow(20);
680  _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);
681}
682
683void AString::AddFrom(const char *s, unsigned len) // no check
684{
685  if (len != 0)
686  {
687    Grow(len);
688    memcpy(_chars + _len, s, len);
689    len += _len;
690    _chars[len] = 0;
691    _len = len;
692  }
693}
694
695void AString::SetFrom(const char *s, unsigned len) // no check
696{
697  if (len > _limit)
698  {
699    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);
700    MY_STRING_DELETE(_chars)
701    _chars = newBuf;
702    _limit = len;
703  }
704  if (len != 0)
705    memcpy(_chars, s, len);
706  _chars[len] = 0;
707  _len = len;
708}
709
710void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check
711{
712  unsigned i;
713  for (i = 0; i < len; i++)
714    if (s[i] == 0)
715      break;
716  SetFrom(s, i);
717}
718
719int AString::Find(const char *s, unsigned startIndex) const throw()
720{
721  const char *fs = strstr(_chars + startIndex, s);
722  if (!fs)
723    return -1;
724  return (int)(fs - _chars);
725
726  /*
727  if (s[0] == 0)
728    return startIndex;
729  unsigned len = MyStringLen(s);
730  const char *p = _chars + startIndex;
731  for (;; p++)
732  {
733    const char c = *p;
734    if (c != s[0])
735    {
736      if (c == 0)
737        return -1;
738      continue;
739    }
740    unsigned i;
741    for (i = 1; i < len; i++)
742      if (p[i] != s[i])
743        break;
744    if (i == len)
745      return (int)(p - _chars);
746  }
747  */
748}
749
750int AString::ReverseFind(char c) const throw()
751{
752  if (_len == 0)
753    return -1;
754  const char *p = _chars + _len - 1;
755  for (;;)
756  {
757    if (*p == c)
758      return (int)(p - _chars);
759    if (p == _chars)
760      return -1;
761    p--; // p = GetPrevCharPointer(_chars, p);
762  }
763}
764
765int AString::ReverseFind_PathSepar() const throw()
766{
767  if (_len == 0)
768    return -1;
769  const char *p = _chars + _len - 1;
770  for (;;)
771  {
772    const char c = *p;
773    if (IS_PATH_SEPAR(c))
774      return (int)(p - _chars);
775    if (p == _chars)
776      return -1;
777    p--;
778  }
779}
780
781void AString::TrimLeft() throw()
782{
783  const char *p = _chars;
784  for (;; p++)
785  {
786    char c = *p;
787    if (c != ' ' && c != '\n' && c != '\t')
788      break;
789  }
790  unsigned pos = (unsigned)(p - _chars);
791  if (pos != 0)
792  {
793    MoveItems(0, pos);
794    _len -= pos;
795  }
796}
797
798void AString::TrimRight() throw()
799{
800  const char *p = _chars;
801  unsigned i;
802  for (i = _len; i != 0; i--)
803  {
804    char c = p[(size_t)i - 1];
805    if (c != ' ' && c != '\n' && c != '\t')
806      break;
807  }
808  if (i != _len)
809  {
810    _chars[i] = 0;
811    _len = i;
812  }
813}
814
815void AString::InsertAtFront(char c)
816{
817  if (_limit == _len)
818    Grow_1();
819  MoveItems(1, 0);
820  _chars[0] = c;
821  _len++;
822}
823
824/*
825void AString::Insert(unsigned index, char c)
826{
827  InsertSpace(index, 1);
828  _chars[index] = c;
829  _len++;
830}
831*/
832
833void AString::Insert(unsigned index, const char *s)
834{
835  unsigned num = MyStringLen(s);
836  if (num != 0)
837  {
838    InsertSpace(index, num);
839    memcpy(_chars + index, s, num);
840    _len += num;
841  }
842}
843
844void AString::Insert(unsigned index, const AString &s)
845{
846  unsigned num = s.Len();
847  if (num != 0)
848  {
849    InsertSpace(index, num);
850    memcpy(_chars + index, s, num);
851    _len += num;
852  }
853}
854
855void AString::RemoveChar(char ch) throw()
856{
857  char *src = _chars;
858
859  for (;;)
860  {
861    char c = *src++;
862    if (c == 0)
863      return;
864    if (c == ch)
865      break;
866  }
867
868  char *dest = src - 1;
869
870  for (;;)
871  {
872    char c = *src++;
873    if (c == 0)
874      break;
875    if (c != ch)
876      *dest++ = c;
877  }
878
879  *dest = 0;
880  _len = (unsigned)(dest - _chars);
881}
882
883// !!!!!!!!!!!!!!! test it if newChar = '\0'
884void AString::Replace(char oldChar, char newChar) throw()
885{
886  if (oldChar == newChar)
887    return; // 0;
888  // unsigned number = 0;
889  int pos = 0;
890  char *chars = _chars;
891  while ((unsigned)pos < _len)
892  {
893    pos = Find(oldChar, (unsigned)pos);
894    if (pos < 0)
895      break;
896    chars[(unsigned)pos] = newChar;
897    pos++;
898    // number++;
899  }
900  return; //  number;
901}
902
903void AString::Replace(const AString &oldString, const AString &newString)
904{
905  if (oldString.IsEmpty())
906    return; // 0;
907  if (oldString == newString)
908    return; // 0;
909  unsigned oldLen = oldString.Len();
910  unsigned newLen = newString.Len();
911  // unsigned number = 0;
912  int pos = 0;
913  while ((unsigned)pos < _len)
914  {
915    pos = Find(oldString, (unsigned)pos);
916    if (pos < 0)
917      break;
918    Delete((unsigned)pos, oldLen);
919    Insert((unsigned)pos, newString);
920    pos += newLen;
921    // number++;
922  }
923  // return number;
924}
925
926void AString::Delete(unsigned index) throw()
927{
928  MoveItems(index, index + 1);
929  _len--;
930}
931
932void AString::Delete(unsigned index, unsigned count) throw()
933{
934  if (index + count > _len)
935    count = _len - index;
936  if (count > 0)
937  {
938    MoveItems(index, index + count);
939    _len -= count;
940  }
941}
942
943void AString::DeleteFrontal(unsigned num) throw()
944{
945  if (num != 0)
946  {
947    MoveItems(0, num);
948    _len -= num;
949  }
950}
951
952/*
953AString operator+(const AString &s1, const AString &s2)
954{
955  AString result(s1);
956  result += s2;
957  return result;
958}
959
960AString operator+(const AString &s, const char *chars)
961{
962  AString result(s);
963  result += chars;
964  return result;
965}
966
967AString operator+(const char *chars, const AString &s)
968{
969  AString result(chars);
970  result += s;
971  return result;
972}
973
974AString operator+(const AString &s, char c)
975{
976  AString result(s);
977  result += c;
978  return result;
979}
980*/
981
982/*
983AString operator+(char c, const AString &s)
984{
985  AString result(c);
986  result += s;
987  return result;
988}
989*/
990
991
992
993
994// ---------- UString ----------
995
996void UString::InsertSpace(unsigned index, unsigned size)
997{
998  Grow(size);
999  MoveItems(index + size, index);
1000}
1001
1002void UString::ReAlloc(unsigned newLimit)
1003{
1004  // MY_STRING_REALLOC(_chars, wchar_t, (size_t)newLimit + 1, (size_t)_len + 1);
1005  wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);
1006  wmemcpy(newBuf, _chars, _len + 1);
1007  MY_STRING_DELETE(_chars)
1008  _chars = newBuf;
1009  _limit = newLimit;
1010}
1011
1012void UString::ReAlloc2(unsigned newLimit)
1013{
1014  if (newLimit > k_Alloc_Len_Limit) throw 20130221;
1015  // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
1016  wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);
1017  newBuf[0] = 0;
1018  MY_STRING_DELETE(_chars)
1019  _chars = newBuf;
1020  _limit = newLimit;
1021  _len = 0;
1022}
1023
1024void UString::SetStartLen(unsigned len)
1025{
1026  _chars = NULL;
1027  _chars = MY_STRING_NEW_wchar_t((size_t)len + 1);
1028  _len = len;
1029  _limit = len;
1030}
1031
1032void UString::Grow_1()
1033{
1034  unsigned next = _len;
1035  next += next / 2;
1036  next += 16;
1037  next &= ~(unsigned)15;
1038  next--;
1039  if (next < _len || next > k_Alloc_Len_Limit)
1040    next = k_Alloc_Len_Limit;
1041  if (next <= _len)
1042    throw 20130220;
1043  ReAlloc(next);
1044}
1045
1046void UString::Grow(unsigned n)
1047{
1048  const unsigned freeSize = _limit - _len;
1049  if (n <= freeSize)
1050    return;
1051  unsigned next = _len + n;
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 || next - _len < n)
1059    throw 20130220;
1060  ReAlloc(next - 1);
1061}
1062
1063
1064UString::UString(unsigned num, const wchar_t *s)
1065{
1066  unsigned len = MyStringLen(s);
1067  if (num > len)
1068    num = len;
1069  SetStartLen(num);
1070  wmemcpy(_chars, s, num);
1071  _chars[num] = 0;
1072}
1073
1074
1075UString::UString(unsigned num, const UString &s)
1076{
1077  if (num > s._len)
1078    num = s._len;
1079  SetStartLen(num);
1080  wmemcpy(_chars, s._chars, num);
1081  _chars[num] = 0;
1082}
1083
1084UString::UString(const UString &s, wchar_t c)
1085{
1086  SetStartLen(s.Len() + 1);
1087  wchar_t *chars = _chars;
1088  unsigned len = s.Len();
1089  wmemcpy(chars, s, len);
1090  chars[len] = c;
1091  chars[(size_t)len + 1] = 0;
1092}
1093
1094UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)
1095{
1096  SetStartLen(num1 + num2);
1097  wchar_t *chars = _chars;
1098  wmemcpy(chars, s1, num1);
1099  wmemcpy(chars + num1, s2, num2 + 1);
1100}
1101
1102UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }
1103UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); }
1104UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }
1105
1106UString::UString()
1107{
1108  _chars = NULL;
1109  _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity);
1110  _len = 0;
1111  _limit = kStartStringCapacity - 1;
1112  _chars[0] = 0;
1113}
1114
1115UString::UString(wchar_t c)
1116{
1117  SetStartLen(1);
1118  wchar_t *chars = _chars;
1119  chars[0] = c;
1120  chars[1] = 0;
1121}
1122
1123UString::UString(char c)
1124{
1125  SetStartLen(1);
1126  wchar_t *chars = _chars;
1127  chars[0] = (unsigned char)c;
1128  chars[1] = 0;
1129}
1130
1131UString::UString(const wchar_t *s)
1132{
1133  const unsigned len = MyStringLen(s);
1134  SetStartLen(len);
1135  wmemcpy(_chars, s, len + 1);
1136}
1137
1138UString::UString(const char *s)
1139{
1140  const unsigned len = MyStringLen(s);
1141  SetStartLen(len);
1142  wchar_t *chars = _chars;
1143  for (unsigned i = 0; i < len; i++)
1144    chars[i] = (unsigned char)s[i];
1145  chars[len] = 0;
1146}
1147
1148UString::UString(const AString &s)
1149{
1150  const unsigned len = s.Len();
1151  SetStartLen(len);
1152  wchar_t *chars = _chars;
1153  const char *s2 = s.Ptr();
1154  for (unsigned i = 0; i < len; i++)
1155    chars[i] = (unsigned char)s2[i];
1156  chars[len] = 0;
1157}
1158
1159UString::UString(const UString &s)
1160{
1161  SetStartLen(s._len);
1162  wmemcpy(_chars, s._chars, s._len + 1);
1163}
1164
1165UString &UString::operator=(wchar_t c)
1166{
1167  if (1 > _limit)
1168  {
1169    wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
1170    MY_STRING_DELETE(_chars)
1171    _chars = newBuf;
1172    _limit = 1;
1173  }
1174  _len = 1;
1175  wchar_t *chars = _chars;
1176  chars[0] = c;
1177  chars[1] = 0;
1178  return *this;
1179}
1180
1181UString &UString::operator=(const wchar_t *s)
1182{
1183  unsigned len = MyStringLen(s);
1184  if (len > _limit)
1185  {
1186    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1187    MY_STRING_DELETE(_chars)
1188    _chars = newBuf;
1189    _limit = len;
1190  }
1191  _len = len;
1192  wmemcpy(_chars, s, len + 1);
1193  return *this;
1194}
1195
1196UString &UString::operator=(const UString &s)
1197{
1198  if (&s == this)
1199    return *this;
1200  unsigned len = s._len;
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._chars, len + 1);
1210  return *this;
1211}
1212
1213void UString::SetFrom(const wchar_t *s, unsigned len) // no check
1214{
1215  if (len > _limit)
1216  {
1217    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1218    MY_STRING_DELETE(_chars)
1219    _chars = newBuf;
1220    _limit = len;
1221  }
1222  if (len != 0)
1223    wmemcpy(_chars, s, len);
1224  _chars[len] = 0;
1225  _len = len;
1226}
1227
1228void UString::SetFromBstr(LPCOLESTR s)
1229{
1230  unsigned len = ::SysStringLen((BSTR)(void *)(s));
1231
1232  /*
1233  #if WCHAR_MAX > 0xffff
1234  size_t num_wchars = 0;
1235  for (size_t i = 0; i < len;)
1236  {
1237    wchar_t c = s[i++];
1238    if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1239    {
1240      wchar_t c2 = s[i];
1241      if (c2 >= 0xdc00 && c2 < 0x10000)
1242      {
1243        c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1244        i++;
1245      }
1246    }
1247    num_wchars++;
1248  }
1249  len = num_wchars;
1250  #endif
1251  */
1252
1253  if (len > _limit)
1254  {
1255    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1256    MY_STRING_DELETE(_chars)
1257    _chars = newBuf;
1258    _limit = len;
1259  }
1260  _len = len;
1261
1262  /*
1263  #if WCHAR_MAX > 0xffff
1264
1265  wchar_t *chars = _chars;
1266  for (size_t i = 0; i <= len; i++)
1267  {
1268    wchar_t c = *s++;
1269    if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1270    {
1271      wchar_t c2 = *s;
1272      if (c2 >= 0xdc00 && c2 < 0x10000)
1273      {
1274        s++;
1275        c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1276      }
1277    }
1278    chars[i] = c;
1279  }
1280
1281  #else
1282  */
1283
1284  // if (s)
1285    wmemcpy(_chars, s, len + 1);
1286
1287  // #endif
1288}
1289
1290UString &UString::operator=(const char *s)
1291{
1292  unsigned len = MyStringLen(s);
1293  if (len > _limit)
1294  {
1295    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1296    MY_STRING_DELETE(_chars)
1297    _chars = newBuf;
1298    _limit = len;
1299  }
1300  wchar_t *chars = _chars;
1301  for (unsigned i = 0; i < len; i++)
1302    chars[i] = (unsigned char)s[i];
1303  chars[len] = 0;
1304  _len = len;
1305  return *this;
1306}
1307
1308void UString::Add_Dot() { operator+=(L'.'); }
1309void UString::Add_Space() { operator+=(L' '); }
1310void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
1311
1312void UString::Add_LF()
1313{
1314  if (_limit == _len)
1315    Grow_1();
1316  unsigned len = _len;
1317  wchar_t *chars = _chars;
1318  chars[len++] = L'\n';
1319  chars[len] = 0;
1320  _len = len;
1321}
1322
1323UString &UString::operator+=(const wchar_t *s)
1324{
1325  unsigned len = MyStringLen(s);
1326  Grow(len);
1327  wmemcpy(_chars + _len, s, len + 1);
1328  _len += len;
1329  return *this;
1330}
1331
1332UString &UString::operator+=(const UString &s)
1333{
1334  Grow(s._len);
1335  wmemcpy(_chars + _len, s._chars, s._len + 1);
1336  _len += s._len;
1337  return *this;
1338}
1339
1340UString &UString::operator+=(const char *s)
1341{
1342  unsigned len = MyStringLen(s);
1343  Grow(len);
1344  wchar_t *chars = _chars + _len;
1345  for (unsigned i = 0; i < len; i++)
1346    chars[i] = (unsigned char)s[i];
1347  chars[len] = 0;
1348  _len += len;
1349  return *this;
1350}
1351
1352
1353void UString::Add_UInt32(UInt32 v)
1354{
1355  Grow(10);
1356  _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);
1357}
1358
1359void AString::Add_UInt64(UInt64 v)
1360{
1361  Grow(20);
1362  _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);
1363}
1364
1365
1366int UString::Find(const wchar_t *s, unsigned startIndex) const throw()
1367{
1368  const wchar_t *fs = wcsstr(_chars + startIndex, s);
1369  if (!fs)
1370    return -1;
1371  return (int)(fs - _chars);
1372
1373  /*
1374  if (s[0] == 0)
1375    return startIndex;
1376  unsigned len = MyStringLen(s);
1377  const wchar_t *p = _chars + startIndex;
1378  for (;; p++)
1379  {
1380    const wchar_t c = *p;
1381    if (c != s[0])
1382    {
1383      if (c == 0)
1384        return -1;
1385      continue;
1386    }
1387    unsigned i;
1388    for (i = 1; i < len; i++)
1389      if (p[i] != s[i])
1390        break;
1391    if (i == len)
1392      return (int)(p - _chars);
1393  }
1394  */
1395}
1396
1397int UString::ReverseFind(wchar_t c) const throw()
1398{
1399  if (_len == 0)
1400    return -1;
1401  const wchar_t *p = _chars + _len;
1402  do
1403  {
1404    if (*(--p) == c)
1405      return (int)(p - _chars);
1406  }
1407  while (p != _chars);
1408  return -1;
1409}
1410
1411int UString::ReverseFind_PathSepar() const throw()
1412{
1413  const wchar_t *p = _chars + _len;
1414  while (p != _chars)
1415  {
1416    const wchar_t c = *(--p);
1417    if (IS_PATH_SEPAR(c))
1418      return (int)(p - _chars);
1419  }
1420  return -1;
1421}
1422
1423void UString::TrimLeft() throw()
1424{
1425  const wchar_t *p = _chars;
1426  for (;; p++)
1427  {
1428    wchar_t c = *p;
1429    if (c != ' ' && c != '\n' && c != '\t')
1430      break;
1431  }
1432  unsigned pos = (unsigned)(p - _chars);
1433  if (pos != 0)
1434  {
1435    MoveItems(0, pos);
1436    _len -= pos;
1437  }
1438}
1439
1440void UString::TrimRight() throw()
1441{
1442  const wchar_t *p = _chars;
1443  unsigned i;
1444  for (i = _len; i != 0; i--)
1445  {
1446    wchar_t c = p[(size_t)i - 1];
1447    if (c != ' ' && c != '\n' && c != '\t')
1448      break;
1449  }
1450  if (i != _len)
1451  {
1452    _chars[i] = 0;
1453    _len = i;
1454  }
1455}
1456
1457void UString::InsertAtFront(wchar_t c)
1458{
1459  if (_limit == _len)
1460    Grow_1();
1461  MoveItems(1, 0);
1462  _chars[0] = c;
1463  _len++;
1464}
1465
1466/*
1467void UString::Insert_wchar_t(unsigned index, wchar_t c)
1468{
1469  InsertSpace(index, 1);
1470  _chars[index] = c;
1471  _len++;
1472}
1473*/
1474
1475void UString::Insert(unsigned index, const wchar_t *s)
1476{
1477  unsigned num = MyStringLen(s);
1478  if (num != 0)
1479  {
1480    InsertSpace(index, num);
1481    wmemcpy(_chars + index, s, num);
1482    _len += num;
1483  }
1484}
1485
1486void UString::Insert(unsigned index, const UString &s)
1487{
1488  unsigned num = s.Len();
1489  if (num != 0)
1490  {
1491    InsertSpace(index, num);
1492    wmemcpy(_chars + index, s, num);
1493    _len += num;
1494  }
1495}
1496
1497void UString::RemoveChar(wchar_t ch) throw()
1498{
1499  wchar_t *src = _chars;
1500
1501  for (;;)
1502  {
1503    wchar_t c = *src++;
1504    if (c == 0)
1505      return;
1506    if (c == ch)
1507      break;
1508  }
1509
1510  wchar_t *dest = src - 1;
1511
1512  for (;;)
1513  {
1514    wchar_t c = *src++;
1515    if (c == 0)
1516      break;
1517    if (c != ch)
1518      *dest++ = c;
1519  }
1520
1521  *dest = 0;
1522  _len = (unsigned)(dest - _chars);
1523}
1524
1525// !!!!!!!!!!!!!!! test it if newChar = '\0'
1526void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
1527{
1528  if (oldChar == newChar)
1529    return; // 0;
1530  // unsigned number = 0;
1531  int pos = 0;
1532  wchar_t *chars = _chars;
1533  while ((unsigned)pos < _len)
1534  {
1535    pos = Find(oldChar, (unsigned)pos);
1536    if (pos < 0)
1537      break;
1538    chars[(unsigned)pos] = newChar;
1539    pos++;
1540    // number++;
1541  }
1542  return; //  number;
1543}
1544
1545void UString::Replace(const UString &oldString, const UString &newString)
1546{
1547  if (oldString.IsEmpty())
1548    return; // 0;
1549  if (oldString == newString)
1550    return; // 0;
1551  unsigned oldLen = oldString.Len();
1552  unsigned newLen = newString.Len();
1553  // unsigned number = 0;
1554  int pos = 0;
1555  while ((unsigned)pos < _len)
1556  {
1557    pos = Find(oldString, (unsigned)pos);
1558    if (pos < 0)
1559      break;
1560    Delete((unsigned)pos, oldLen);
1561    Insert((unsigned)pos, newString);
1562    pos += newLen;
1563    // number++;
1564  }
1565  // return number;
1566}
1567
1568void UString::Delete(unsigned index) throw()
1569{
1570  MoveItems(index, index + 1);
1571  _len--;
1572}
1573
1574void UString::Delete(unsigned index, unsigned count) throw()
1575{
1576  if (index + count > _len)
1577    count = _len - index;
1578  if (count > 0)
1579  {
1580    MoveItems(index, index + count);
1581    _len -= count;
1582  }
1583}
1584
1585void UString::DeleteFrontal(unsigned num) throw()
1586{
1587  if (num != 0)
1588  {
1589    MoveItems(0, num);
1590    _len -= num;
1591  }
1592}
1593
1594
1595// ---------- UString2 ----------
1596
1597void UString2::ReAlloc2(unsigned newLimit)
1598{
1599  // wrong (_len) is allowed after this function
1600  if (newLimit > k_Alloc_Len_Limit) throw 20130221;
1601  // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
1602  if (_chars)
1603  {
1604    MY_STRING_DELETE(_chars)
1605    _chars = NULL;
1606    // _len = 0;
1607  }
1608  _chars = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);
1609  _chars[0] = 0;
1610  // _len = newLimit;
1611}
1612
1613void UString2::SetStartLen(unsigned len)
1614{
1615  _chars = NULL;
1616  _chars = MY_STRING_NEW_wchar_t((size_t)len + 1);
1617  _len = len;
1618}
1619
1620
1621/*
1622UString2::UString2(wchar_t c)
1623{
1624  SetStartLen(1);
1625  wchar_t *chars = _chars;
1626  chars[0] = c;
1627  chars[1] = 0;
1628}
1629*/
1630
1631UString2::UString2(const wchar_t *s)
1632{
1633  const unsigned len = MyStringLen(s);
1634  SetStartLen(len);
1635  wmemcpy(_chars, s, len + 1);
1636}
1637
1638UString2::UString2(const UString2 &s): _chars(NULL), _len(0)
1639{
1640  if (s._chars)
1641  {
1642    SetStartLen(s._len);
1643    wmemcpy(_chars, s._chars, s._len + 1);
1644  }
1645}
1646
1647/*
1648UString2 &UString2::operator=(wchar_t c)
1649{
1650  if (1 > _len)
1651  {
1652    wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
1653    if (_chars)
1654      MY_STRING_DELETE(_chars)
1655    _chars = newBuf;
1656  }
1657  _len = 1;
1658  wchar_t *chars = _chars;
1659  chars[0] = c;
1660  chars[1] = 0;
1661  return *this;
1662}
1663*/
1664
1665UString2 &UString2::operator=(const wchar_t *s)
1666{
1667  unsigned len = MyStringLen(s);
1668  if (len > _len)
1669  {
1670    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1671    if (_chars)
1672      MY_STRING_DELETE(_chars)
1673    _chars = newBuf;
1674  }
1675  _len = len;
1676  MyStringCopy(_chars, s);
1677  return *this;
1678}
1679
1680void UString2::SetFromAscii(const char *s)
1681{
1682  unsigned len = MyStringLen(s);
1683  if (len > _len)
1684  {
1685    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1686    if (_chars)
1687      MY_STRING_DELETE(_chars)
1688    _chars = newBuf;
1689  }
1690  wchar_t *chars = _chars;
1691  for (unsigned i = 0; i < len; i++)
1692    chars[i] = (unsigned char)s[i];
1693  chars[len] = 0;
1694  _len = len;
1695}
1696
1697UString2 &UString2::operator=(const UString2 &s)
1698{
1699  if (&s == this)
1700    return *this;
1701  unsigned len = s._len;
1702  if (len > _len)
1703  {
1704    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);
1705    if (_chars)
1706      MY_STRING_DELETE(_chars)
1707    _chars = newBuf;
1708  }
1709  _len = len;
1710  MyStringCopy(_chars, s._chars);
1711  return *this;
1712}
1713
1714bool operator==(const UString2 &s1, const UString2 &s2)
1715{
1716  return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);
1717}
1718
1719bool operator==(const UString2 &s1, const wchar_t *s2)
1720{
1721  if (s1.IsEmpty())
1722    return (*s2 == 0);
1723  return wcscmp(s1.GetRawPtr(), s2) == 0;
1724}
1725
1726bool operator==(const wchar_t *s1, const UString2 &s2)
1727{
1728  if (s2.IsEmpty())
1729    return (*s1 == 0);
1730  return wcscmp(s1, s2.GetRawPtr()) == 0;
1731}
1732
1733
1734
1735// ----------------------------------------
1736
1737/*
1738int MyStringCompareNoCase(const char *s1, const char *s2)
1739{
1740  return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
1741}
1742*/
1743
1744#if !defined(USE_UNICODE_FSTRING) || !defined(_UNICODE)
1745
1746static inline UINT GetCurrentCodePage()
1747{
1748  #if defined(UNDER_CE) || !defined(_WIN32)
1749  return CP_ACP;
1750  #else
1751  return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1752  #endif
1753}
1754
1755#endif
1756
1757#ifdef USE_UNICODE_FSTRING
1758
1759#ifndef _UNICODE
1760
1761AString fs2fas(CFSTR s)
1762{
1763  return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1764}
1765
1766FString fas2fs(const char *s)
1767{
1768  return MultiByteToUnicodeString(s, GetCurrentCodePage());
1769}
1770
1771FString fas2fs(const AString &s)
1772{
1773  return MultiByteToUnicodeString(s, GetCurrentCodePage());
1774}
1775
1776#endif //  _UNICODE
1777
1778#else // USE_UNICODE_FSTRING
1779
1780UString fs2us(const FChar *s)
1781{
1782  return MultiByteToUnicodeString(s, GetCurrentCodePage());
1783}
1784
1785UString fs2us(const FString &s)
1786{
1787  return MultiByteToUnicodeString(s, GetCurrentCodePage());
1788}
1789
1790FString us2fs(const wchar_t *s)
1791{
1792  return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1793}
1794
1795#endif // USE_UNICODE_FSTRING
1796
1797
1798bool CStringFinder::FindWord_In_LowCaseAsciiList_NoCase(const char *p, const wchar_t *str)
1799{
1800  _temp.Empty();
1801  for (;;)
1802  {
1803    const wchar_t c = *str++;
1804    if (c == 0)
1805      break;
1806    if (c <= 0x20 || c > 0x7f)
1807      return false;
1808    _temp += (char)MyCharLower_Ascii((char)c);
1809  }
1810
1811  while (*p != 0)
1812  {
1813    const char *s2 = _temp.Ptr();
1814    char c, c2;
1815    do
1816    {
1817      c = *p++;
1818      c2 = *s2++;
1819    }
1820    while (c == c2);
1821
1822    if (c == ' ')
1823    {
1824      if (c2 == 0)
1825        return true;
1826      continue;
1827    }
1828
1829    while (*p++ != ' ');
1830  }
1831
1832  return false;
1833}
1834
1835
1836void SplitString(const UString &srcString, UStringVector &destStrings)
1837{
1838  destStrings.Clear();
1839  unsigned len = srcString.Len();
1840  if (len == 0)
1841    return;
1842  UString s;
1843  for (unsigned i = 0; i < len; i++)
1844  {
1845    const wchar_t c = srcString[i];
1846    if (c == ' ')
1847    {
1848      if (!s.IsEmpty())
1849      {
1850        destStrings.Add(s);
1851        s.Empty();
1852      }
1853    }
1854    else
1855      s += c;
1856  }
1857  if (!s.IsEmpty())
1858    destStrings.Add(s);
1859}
1860