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