1// Common/String.h
2
3#ifndef __COMMON_STRING_H
4#define __COMMON_STRING_H
5
6#include <string.h>
7
8#ifndef _WIN32
9#include <wctype.h>
10#include <wchar.h>
11#endif
12
13#include "MyTypes.h"
14#include "MyVector.h"
15
16inline unsigned MyStringLen(const char *s)
17{
18  unsigned i;
19  for (i = 0; s[i] != 0; i++);
20  return i;
21}
22
23inline void MyStringCopy(char *dest, const char *src)
24{
25  while ((*dest++ = *src++) != 0);
26}
27
28inline char *MyStpCpy(char *dest, const char *src)
29{
30  for (;;)
31  {
32    char c = *src;
33    *dest = c;
34    if (c == 0)
35      return dest;
36    src++;
37    dest++;
38  }
39}
40
41inline unsigned MyStringLen(const wchar_t *s)
42{
43  unsigned i;
44  for (i = 0; s[i] != 0; i++);
45  return i;
46}
47
48inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
49{
50  while ((*dest++ = *src++) != 0);
51}
52
53int FindCharPosInString(const char *s, char c) throw();
54int FindCharPosInString(const wchar_t *s, wchar_t c) throw();
55
56#ifdef _WIN32
57  #ifndef _UNICODE
58    #define STRING_UNICODE_THROW
59  #endif
60#endif
61
62#ifndef STRING_UNICODE_THROW
63  #define STRING_UNICODE_THROW throw()
64#endif
65
66/*
67inline char MyCharUpper_Ascii(char c)
68{
69  if (c >= 'a' && c <= 'z')
70    return (char)(c - 0x20);
71  return c;
72}
73inline wchar_t MyCharUpper_Ascii(wchar_t c)
74{
75  if (c >= 'a' && c <= 'z')
76    return (wchar_t)(c - 0x20);
77  return c;
78}
79*/
80
81inline char MyCharLower_Ascii(char c)
82{
83  if (c >= 'A' && c <= 'Z')
84    return (char)(c + 0x20);
85  return c;
86}
87
88inline wchar_t MyCharLower_Ascii(wchar_t c)
89{
90  if (c >= 'A' && c <= 'Z')
91    return (wchar_t)(c + 0x20);
92  return c;
93}
94
95wchar_t MyCharUpper_WIN(wchar_t c) throw();
96
97inline wchar_t MyCharUpper(wchar_t c) throw()
98{
99  if (c < 'a') return c;
100  if (c <= 'z') return (wchar_t)(c - 0x20);
101  if (c <= 0x7F) return c;
102  #ifdef _WIN32
103    #ifdef _UNICODE
104      return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
105    #else
106      return (wchar_t)MyCharUpper_WIN(c);
107    #endif
108  #else
109    return (wchar_t)towupper(c);
110  #endif
111}
112
113/*
114wchar_t MyCharLower_WIN(wchar_t c) throw();
115
116inline wchar_t MyCharLower(wchar_t c) throw()
117{
118  if (c < 'A') return c;
119  if (c <= 'Z') return (wchar_t)(c + 0x20);
120  if (c <= 0x7F) return c;
121  #ifdef _WIN32
122    #ifdef _UNICODE
123      return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
124    #else
125      return (wchar_t)MyCharLower_WIN(c);
126    #endif
127  #else
128    return (wchar_t)tolower(c);
129  #endif
130}
131*/
132
133// char *MyStringUpper(char *s) throw();
134// char *MyStringLower(char *s) throw();
135
136// void MyStringUpper_Ascii(wchar_t *s) throw();
137void MyStringLower_Ascii(wchar_t *s) throw();
138// wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW;
139// wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW;
140
141bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
142
143bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
144bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
145
146int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();
147int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();
148
149// ---------- ASCII ----------
150// char values in ASCII strings must be less then 128
151bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();
152bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();
153bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();
154bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw();
155
156#define MY_STRING_DELETE(_p_) delete []_p_;
157// #define MY_STRING_DELETE(_p_) my_delete(_p_);
158
159class AString
160{
161  char *_chars;
162  unsigned _len;
163  unsigned _limit;
164
165  void MoveItems(unsigned dest, unsigned src)
166  {
167    memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char));
168  }
169
170  void InsertSpace(unsigned &index, unsigned size);
171
172  void ReAlloc(unsigned newLimit);
173  void SetStartLen(unsigned len);
174  void Grow_1();
175  void Grow(unsigned n);
176
177  // AString(unsigned num, const char *s);
178  AString(unsigned num, const AString &s);
179  AString(const AString &s, char c); // it's for String + char
180  AString(const char *s1, unsigned num1, const char *s2, unsigned num2);
181
182  friend AString operator+(const AString &s, char c) { return AString(s, c); } ;
183  // friend AString operator+(char c, const AString &s); // is not supported
184
185  friend AString operator+(const AString &s1, const AString &s2);
186  friend AString operator+(const AString &s1, const char    *s2);
187  friend AString operator+(const char    *s1, const AString &s2);
188
189public:
190  AString();
191  AString(char c);
192  AString(const char *s);
193  AString(const AString &s);
194  ~AString() { MY_STRING_DELETE(_chars); }
195
196  unsigned Len() const { return _len; }
197  bool IsEmpty() const { return _len == 0; }
198  void Empty() { _len = 0; _chars[0] = 0; }
199
200  operator const char *() const { return _chars; }
201  const char *Ptr() const { return _chars; }
202  const char *Ptr(unsigned pos) const { return _chars + pos; }
203  const char *RightPtr(unsigned num) const { return _chars + _len - num; }
204  char Back() const { return _chars[_len - 1]; }
205
206  void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
207
208  // The minimum size of the character buffer in characters.
209  // This value does not include space for a null terminator.
210  char *GetBuffer(unsigned minBufLen)
211  {
212    if (minBufLen > _limit)
213      ReAlloc(minBufLen);
214    return _chars;
215  }
216  void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
217  void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
218
219  AString &operator=(char c);
220  AString &operator=(const char *s);
221  AString &operator=(const AString &s);
222
223  AString &operator+=(char c)
224  {
225    if (_limit == _len)
226      Grow_1();
227    unsigned len = _len;
228    char *chars = _chars;
229    chars[len++] = c;
230    chars[len] = 0;
231    _len = len;
232    return *this;
233  }
234
235  AString &operator+=(const char *s);
236  AString &operator+=(const AString &s);
237
238  void SetFrom(const char *s, unsigned len); // no check
239  // AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
240  AString Left(unsigned count) const { return AString(count, *this); }
241
242  // void MakeUpper() { MyStringUpper(_chars); }
243  // void MakeLower() { MyStringLower(_chars); }
244
245
246  // int Compare(const char *s) const { return MyStringCompare(_chars, s); }
247  // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }
248  // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }
249  // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
250  bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
251  bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
252
253  int Find(char c) const { return FindCharPosInString(_chars, c); }
254  int Find(char c, unsigned startIndex) const
255  {
256    int pos = FindCharPosInString(_chars + startIndex, c);
257    return pos < 0 ? -1 : (int)startIndex + pos;
258  }
259  int ReverseFind(char c) const throw();
260  int Find(const AString &s) const { return Find(s, 0); }
261  int Find(const AString &s, unsigned startIndex) const throw();
262
263  void TrimLeft() throw();
264  void TrimRight() throw();
265  void Trim()
266  {
267    TrimRight();
268    TrimLeft();
269  }
270
271  void InsertAtFront(char c);
272  // void Insert(unsigned index, char c);
273  void Insert(unsigned index, const char *s);
274  void Insert(unsigned index, const AString &s);
275
276  void RemoveChar(char ch) throw();
277  void Replace(char oldChar, char newChar) throw();
278  void Replace(const AString &oldString, const AString &newString);
279
280  void Delete(unsigned index) throw();
281  void Delete(unsigned index, unsigned count) throw();
282  void DeleteFrontal(unsigned num) throw();
283  void DeleteBack() { _chars[--_len] = 0; }
284  void DeleteFrom(unsigned index)
285  {
286    if (index < _len)
287    {
288      _len = index;
289      _chars[index] = 0;
290    }
291  }
292};
293
294bool operator<(const AString &s1, const AString &s2);
295bool operator>(const AString &s1, const AString &s2);
296
297/*
298bool operator==(const AString &s1, const AString &s2);
299bool operator==(const AString &s1, const char    *s2);
300bool operator==(const char    *s1, const AString &s2);
301
302bool operator!=(const AString &s1, const AString &s2);
303bool operator!=(const AString &s1, const char    *s2);
304bool operator!=(const char    *s1, const AString &s2);
305*/
306
307inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }
308inline bool operator==(const AString &s1, const char    *s2) { return strcmp(s1, s2) == 0; }
309inline bool operator==(const char    *s1, const AString &s2) { return strcmp(s1, s2) == 0; }
310
311inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }
312inline bool operator!=(const AString &s1, const char    *s2) { return strcmp(s1, s2) != 0; }
313inline bool operator!=(const char    *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
314
315
316
317class UString
318{
319  wchar_t *_chars;
320  unsigned _len;
321  unsigned _limit;
322
323  void MoveItems(unsigned dest, unsigned src)
324  {
325    memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t));
326  }
327
328  void InsertSpace(unsigned index, unsigned size);
329
330  void ReAlloc(unsigned newLimit);
331  void SetStartLen(unsigned len);
332  void Grow_1();
333  void Grow(unsigned n);
334
335  UString(unsigned num, const wchar_t *s); // for Mid
336  UString(unsigned num, const UString &s); // for Left
337  UString(const UString &s, wchar_t c); // it's for String + char
338  UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2);
339
340  friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ;
341  // friend UString operator+(wchar_t c, const UString &s); // is not supported
342
343  friend UString operator+(const UString &s1, const UString &s2);
344  friend UString operator+(const UString &s1, const wchar_t *s2);
345  friend UString operator+(const wchar_t *s1, const UString &s2);
346
347public:
348  UString();
349  UString(wchar_t c);
350  UString(const wchar_t *s);
351  UString(const UString &s);
352  ~UString() { MY_STRING_DELETE(_chars); }
353
354  unsigned Len() const { return _len; }
355  bool IsEmpty() const { return _len == 0; }
356  void Empty() { _len = 0; _chars[0] = 0; }
357
358  operator const wchar_t *() const { return _chars; }
359  const wchar_t *Ptr() const { return _chars; }
360  const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
361  const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
362  wchar_t Back() const { return _chars[_len - 1]; }
363
364  void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
365
366  // The minimum size of the character buffer in characters.
367  // This value does not include space for a null terminator.
368  wchar_t *GetBuffer(unsigned minBufLen)
369  {
370    if (minBufLen > _limit)
371      ReAlloc(minBufLen);
372    return _chars;
373  }
374  void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
375  void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
376
377  UString &operator=(wchar_t c);
378  UString &operator=(const wchar_t *s);
379  UString &operator=(const UString &s);
380
381  UString &operator+=(wchar_t c)
382  {
383    if (_limit == _len)
384      Grow_1();
385    unsigned len = _len;
386    wchar_t *chars = _chars;
387    chars[len++] = c;
388    chars[len] = 0;
389    _len = len;
390    return *this;
391  }
392
393  UString &operator+=(const wchar_t *s);
394  UString &operator+=(const UString &s);
395
396  void SetFrom(const wchar_t *s, unsigned len); // no check
397
398  void SetFromAscii(const char *s);
399  void AddAsciiStr(const char *s);
400
401  UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
402  UString Left(unsigned count) const { return UString(count, *this); }
403
404  // void MakeUpper() { MyStringUpper(_chars); }
405  // void MakeUpper() { MyStringUpper_Ascii(_chars); }
406  // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); }
407  void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
408
409  bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
410  bool IsEqualToNoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
411  int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
412  // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }
413  // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }
414  // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
415  bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); };
416  bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
417
418  int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
419  int Find(wchar_t c, unsigned startIndex) const
420  {
421    int pos = FindCharPosInString(_chars + startIndex, c);
422    return pos < 0 ? -1 : (int)startIndex + pos;
423  }
424  int Find(const UString &s) const { return Find(s, 0); }
425  int Find(const UString &s, unsigned startIndex) const throw();
426  int ReverseFind(wchar_t c) const throw();
427
428  void TrimLeft() throw();
429  void TrimRight() throw();
430  void Trim()
431  {
432    TrimRight();
433    TrimLeft();
434  }
435
436  void InsertAtFront(wchar_t c);
437  // void Insert(unsigned index, wchar_t c);
438  void Insert(unsigned index, const wchar_t *s);
439  void Insert(unsigned index, const UString &s);
440
441  void RemoveChar(wchar_t ch) throw();
442  void Replace(wchar_t oldChar, wchar_t newChar) throw();
443  void Replace(const UString &oldString, const UString &newString);
444
445  void Delete(unsigned index) throw();
446  void Delete(unsigned index, unsigned count) throw();
447  void DeleteFrontal(unsigned num) throw();
448  void DeleteBack() { _chars[--_len] = 0; }
449  void DeleteFrom(unsigned index)
450  {
451    if (index < _len)
452    {
453      _len = index;
454      _chars[index] = 0;
455    }
456  }
457};
458
459bool operator<(const UString &s1, const UString &s2);
460bool operator>(const UString &s1, const UString &s2);
461
462inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }
463inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }
464inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }
465
466inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }
467inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }
468inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
469
470
471typedef CObjectVector<AString> AStringVector;
472typedef CObjectVector<UString> UStringVector;
473
474#ifdef _UNICODE
475  typedef UString CSysString;
476#else
477  typedef AString CSysString;
478#endif
479
480typedef CObjectVector<CSysString> CSysStringVector;
481
482
483// ---------- FString ----------
484
485#ifdef _WIN32
486  #define USE_UNICODE_FSTRING
487#endif
488
489#ifdef USE_UNICODE_FSTRING
490
491  #define __FTEXT(quote) L##quote
492
493  typedef wchar_t FChar;
494  typedef UString FString;
495
496  #define fs2us(_x_) (_x_)
497  #define us2fs(_x_) (_x_)
498  FString fas2fs(const AString &s);
499  AString fs2fas(const FChar *s);
500
501#else
502
503  #define __FTEXT(quote) quote
504
505  typedef char FChar;
506  typedef AString FString;
507
508  UString fs2us(const FString &s);
509  FString us2fs(const wchar_t *s);
510  #define fas2fs(_x_) (_x_)
511  #define fs2fas(_x_) (_x_)
512
513#endif
514
515#define FTEXT(quote) __FTEXT(quote)
516
517#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)
518#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)
519#define FCHAR_ANY_MASK FTEXT('*')
520#define FSTRING_ANY_MASK FTEXT("*")
521typedef const FChar *CFSTR;
522
523typedef CObjectVector<FString> FStringVector;
524
525#endif
526