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 
MyStringLen(const char * s)16 inline unsigned MyStringLen(const char *s)
17 {
18   unsigned i;
19   for (i = 0; s[i] != 0; i++);
20   return i;
21 }
22 
MyStringCopy(char * dest,const char * src)23 inline void MyStringCopy(char *dest, const char *src)
24 {
25   while ((*dest++ = *src++) != 0);
26 }
27 
MyStpCpy(char * dest,const char * src)28 inline 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 
MyStringLen(const wchar_t * s)41 inline unsigned MyStringLen(const wchar_t *s)
42 {
43   unsigned i;
44   for (i = 0; s[i] != 0; i++);
45   return i;
46 }
47 
MyStringCopy(wchar_t * dest,const wchar_t * src)48 inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
49 {
50   while ((*dest++ = *src++) != 0);
51 }
52 
53 int FindCharPosInString(const char *s, char c) throw();
54 int 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 /*
67 inline char MyCharUpper_Ascii(char c)
68 {
69   if (c >= 'a' && c <= 'z')
70     return (char)(c - 0x20);
71   return c;
72 }
73 inline 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 
MyCharLower_Ascii(char c)81 inline char MyCharLower_Ascii(char c)
82 {
83   if (c >= 'A' && c <= 'Z')
84     return (char)(c + 0x20);
85   return c;
86 }
87 
MyCharLower_Ascii(wchar_t c)88 inline 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 
95 wchar_t MyCharUpper_WIN(wchar_t c) throw();
96 
MyCharUpper(wchar_t c)97 inline 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 /*
114 wchar_t MyCharLower_WIN(wchar_t c) throw();
115 
116 inline 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();
137 void 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 
141 bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
142 
143 bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
144 bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
145 
146 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();
147 int 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
151 bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();
152 bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();
153 bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();
154 bool 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 
159 class AString
160 {
161   char *_chars;
162   unsigned _len;
163   unsigned _limit;
164 
MoveItems(unsigned dest,unsigned src)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 
189 public:
190   AString();
191   AString(char c);
192   AString(const char *s);
193   AString(const AString &s);
~AString()194   ~AString() { MY_STRING_DELETE(_chars); }
195 
Len()196   unsigned Len() const { return _len; }
IsEmpty()197   bool IsEmpty() const { return _len == 0; }
Empty()198   void Empty() { _len = 0; _chars[0] = 0; }
199 
200   operator const char *() const { return _chars; }
Ptr()201   const char *Ptr() const { return _chars; }
Ptr(unsigned pos)202   const char *Ptr(unsigned pos) const { return _chars + pos; }
RightPtr(unsigned num)203   const char *RightPtr(unsigned num) const { return _chars + _len - num; }
Back()204   char Back() const { return _chars[_len - 1]; }
205 
ReplaceOneCharAtPos(unsigned pos,char c)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.
GetBuffer(unsigned minBufLen)210   char *GetBuffer(unsigned minBufLen)
211   {
212     if (minBufLen > _limit)
213       ReAlloc(minBufLen);
214     return _chars;
215   }
ReleaseBuffer()216   void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
ReleaseBuffer(unsigned newLen)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); }
Left(unsigned count)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); }
IsPrefixedBy(const char * s)250   bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
251   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
252 
Find(char c)253   int Find(char c) const { return FindCharPosInString(_chars, c); }
Find(char c,unsigned startIndex)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();
Find(const AString & s)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();
Trim()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();
DeleteBack()283   void DeleteBack() { _chars[--_len] = 0; }
DeleteFrom(unsigned index)284   void DeleteFrom(unsigned index)
285   {
286     if (index < _len)
287     {
288       _len = index;
289       _chars[index] = 0;
290     }
291   }
292 };
293 
294 bool operator<(const AString &s1, const AString &s2);
295 bool operator>(const AString &s1, const AString &s2);
296 
297 /*
298 bool operator==(const AString &s1, const AString &s2);
299 bool operator==(const AString &s1, const char    *s2);
300 bool operator==(const char    *s1, const AString &s2);
301 
302 bool operator!=(const AString &s1, const AString &s2);
303 bool operator!=(const AString &s1, const char    *s2);
304 bool operator!=(const char    *s1, const AString &s2);
305 */
306 
307 inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }
308 inline bool operator==(const AString &s1, const char    *s2) { return strcmp(s1, s2) == 0; }
309 inline bool operator==(const char    *s1, const AString &s2) { return strcmp(s1, s2) == 0; }
310 
311 inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }
312 inline bool operator!=(const AString &s1, const char    *s2) { return strcmp(s1, s2) != 0; }
313 inline bool operator!=(const char    *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
314 
315 
316 
317 class UString
318 {
319   wchar_t *_chars;
320   unsigned _len;
321   unsigned _limit;
322 
MoveItems(unsigned dest,unsigned src)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 
347 public:
348   UString();
349   UString(wchar_t c);
350   UString(const wchar_t *s);
351   UString(const UString &s);
~UString()352   ~UString() { MY_STRING_DELETE(_chars); }
353 
Len()354   unsigned Len() const { return _len; }
IsEmpty()355   bool IsEmpty() const { return _len == 0; }
Empty()356   void Empty() { _len = 0; _chars[0] = 0; }
357 
358   operator const wchar_t *() const { return _chars; }
Ptr()359   const wchar_t *Ptr() const { return _chars; }
Ptr(unsigned pos)360   const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
RightPtr(unsigned num)361   const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
Back()362   wchar_t Back() const { return _chars[_len - 1]; }
363 
ReplaceOneCharAtPos(unsigned pos,wchar_t c)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.
GetBuffer(unsigned minBufLen)368   wchar_t *GetBuffer(unsigned minBufLen)
369   {
370     if (minBufLen > _limit)
371       ReAlloc(minBufLen);
372     return _chars;
373   }
ReleaseBuffer()374   void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
ReleaseBuffer(unsigned newLen)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 
Mid(unsigned startIndex,unsigned count)401   UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
Left(unsigned count)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); }
MakeLower_Ascii()407   void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
408 
IsEqualTo(const char * s)409   bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
IsEqualToNoCase(const wchar_t * s)410   bool IsEqualToNoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
Compare(const wchar_t * 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); }
IsPrefixedBy(const wchar_t * s)415   bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); };
416   bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
417 
Find(wchar_t c)418   int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
Find(wchar_t c,unsigned startIndex)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   }
Find(const UString & s)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();
Trim()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();
DeleteBack()448   void DeleteBack() { _chars[--_len] = 0; }
DeleteFrom(unsigned index)449   void DeleteFrom(unsigned index)
450   {
451     if (index < _len)
452     {
453       _len = index;
454       _chars[index] = 0;
455     }
456   }
457 };
458 
459 bool operator<(const UString &s1, const UString &s2);
460 bool operator>(const UString &s1, const UString &s2);
461 
462 inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }
463 inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }
464 inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }
465 
466 inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }
467 inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }
468 inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
469 
470 
471 typedef CObjectVector<AString> AStringVector;
472 typedef CObjectVector<UString> UStringVector;
473 
474 #ifdef _UNICODE
475   typedef UString CSysString;
476 #else
477   typedef AString CSysString;
478 #endif
479 
480 typedef 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("*")
521 typedef const FChar *CFSTR;
522 
523 typedef CObjectVector<FString> FStringVector;
524 
525 #endif
526