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