Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | daniel-mar | 1 | #include "stdafx.h" |
2 | #pragma hdrstop |
||
3 | |||
4 | #include "DZ_StrW.h" |
||
5 | #include <stdio.h> |
||
6 | #include <tchar.h> |
||
7 | //#include "common.h" |
||
8 | #include "dz_errs.h" |
||
9 | #include "DivMod64.h" |
||
10 | |||
11 | #undef _DZ_FILE_ |
||
12 | #define _DZ_FILE_ DZ_DZ_STRW_CPP |
||
13 | |||
14 | /* DZ_StrW.cpp |
||
15 | ************************************************************************ |
||
16 | Copyright (C) 2009, 2010 by Russell J. Peters, Roger Aelbrecht |
||
17 | |||
18 | This file is part of TZipMaster Version 1.9. |
||
19 | |||
20 | TZipMaster is free software: you can redistribute it and/or modify |
||
21 | it under the terms of the GNU Lesser General Public License as published by |
||
22 | the Free Software Foundation, either version 3 of the License, or |
||
23 | (at your option) any later version. |
||
24 | |||
25 | TZipMaster is distributed in the hope that it will be useful, |
||
26 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
28 | GNU Lesser General Public License for more details. |
||
29 | |||
30 | You should have received a copy of the GNU Lesser General Public License |
||
31 | along with TZipMaster. If not, see <http://www.gnu.org/licenses/>. |
||
32 | |||
33 | contact: problems@delphizip.org (include ZipMaster in the subject). |
||
34 | updates: http://www.delphizip.org |
||
35 | DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip |
||
36 | ************************************************************************/ |
||
37 | #ifndef WC_NO_BEST_FIT_CHARS |
||
38 | # define WC_NO_BEST_FIT_CHARS 0x00000400 |
||
39 | #endif |
||
40 | |||
41 | |||
42 | #ifdef DEBUG_COUNT |
||
43 | int AliveCountW = 0; |
||
44 | #endif |
||
45 | |||
46 | |||
47 | int DZ_MIN(int arg1, int arg2) |
||
48 | { |
||
49 | return arg2 < arg1 ? arg2 : arg1; |
||
50 | } |
||
51 | |||
52 | int DZ_MAX(int arg1, int arg2) |
||
53 | { |
||
54 | return arg2 > arg1 ? arg2 : arg1; |
||
55 | } |
||
56 | |||
57 | // min capacity = 25 chars, grow n * 32 |
||
58 | dzstrw_imp* __fastcall DZStrW::NewImp(unsigned siz) |
||
59 | { |
||
60 | unsigned datasize = siz * sizeof(wchar_t); |
||
61 | unsigned rawsize = sizeof(dzstrw_imp) + datasize; |
||
62 | if (rawsize & 63) |
||
63 | rawsize = (rawsize | 63) + 1; |
||
64 | |||
65 | dzstrw_imp* _imp = (dzstrw_imp*) (new char[rawsize]); |
||
66 | if (! _imp) |
||
67 | throw DZException(DZ_ERM_MEMORY); |
||
68 | |||
69 | _imp->refs = 1; |
||
70 | _imp->capacity = (rawsize - sizeof(dzstrw_imp)) / sizeof(wchar_t); |
||
71 | _imp->len = 0; |
||
72 | _imp->data[0] = 0; |
||
73 | #ifdef DEBUG_COUNT |
||
74 | AliveCountW++; |
||
75 | #endif |
||
76 | return _imp; |
||
77 | } |
||
78 | |||
79 | dzstrw_imp* __fastcall DZStrW::NewImp(const wchar_t* src, int maxLen) |
||
80 | { |
||
81 | int len = 0; |
||
82 | if (src) |
||
83 | len = wcslen(src); |
||
84 | |||
85 | if (maxLen >= 0 && len > maxLen) |
||
86 | len = maxLen; |
||
87 | |||
88 | if (!len) |
||
89 | return NULL; // empty |
||
90 | |||
91 | dzstrw_imp* nimp = NewImp(len >= maxLen ? len : maxLen); // make new |
||
92 | wcsncpy(nimp->data, src, len); |
||
93 | nimp->data[len] = 0; // mark end - in case |
||
94 | nimp->len = wcslen(nimp->data); |
||
95 | return nimp; |
||
96 | } |
||
97 | |||
98 | dzstrw_imp* __fastcall DZStrW::NewImp(const char* src, int maxLen) |
||
99 | { |
||
100 | int len = 0; |
||
101 | if (src) |
||
102 | len = strlen(src); |
||
103 | |||
104 | if (maxLen >= 0 && len > maxLen) |
||
105 | len = maxLen; |
||
106 | |||
107 | if (!len) |
||
108 | return NULL; // empty |
||
109 | int space = len + (len / 2); // generous |
||
110 | |||
111 | dzstrw_imp* nimp = NewImp(space >= maxLen ? space : maxLen); // make new |
||
112 | int wcnt = MultiByteToWideChar(0, 0, src, len, nimp->data, nimp->capacity); |
||
113 | nimp->data[wcnt] = 0; |
||
114 | nimp->len = wcslen(nimp->data); |
||
115 | return nimp; |
||
116 | |||
117 | } |
||
118 | |||
119 | unsigned __fastcall DZStrW::_Capacity(dzstrw_imp* _imp) const |
||
120 | { |
||
121 | if (_imp) |
||
122 | return _imp->capacity; |
||
123 | return 0; |
||
124 | } |
||
125 | |||
126 | unsigned __fastcall DZStrW::Capacity(void) const |
||
127 | { |
||
128 | return _Capacity(_IMP_Ptr(imp)); |
||
129 | } |
||
130 | |||
131 | unsigned __fastcall DZStrW::_Length(dzstrw_imp* _imp) const |
||
132 | { |
||
133 | if (_imp) |
||
134 | return _imp->len; |
||
135 | return 0; |
||
136 | } |
||
137 | |||
138 | unsigned __fastcall DZStrW::Length(void) const |
||
139 | { |
||
140 | return _Length(_IMP_Ptr(imp)); |
||
141 | } |
||
142 | |||
143 | unsigned __fastcall DZStrW::_IncImpRefs(dzstrw_imp* _imp) |
||
144 | { |
||
145 | if (_imp) |
||
146 | return InterlockedIncrement(& (_imp->refs)); |
||
147 | return 0; |
||
148 | } |
||
149 | |||
150 | unsigned __fastcall DZStrW::_DecImpRefs(dzstrw_imp* _imp) |
||
151 | { |
||
152 | if (_imp->refs) |
||
153 | return InterlockedDecrement(& (_imp->refs)); |
||
154 | return 0; |
||
155 | } |
||
156 | |||
157 | void __fastcall DZStrW::_ReleaseImp(dzstrw_imp* _imp) |
||
158 | { |
||
159 | if (_imp && !_DecImpRefs(_imp)) |
||
160 | { |
||
161 | delete [] _imp; |
||
162 | #ifdef DEBUG_COUNT |
||
163 | AliveCountW--; |
||
164 | #endif |
||
165 | } |
||
166 | } |
||
167 | |||
168 | void __fastcall DZStrW::Release(void) |
||
169 | { |
||
170 | if (imp) |
||
171 | { |
||
172 | dzstrw_imp* _imp = _IMP_Ptr(imp); |
||
173 | imp = NULL; |
||
174 | _ReleaseImp(_imp); |
||
175 | } |
||
176 | } |
||
177 | |||
178 | int __fastcall DZStrW::IncRefs(void) |
||
179 | { |
||
180 | if (imp) |
||
181 | return _IncImpRefs(_IMP_Ptr(imp)); |
||
182 | return 0; |
||
183 | } |
||
184 | |||
185 | int __fastcall DZStrW::DecRefs(void) |
||
186 | { |
||
187 | if (imp) |
||
188 | return _DecImpRefs(_IMP_Ptr(imp)); |
||
189 | return -1; |
||
190 | } |
||
191 | |||
192 | // maxSpace is max characters |
||
193 | void __fastcall DZStrW::_Assign(const wchar_t* src, int maxLen) |
||
194 | { |
||
195 | Release(); |
||
196 | imp = _IMP_Data(NewImp(src, maxLen)); |
||
197 | } |
||
198 | |||
199 | void __fastcall DZStrW::_Assign(const char* src, int maxLen) |
||
200 | { |
||
201 | Release(); |
||
202 | imp = _IMP_Data(NewImp(src, maxLen)); |
||
203 | } |
||
204 | |||
205 | void __fastcall DZStrW::_Append(const wchar_t* src, int maxLen) |
||
206 | { |
||
207 | dzstrw_imp* _imp = _IMP_Ptr(imp); |
||
208 | |||
209 | unsigned len = 0; |
||
210 | if (src) |
||
211 | len = wcslen(src); |
||
212 | if (maxLen >= 0 && len > (unsigned)maxLen) |
||
213 | len = maxLen; |
||
214 | // check something to append |
||
215 | if (len) |
||
216 | { |
||
217 | if (!imp) |
||
218 | imp = _IMP_Data(NewImp(src, len)); |
||
219 | else |
||
220 | { |
||
221 | unsigned oldlen = _imp->len; |
||
222 | unsigned nlen = oldlen + len; |
||
223 | |||
224 | // do we need a new one |
||
225 | if (_imp->refs > 1 || nlen > _imp->capacity) |
||
226 | { |
||
227 | // need new imp - make copy with enough space |
||
228 | dzstrw_imp* nimp = NewImp(_imp->data, nlen); |
||
229 | Release(); // out with the old |
||
230 | imp = _IMP_Data(nimp); // in with the new |
||
231 | _imp = nimp; |
||
232 | } |
||
233 | // append data |
||
234 | wchar_t *bf = &_imp->data[_imp->len]; |
||
235 | wcsncpy(bf, src, len); |
||
236 | _imp->data[nlen] = 0; |
||
237 | _imp->len = wcslen(_imp->data); |
||
238 | } |
||
239 | } |
||
240 | } |
||
241 | |||
242 | void __fastcall DZStrW::_Append(const char* src, int maxSpace) |
||
243 | { |
||
244 | DZStrW Asrc(src, maxSpace); |
||
245 | _Append(Asrc.imp, maxSpace); |
||
246 | } |
||
247 | |||
248 | void __fastcall DZStrW::_Append(wchar_t ch) |
||
249 | { |
||
250 | wchar_t chr[2]; |
||
251 | chr[0] = ch; |
||
252 | chr[1] = 0; |
||
253 | _Append(chr, 1); |
||
254 | } |
||
255 | |||
256 | __fastcall DZStrW::DZStrW(const DZStrW& other) |
||
257 | { |
||
258 | if (other.IsEmpty()) |
||
259 | imp = NULL; |
||
260 | else |
||
261 | { |
||
262 | imp = other.imp; |
||
263 | IncRefs(); |
||
264 | } |
||
265 | } |
||
266 | |||
267 | __fastcall DZStrW::DZStrW(const DZStrA& other) |
||
268 | { |
||
269 | if (other.IsEmpty()) |
||
270 | imp = NULL; |
||
271 | else |
||
272 | imp = _IMP_Data(NewImp(other.c_str(), other.Length())); |
||
273 | } |
||
274 | |||
275 | __fastcall DZStrW::DZStrW(const wchar_t* str, int len) |
||
276 | { |
||
277 | imp = _IMP_Data(NewImp(str, len)); |
||
278 | } |
||
279 | |||
280 | __fastcall DZStrW::DZStrW(const char* str, int len) |
||
281 | { |
||
282 | imp = _IMP_Data(NewImp(str, len)); |
||
283 | } |
||
284 | |||
285 | __fastcall DZStrW::DZStrW(UINT cp, const char* str, int len) |
||
286 | { |
||
287 | imp = NULL; |
||
288 | if (str && *str && len && len < (32 * 1024)) |
||
289 | { |
||
290 | if (len < 0) |
||
291 | len = strlen(str); |
||
292 | // convert to Unicode |
||
293 | int wcnt = MultiByteToWideChar(cp, 0, str, len, NULL, 0); |
||
294 | if (wcnt > 0) |
||
295 | { |
||
296 | dzstrw_imp* nimp = NewImp(wcnt); |
||
297 | imp = _IMP_Data(nimp); |
||
298 | wcnt = MultiByteToWideChar(cp, 0, str, len, imp, wcnt); |
||
299 | imp[wcnt] = 0; |
||
300 | nimp->len = wcnt; |
||
301 | } |
||
302 | } |
||
303 | } |
||
304 | |||
305 | __fastcall DZStrW::DZStrW(wchar_t ch, unsigned cnt) |
||
306 | { |
||
307 | if (cnt) { |
||
308 | dzstrw_imp* nimp = NewImp(cnt); |
||
309 | imp = _IMP_Data(nimp); |
||
310 | wchar_t* bf = imp; |
||
311 | for (unsigned i = cnt; i < cnt; i++) |
||
312 | *bf++ = ch; |
||
313 | *bf = 0; |
||
314 | nimp->len = cnt; |
||
315 | } |
||
316 | else |
||
317 | imp = NULL; |
||
318 | } |
||
319 | |||
320 | DZStrW& __fastcall DZStrW::operator =(const DZStrW& other) |
||
321 | { |
||
322 | if (this != &other) |
||
323 | { |
||
324 | Release(); |
||
325 | if (!other.IsEmpty()) |
||
326 | { |
||
327 | imp = other.imp; |
||
328 | IncRefs(); |
||
329 | } |
||
330 | } |
||
331 | return *this; |
||
332 | } |
||
333 | |||
334 | DZStrW& __fastcall DZStrW::operator =(const wchar_t* str) |
||
335 | { |
||
336 | Release(); |
||
337 | imp = _IMP_Data(NewImp(str, -1)); |
||
338 | return *this; |
||
339 | } |
||
340 | |||
341 | DZStrW& __fastcall DZStrW::operator =(const char* str) |
||
342 | { |
||
343 | Release(); |
||
344 | imp = _IMP_Data(NewImp(str, -1)); |
||
345 | return *this; |
||
346 | } |
||
347 | |||
348 | DZStrW __fastcall DZStrW::operator +(const DZStrW& other) |
||
349 | { |
||
350 | DZStrW res(*this); |
||
351 | res._Append(other.c_str(), -1); |
||
352 | return res; |
||
353 | } |
||
354 | |||
355 | DZStrW __fastcall DZStrW::operator +(const wchar_t* str) |
||
356 | { |
||
357 | DZStrW res(*this); |
||
358 | res._Append(str, -1); |
||
359 | return res; |
||
360 | } |
||
361 | |||
362 | DZStrW& __fastcall DZStrW::operator +=(const DZStrW& other) |
||
363 | { |
||
364 | _Append(other.c_str(), -1); |
||
365 | return *this; |
||
366 | } |
||
367 | |||
368 | DZStrW& __fastcall DZStrW::operator +=(const wchar_t* str) |
||
369 | { |
||
370 | _Append(str, -1); |
||
371 | return *this; |
||
372 | } |
||
373 | |||
374 | |||
375 | __fastcall DZStrW::~DZStrW(void) |
||
376 | { |
||
377 | Release(); |
||
378 | } |
||
379 | |||
380 | DZStrW& __fastcall DZStrW::operator +=(wchar_t ch) |
||
381 | { |
||
382 | wchar_t buf[2]; |
||
383 | buf[0] = ch; |
||
384 | buf[1] = 0; |
||
385 | _Append(buf, 1); |
||
386 | return *this; |
||
387 | } |
||
388 | |||
389 | wchar_t __fastcall DZStrW::operator [](unsigned idx) const |
||
390 | { |
||
391 | if (!imp || idx >= Length()) |
||
392 | return 0; |
||
393 | return *(imp + idx); |
||
394 | } |
||
395 | |||
396 | wchar_t * __fastcall DZStrW::GetBuffer(int minsize) |
||
397 | { |
||
398 | dzstrw_imp* _imp = _IMP_Ptr(imp); |
||
399 | |||
400 | int nlen = _imp ? _imp->len : 0; |
||
401 | if (minsize >= 0) |
||
402 | nlen = minsize; |
||
403 | // need new imp - make copy with enough space |
||
404 | dzstrw_imp* nimp; |
||
405 | if (!_imp) |
||
406 | nimp = NewImp(nlen); |
||
407 | else |
||
408 | { |
||
409 | nimp = NewImp(_imp->data, nlen); |
||
410 | Release(); // out with the old |
||
411 | } |
||
412 | imp = _IMP_Data(nimp); // in with the new |
||
413 | return imp; |
||
414 | } |
||
415 | |||
416 | void __fastcall DZStrW::ReleaseBuffer(int newlen) |
||
417 | { |
||
418 | if (imp) |
||
419 | { |
||
420 | dzstrw_imp* _imp = _IMP_Ptr(imp); |
||
421 | _imp->data[_imp->capacity] = 0; //ensure end marked |
||
422 | int len = wcslen(imp); |
||
423 | if (newlen >=0 && newlen < len) { |
||
424 | len = newlen; |
||
425 | _imp->data[len] = 0; // truncate |
||
426 | } |
||
427 | _imp->len = len; |
||
428 | } |
||
429 | } |
||
430 | |||
431 | dzstrw_imp* DZStrW::Unique(void) |
||
432 | { |
||
433 | dzstrw_imp* _imp = _IMP_Ptr(imp); |
||
434 | if (imp && _imp->refs > 1) |
||
435 | { |
||
436 | dzstrw_imp* nimp = NewImp(imp, Capacity()); |
||
437 | Release(); |
||
438 | imp = _IMP_Data(nimp); |
||
439 | return nimp; |
||
440 | } |
||
441 | return _imp; |
||
442 | } |
||
443 | |||
444 | void __cdecl DZStrW::AppendFormat(const wchar_t *fmt, ...) |
||
445 | { |
||
446 | if (fmt) |
||
447 | { |
||
448 | DZStrW tmp; |
||
449 | va_list argList; |
||
450 | va_start(argList, fmt); |
||
451 | tmp.FormatV(fmt, argList); |
||
452 | va_end(argList); |
||
453 | if (!tmp.IsEmpty()) |
||
454 | _Append(tmp.c_str()); |
||
455 | } |
||
456 | } |
||
457 | |||
458 | bool __fastcall DZStrW::BadDOS(void) const |
||
459 | { |
||
460 | if (IsEmpty()) |
||
461 | return false; |
||
462 | |||
463 | // int Bad; |
||
464 | // WideCharToMultiByte(CP_ACP, 0, c_str(), Length(), NULL, 0, 0, &Bad); |
||
465 | // return Bad; |
||
466 | wchar_t tmp; |
||
467 | for (const wchar_t* p = imp; (tmp = *p) != 0; p++) |
||
468 | if (tmp < 32 || tmp > 126) |
||
469 | return true; |
||
470 | return false; |
||
471 | } |
||
472 | |||
473 | int __fastcall DZStrW::Compare(const wchar_t *other) const |
||
474 | { |
||
475 | if (!imp) |
||
476 | return (other && *other)? -1 : 0; |
||
477 | if (!other || !*other) |
||
478 | return -1; |
||
479 | return wcscmp(imp, other); |
||
480 | } |
||
481 | |||
482 | int __fastcall DZStrW::CompareNoCase(const wchar_t *other) const |
||
483 | { |
||
484 | if (!imp) |
||
485 | return (other && *other)? -1 : 0; |
||
486 | if (!other || !*other) |
||
487 | return -1; |
||
488 | |||
489 | DZStrW me(*this); |
||
490 | me.ToUpper(); |
||
491 | DZStrW theOther(other); |
||
492 | theOther.ToUpper(); |
||
493 | return wcscmp(me.imp, theOther.imp); |
||
494 | } |
||
495 | |||
496 | int __fastcall DZStrW::Delete(unsigned pos, unsigned cnt) |
||
497 | { |
||
498 | if (!imp || pos >= Length()) |
||
499 | return 0; |
||
500 | dzstrw_imp* _imp = Unique(); |
||
501 | wchar_t* p = _imp->data + pos; |
||
502 | if (pos + cnt < _imp->len) |
||
503 | { |
||
504 | for (wchar_t* q = p + cnt; *q; q++) |
||
505 | *p++ = *q; |
||
506 | } |
||
507 | *p = 0; |
||
508 | _imp->len = wcslen(_imp->data); |
||
509 | return (int)_imp->len; |
||
510 | } |
||
511 | |||
512 | int __fastcall DZStrW::Find(const wchar_t *sub, unsigned start) const |
||
513 | { |
||
514 | if (!imp || start > Length() || !sub || !*sub) |
||
515 | return -1; |
||
516 | int slen = wcslen(sub); |
||
517 | if (start + slen > Length()) |
||
518 | return -1; |
||
519 | const wchar_t* si = wcsstr(imp + start, sub); |
||
520 | if (!si) |
||
521 | return -1; |
||
522 | return si - imp; |
||
523 | } |
||
524 | |||
525 | int __fastcall DZStrW::Find(wchar_t ch, unsigned start) const |
||
526 | { |
||
527 | if (!imp || start > Length()) |
||
528 | return -1; |
||
529 | |||
530 | int i = start; |
||
531 | for (const wchar_t* p = &imp[start]; *p && *p != ch; p++) |
||
532 | i++; |
||
533 | return (unsigned)i >= Length() ? -1 : i; |
||
534 | } |
||
535 | |||
536 | int __fastcall DZStrW::FindOneOf(const wchar_t *chars, unsigned start) const |
||
537 | { |
||
538 | if (!imp || start > Length()) |
||
539 | return -1; |
||
540 | |||
541 | int i = start; |
||
542 | for (const wchar_t* p = &imp[start]; *p; p++) |
||
543 | { |
||
544 | bool found = false; |
||
545 | wchar_t ch = *p; |
||
546 | for (const wchar_t* q = chars; *q; q++) |
||
547 | { |
||
548 | if (*q == ch) |
||
549 | { |
||
550 | found = true; |
||
551 | break; |
||
552 | } |
||
553 | } |
||
554 | if (found) |
||
555 | break; |
||
556 | i++; |
||
557 | } |
||
558 | return (unsigned)i >= Length() ? -1 : i; |
||
559 | } |
||
560 | |||
561 | int __cdecl DZStrW::Format(const wchar_t *fmt, ...) |
||
562 | { |
||
563 | Release(); |
||
564 | int r = 0; |
||
565 | if (fmt) |
||
566 | { |
||
567 | va_list argList; |
||
568 | va_start(argList, fmt); |
||
569 | r = FormatV(fmt, argList); |
||
570 | va_end(argList); |
||
571 | } |
||
572 | return r; |
||
573 | } |
||
574 | |||
575 | #if 0 |
||
576 | // arg = arg / divisor , returns remainder |
||
577 | unsigned DivMod64(unsigned __int64& arg, unsigned divisor) |
||
578 | { |
||
579 | asm |
||
580 | { |
||
581 | mov ecx, [ebp + 8] // arg |
||
582 | mov eax, [ebp + 12] // divisor |
||
583 | or eax, eax |
||
584 | jnz @@ok |
||
585 | // / 0 _ return 0, 0 _ not correct but safer |
||
586 | mov [ecx + 4] ,eax // arg hi |
||
587 | mov [ecx + 0] ,eax // arg lo |
||
588 | jmp @@done |
||
589 | @@ok: |
||
590 | xor edx, edx |
||
591 | mov eax, [ecx + 4] // arg hi |
||
592 | or eax, eax // zero? |
||
593 | jz @@nohi |
||
594 | div dword ptr [ebp + 12] |
||
595 | @@nohi: |
||
596 | mov [ecx + 4], eax // quot hi |
||
597 | mov eax, [ecx] // _dividend[0] |
||
598 | div dword ptr [ebp + 12] |
||
599 | mov [ecx], eax // quot lo |
||
600 | mov eax, edx // remainder |
||
601 | @@done: |
||
602 | } |
||
603 | #pragma warn -rvl |
||
604 | #pragma warn -par |
||
605 | } |
||
606 | #endif |
||
607 | |||
608 | #define MAXDIGITS 64 |
||
609 | |||
610 | //static const wchar_t digits[] = L"0123456789abcdefghijklmnopqrstuvwxyz"; |
||
611 | static const wchar_t zeros[] = L"00000000000000000000000000000000"; |
||
612 | static const wchar_t spaces[] = L" "; |
||
613 | |||
614 | static |
||
615 | int convert(unsigned __int64 value, int radix, wchar_t *buffer, bool upper) |
||
616 | { |
||
617 | wchar_t buf[MAXDIGITS + 2]; |
||
618 | int i; |
||
619 | wchar_t aA = upper ? L'A' : L'a'; |
||
620 | |||
621 | i = 0; |
||
622 | |||
623 | if (radix == -10) { |
||
624 | if ((int)value < 0) { |
||
625 | buffer[i++] = '-'; |
||
626 | value = 0-value; |
||
627 | } |
||
628 | radix = 10; |
||
629 | } |
||
630 | |||
631 | if (radix != 10 && radix != 16 && radix != 8 && radix != 2 && radix != 36) |
||
632 | radix = 16; |
||
633 | |||
634 | wchar_t* p = &buf[MAXDIGITS + 1]; |
||
635 | *p = 0; |
||
636 | while (value) |
||
637 | { |
||
638 | int cv = DivMod64(value, radix); |
||
639 | wchar_t c;// = digits[DivMod64(value, radix) & 15]; |
||
640 | if (cv <= 9) |
||
641 | c = (wchar_t)(L'0' + cv); |
||
642 | else |
||
643 | c = (wchar_t)(aA + (cv - 10)); |
||
644 | *--p = c; |
||
645 | |||
646 | if (++i > MAXDIGITS) |
||
647 | break; |
||
648 | } |
||
649 | if (!i) |
||
650 | { |
||
651 | *--p = L'0'; |
||
652 | i++; |
||
653 | } |
||
654 | wcsncpy(buffer, p, i); |
||
655 | buffer[i] = 0; |
||
656 | return i; |
||
657 | } |
||
658 | |||
659 | #define FORMAT_BUFFER_SIZE 2048 |
||
660 | int __cdecl DZStrW::FormatV(const wchar_t *fmt, void *argList) |
||
661 | { |
||
662 | int i; |
||
663 | int j; |
||
664 | __int64 n; |
||
665 | int arg; |
||
666 | wchar_t c; |
||
667 | int zero; |
||
668 | bool right; |
||
669 | wchar_t flag; |
||
670 | int width; |
||
671 | int prec; |
||
672 | const wchar_t *p; |
||
673 | wchar_t temp[MAXDIGITS+1+55]; |
||
674 | |||
675 | Release(); |
||
676 | if (!fmt) |
||
677 | return 0; |
||
678 | dzstrw_imp* _imp = NewImp(FORMAT_BUFFER_SIZE + 1); |
||
679 | imp = _IMP_Data(_imp); |
||
680 | |||
681 | i = 0; |
||
682 | for (p = fmt; *p; p++) |
||
683 | { |
||
684 | c = *p; |
||
685 | if (c != L'%') |
||
686 | { |
||
687 | _Append(c); |
||
688 | i++; |
||
689 | continue; |
||
690 | } |
||
691 | zero = 0; |
||
692 | width = 0; |
||
693 | right = false; |
||
694 | flag = 0; |
||
695 | c = *++p; |
||
696 | if (c == L'%') |
||
697 | { |
||
698 | _Append(c); |
||
699 | i++; |
||
700 | continue; |
||
701 | } |
||
702 | |||
703 | if (c == L'-') |
||
704 | { |
||
705 | right = true; |
||
706 | c = *++p; |
||
707 | } |
||
708 | |||
709 | if (c == L'0') |
||
710 | { |
||
711 | zero = 1; |
||
712 | c = *++p; |
||
713 | } |
||
714 | if (iswdigit(c)) |
||
715 | { |
||
716 | width = c - L'0'; |
||
717 | c = *++p; |
||
718 | if (iswdigit(c)) |
||
719 | { |
||
720 | width = (width*10) + (c - L'0'); |
||
721 | c = *++p; |
||
722 | } |
||
723 | } |
||
724 | |||
725 | prec = 0x7fffffff; |
||
726 | if (c == L'.') |
||
727 | { |
||
728 | prec = 0; |
||
729 | c = *++p; |
||
730 | while (iswdigit(c)) |
||
731 | { |
||
732 | prec = (prec*10) + (c - L'0'); |
||
733 | c = *++p; |
||
734 | } |
||
735 | } |
||
736 | |||
737 | if (c == L'h' || c == L'l' || c == L'L') |
||
738 | { |
||
739 | flag = c; |
||
740 | c = *++p; |
||
741 | } |
||
742 | |||
743 | if (flag == L'L' && (c == L'd' || c == L'u' || c == L'x' || c == L'X')) |
||
744 | { |
||
745 | n = va_arg(argList, __int64); |
||
746 | } |
||
747 | else |
||
748 | { |
||
749 | arg = va_arg(argList, int); |
||
750 | n = arg; |
||
751 | } |
||
752 | bool upperXZ = false; |
||
753 | switch (c) |
||
754 | { |
||
755 | case L'b': |
||
756 | j = convert(n, 2, temp, false); |
||
757 | break; |
||
758 | case L'c': |
||
759 | temp[0] = (wchar_t)n; |
||
760 | temp[1] = L'\0'; |
||
761 | j = 1; |
||
762 | break; |
||
763 | case L'i': |
||
764 | case L'd': |
||
765 | j = convert(n, -10, temp, false); |
||
766 | break; |
||
767 | case L'u': |
||
768 | j = convert(n, 10, temp, false); |
||
769 | break; |
||
770 | case L'o': |
||
771 | j = convert(n, 8, temp, false); |
||
772 | break; |
||
773 | case L's': |
||
774 | j = 0; |
||
775 | if (arg) |
||
776 | { |
||
777 | if (flag == L'h') |
||
778 | j = DZ_MIN((int)strlen((const char *)arg), prec); |
||
779 | else |
||
780 | j = DZ_MIN((int)wcslen((const wchar_t *)arg), prec); |
||
781 | } |
||
782 | break; |
||
783 | case L'X': |
||
784 | upperXZ = true; |
||
785 | case L'x': |
||
786 | j = convert(n, 16, temp, upperXZ); |
||
787 | break; |
||
788 | case L'Z': |
||
789 | upperXZ = true; |
||
790 | case L'z': |
||
791 | j = convert(n, 36, temp, upperXZ); |
||
792 | break; |
||
793 | default: |
||
794 | //OutputDebugString(L"FormatV - error"); |
||
795 | wcscpy(temp, L"<<error>>"); |
||
796 | j = wcslen(temp); |
||
797 | } |
||
798 | |||
799 | if (!right && j < width) |
||
800 | { |
||
801 | if (zero) |
||
802 | { |
||
803 | _Append(zeros, width-j); |
||
804 | } |
||
805 | else |
||
806 | { |
||
807 | _Append(spaces, width-j); |
||
808 | } |
||
809 | i += width-j; |
||
810 | } |
||
811 | |||
812 | if (c == L's') |
||
813 | { |
||
814 | if (arg) |
||
815 | { |
||
816 | if (flag == L'h') |
||
817 | _Append((const char*)arg, j); |
||
818 | else |
||
819 | _Append((const wchar_t*)arg, j); |
||
820 | } |
||
821 | } |
||
822 | else |
||
823 | { |
||
824 | _Append(temp, j); |
||
825 | } |
||
826 | if (right) |
||
827 | _Append(spaces, width-j); |
||
828 | i += j; |
||
829 | } |
||
830 | return i; |
||
831 | } |
||
832 | |||
833 | int __fastcall DZStrW::Insert(unsigned pos, wchar_t ch) |
||
834 | { |
||
835 | if (!imp) |
||
836 | imp = _IMP_Data(NewImp(1)); |
||
837 | |||
838 | pos = DZ_MIN(pos, Length()); // limit to appending |
||
839 | |||
840 | wchar_t* bf = GetBuffer(Length() + 1); |
||
841 | wchar_t* stop = bf + pos; |
||
842 | wchar_t* p = bf + Length() + 2; |
||
843 | while (--p > stop) |
||
844 | *p = *(p - 1); |
||
845 | *p = ch; |
||
846 | dzstrw_imp* _imp = _IMP_Ptr(imp); |
||
847 | _imp->len = wcslen(_imp->data); |
||
848 | return (int)_imp->len; |
||
849 | } |
||
850 | |||
851 | wchar_t DZStrW::LastChar(void) const |
||
852 | { |
||
853 | if (!imp) |
||
854 | return 0; |
||
855 | return imp[Length()-1]; |
||
856 | } |
||
857 | |||
858 | DZStrW __fastcall DZStrW::Left(unsigned len) const |
||
859 | { |
||
860 | if (!imp) |
||
861 | return DZStrW(); |
||
862 | return DZStrW(imp, DZ_MIN(len, Length())); |
||
863 | } |
||
864 | |||
865 | DZStrW __fastcall DZStrW::Mid(unsigned pos, unsigned len) const |
||
866 | { |
||
867 | if (!imp || pos > Length()) |
||
868 | return DZStrW(); |
||
869 | return DZStrW(imp + pos, DZ_MIN(len, Length() - pos)); |
||
870 | } |
||
871 | |||
872 | |||
873 | int __fastcall DZStrW::ReverseFind(wchar_t ch, unsigned int pos) const |
||
874 | { |
||
875 | if (!imp) |
||
876 | return -1; |
||
877 | int i = Length(); |
||
878 | if (pos < (unsigned)i) |
||
879 | i = pos; |
||
880 | const wchar_t* p = &imp[i]; |
||
881 | while (i >= 0 && *p != ch) |
||
882 | { |
||
883 | i--; |
||
884 | p--; |
||
885 | } |
||
886 | return i; |
||
887 | } |
||
888 | |||
889 | DZStrA __fastcall DZStrW::SafeAnsi(void) const |
||
890 | { |
||
891 | int tmp; |
||
892 | return SafeAnsi(tmp); |
||
893 | } |
||
894 | |||
895 | DZStrA __fastcall DZStrW::SafeAnsi(int &bad) const |
||
896 | { |
||
897 | DZStrA tmp; |
||
898 | if (IsEmpty()) |
||
899 | return tmp; |
||
900 | |||
901 | bad = 0; |
||
902 | int subst = 0x1b; // substitute char - escape |
||
903 | int cnt = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, c_str(), Length(), NULL, 0, |
||
904 | (char*)&subst, &bad); |
||
905 | if (cnt > 0) |
||
906 | { |
||
907 | cnt = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, c_str(), Length(), |
||
908 | tmp.GetBuffer(cnt), cnt, (char*)&subst, &bad); |
||
909 | tmp.ReleaseBuffer(cnt); |
||
910 | } |
||
911 | if (!bad || !tmp) |
||
912 | return tmp; |
||
913 | |||
914 | DZStrA ret; |
||
915 | const char *pa = tmp.c_str(); |
||
916 | const char *good = 0; |
||
917 | cnt = 0; |
||
918 | int i = 0; |
||
919 | wchar_t wc = 0; |
||
920 | char c; |
||
921 | int wlen = Length(); |
||
922 | while ((c= *pa) != 0) |
||
923 | { |
||
924 | if (i < wlen) |
||
925 | wc = (*this)[i++]; |
||
926 | if (((unsigned char)c) < 0x20) |
||
927 | { |
||
928 | if (cnt) |
||
929 | { |
||
930 | ret._Append(good, cnt); |
||
931 | cnt = 0; |
||
932 | } |
||
933 | ret += "#$"; |
||
934 | ret += DZStrA(wc, 4); |
||
935 | } |
||
936 | else |
||
937 | { |
||
938 | if (!cnt) |
||
939 | good = pa; |
||
940 | cnt++; |
||
941 | } |
||
942 | pa = CharNextA(pa); |
||
943 | } |
||
944 | if (cnt) |
||
945 | { |
||
946 | ret._Append(good, cnt); |
||
947 | } |
||
948 | return ret; |
||
949 | } |
||
950 | |||
951 | DZStrA __fastcall DZStrW::SafeNarrow(unsigned cp) const |
||
952 | { |
||
953 | int tmp; |
||
954 | return SafeNarrow(cp, tmp); |
||
955 | } |
||
956 | |||
957 | DZStrA __fastcall DZStrW::SafeNarrow(unsigned cp, int &bad) const |
||
958 | { |
||
959 | DZStrA tmp; |
||
960 | if (IsEmpty()) |
||
961 | return tmp; |
||
962 | |||
963 | bad = 0; |
||
964 | int subst = 0x1b; // substitute char - escape |
||
965 | int cnt = WideCharToMultiByte(cp, WC_NO_BEST_FIT_CHARS, c_str(), Length(), NULL, 0, |
||
966 | (char*)&subst, &bad); |
||
967 | if (cnt > 0) |
||
968 | { |
||
969 | cnt = WideCharToMultiByte(cp, WC_NO_BEST_FIT_CHARS, c_str(), Length(), |
||
970 | tmp.GetBuffer(cnt), cnt, (char*)&subst, &bad); |
||
971 | tmp.ReleaseBuffer(cnt); |
||
972 | } |
||
973 | if (!bad || !tmp) |
||
974 | return tmp; |
||
975 | |||
976 | DZStrA ret; |
||
977 | const char *pa = tmp.c_str(); |
||
978 | const char *good = 0; |
||
979 | cnt = 0; |
||
980 | int i = 0; |
||
981 | wchar_t wc = 0; |
||
982 | char c; |
||
983 | int wlen = Length(); |
||
984 | while ((c= *pa) != 0) |
||
985 | { |
||
986 | if (i < wlen) |
||
987 | wc = (*this)[i++]; |
||
988 | if (((unsigned char)c) < 0x20) |
||
989 | { |
||
990 | if (cnt) |
||
991 | { |
||
992 | ret._Append(good, cnt); |
||
993 | cnt = 0; |
||
994 | } |
||
995 | ret += "#$"; |
||
996 | ret += DZStrA(wc, 4); |
||
997 | } |
||
998 | else |
||
999 | { |
||
1000 | if (!cnt) |
||
1001 | good = pa; |
||
1002 | cnt++; |
||
1003 | } |
||
1004 | pa = CharNextA(pa); |
||
1005 | } |
||
1006 | if (cnt) |
||
1007 | { |
||
1008 | ret._Append(good, cnt); |
||
1009 | } |
||
1010 | return ret; |
||
1011 | } |
||
1012 | |||
1013 | DZStrW& __fastcall DZStrW::ToUpper(void) |
||
1014 | { |
||
1015 | if (imp) |
||
1016 | { |
||
1017 | wchar_t * bf = GetBuffer(); |
||
1018 | CharUpperBuffW(bf, Length()); |
||
1019 | ReleaseBuffer(); |
||
1020 | } |
||
1021 | return *this; |
||
1022 | } |
||
1023 | |||
1024 | DZStrW& __fastcall DZStrW::Trim(void) |
||
1025 | { |
||
1026 | return TrimLeft().TrimRight(); |
||
1027 | } |
||
1028 | |||
1029 | DZStrW& __fastcall DZStrW::TrimLeft(void) |
||
1030 | { |
||
1031 | return TrimLeft(L' '); |
||
1032 | } |
||
1033 | |||
1034 | DZStrW& __fastcall DZStrW::TrimLeft(wchar_t ch) |
||
1035 | { |
||
1036 | if (imp && ch && *imp == ch) |
||
1037 | { |
||
1038 | // something to trim |
||
1039 | wchar_t* bf = GetBuffer(); // will make unique |
||
1040 | const wchar_t* p = bf; |
||
1041 | while (*p == ch) |
||
1042 | p++; |
||
1043 | if (!*p) |
||
1044 | { |
||
1045 | // we empty it |
||
1046 | Release(); |
||
1047 | } |
||
1048 | else |
||
1049 | { |
||
1050 | // move rest |
||
1051 | wchar_t tc; |
||
1052 | do |
||
1053 | { |
||
1054 | tc = *bf++ = *p++; |
||
1055 | } |
||
1056 | while (tc); |
||
1057 | // get new length |
||
1058 | dzstrw_imp* _imp = _IMP_Ptr(imp); |
||
1059 | _imp->len = wcslen(_imp->data); |
||
1060 | } |
||
1061 | } |
||
1062 | return *this; |
||
1063 | } |
||
1064 | |||
1065 | DZStrW& __fastcall DZStrW::TrimRight(void) |
||
1066 | { |
||
1067 | if (imp && imp[Length()-1] == ' ') |
||
1068 | { |
||
1069 | // something to trim |
||
1070 | wchar_t* bf = GetBuffer(); // will make unique |
||
1071 | wchar_t* p = bf + Length() - 1; |
||
1072 | while (p >= bf && *p == ' ') |
||
1073 | --p; |
||
1074 | // truncate it |
||
1075 | *++p = 0; |
||
1076 | if (p == bf) |
||
1077 | { |
||
1078 | // we empty it |
||
1079 | Release(); |
||
1080 | } |
||
1081 | else |
||
1082 | { |
||
1083 | // set new length |
||
1084 | dzstrw_imp* _imp = _IMP_Ptr(imp); |
||
1085 | _imp->len = wcslen(_imp->data); |
||
1086 | } |
||
1087 | } |
||
1088 | return *this; |
||
1089 | } |
||
1090 | |||
1091 | #ifdef DEBUG_COUNT |
||
1092 | int AliveCountA = 0; |
||
1093 | #endif |
||
1094 | |||
1095 | // min capacity = 25 chars, grow n * 32 |
||
1096 | dzstra_imp* __fastcall DZStrA::NewImp(unsigned siz) |
||
1097 | { |
||
1098 | unsigned datasize = siz * sizeof(char); |
||
1099 | unsigned rawsize = sizeof(dzstra_imp) + datasize; |
||
1100 | if (rawsize & 63) |
||
1101 | rawsize = (rawsize | 63) + 1; |
||
1102 | |||
1103 | dzstra_imp* _imp = (dzstra_imp*) (new char[rawsize]); |
||
1104 | if (! _imp) |
||
1105 | throw DZException(DZ_ERM_MEMORY); |
||
1106 | |||
1107 | _imp->refs = 1; |
||
1108 | _imp->capacity = (rawsize - sizeof(dzstra_imp)) / sizeof(char); |
||
1109 | _imp->len = 0; |
||
1110 | _imp->data[0] = 0; |
||
1111 | #ifdef DEBUG_COUNT |
||
1112 | AliveCountA++; |
||
1113 | #endif |
||
1114 | return _imp; |
||
1115 | } |
||
1116 | |||
1117 | dzstra_imp* __fastcall DZStrA::NewImp(const char* src, int maxLen) |
||
1118 | { |
||
1119 | int len = 0; |
||
1120 | if (src) |
||
1121 | len = strlen(src); |
||
1122 | |||
1123 | if (maxLen >= 0 && len > maxLen) |
||
1124 | len = maxLen; |
||
1125 | |||
1126 | if (!len) |
||
1127 | return NULL; // empty |
||
1128 | |||
1129 | dzstra_imp* nimp = NewImp(len >= maxLen ? len : maxLen); // make new |
||
1130 | strncpy(nimp->data, src, len); |
||
1131 | nimp->data[len] = 0; // mark end - in case |
||
1132 | nimp->len = strlen(nimp->data); |
||
1133 | return nimp; |
||
1134 | } |
||
1135 | |||
1136 | unsigned __fastcall DZStrA::_Capacity(dzstra_imp* _imp) const |
||
1137 | { |
||
1138 | if (_imp) |
||
1139 | return _imp->capacity; |
||
1140 | return 0; |
||
1141 | } |
||
1142 | |||
1143 | unsigned __fastcall DZStrA::Capacity(void) const |
||
1144 | { |
||
1145 | return _Capacity(_IMP_Ptr(imp)); |
||
1146 | } |
||
1147 | |||
1148 | unsigned __fastcall DZStrA::_Length(dzstra_imp* _imp) const |
||
1149 | { |
||
1150 | if (_imp) |
||
1151 | return _imp->len; |
||
1152 | return 0; |
||
1153 | } |
||
1154 | |||
1155 | unsigned __fastcall DZStrA::Length(void) const |
||
1156 | { |
||
1157 | return _Length(_IMP_Ptr(imp)); |
||
1158 | } |
||
1159 | |||
1160 | unsigned __fastcall DZStrA::_IncImpRefs(dzstra_imp* _imp) |
||
1161 | { |
||
1162 | if (_imp) |
||
1163 | return InterlockedIncrement(& (_imp->refs)); |
||
1164 | return 0; |
||
1165 | } |
||
1166 | |||
1167 | unsigned __fastcall DZStrA::_DecImpRefs(dzstra_imp* _imp) |
||
1168 | { |
||
1169 | if (_imp && _imp->refs) |
||
1170 | return InterlockedDecrement(& (_imp->refs)); |
||
1171 | return 0; |
||
1172 | } |
||
1173 | |||
1174 | void __fastcall DZStrA::_ReleaseImp(dzstra_imp* _imp) |
||
1175 | { |
||
1176 | if (!_DecImpRefs(_imp)) |
||
1177 | { |
||
1178 | delete[] _imp; |
||
1179 | #ifdef DEBUG_COUNT |
||
1180 | AliveCountA--; |
||
1181 | #endif |
||
1182 | } |
||
1183 | } |
||
1184 | |||
1185 | void __fastcall DZStrA::Release(void) |
||
1186 | { |
||
1187 | if (imp) |
||
1188 | { |
||
1189 | dzstra_imp* _imp = _IMP_Ptr(imp); |
||
1190 | imp = NULL; |
||
1191 | _ReleaseImp(_imp); |
||
1192 | } |
||
1193 | } |
||
1194 | |||
1195 | int __fastcall DZStrA::IncRefs(void) |
||
1196 | { |
||
1197 | if (imp) |
||
1198 | return _IncImpRefs(_IMP_Ptr(imp)); |
||
1199 | return 0; |
||
1200 | } |
||
1201 | |||
1202 | int __fastcall DZStrA::DecRefs(void) |
||
1203 | { |
||
1204 | if (imp) |
||
1205 | return _DecImpRefs(_IMP_Ptr(imp)); |
||
1206 | return -1; |
||
1207 | } |
||
1208 | |||
1209 | // maxSpace is max characters |
||
1210 | void __fastcall DZStrA::_Assign(const char* src, int maxLen) |
||
1211 | { |
||
1212 | Release(); |
||
1213 | imp = _IMP_Data(NewImp(src, maxLen)); |
||
1214 | } |
||
1215 | |||
1216 | void __fastcall DZStrA::_Append(const char* src, int maxLen) |
||
1217 | { |
||
1218 | dzstra_imp* _imp = _IMP_Ptr(imp); |
||
1219 | |||
1220 | unsigned len = 0; |
||
1221 | if (src) |
||
1222 | len = strlen(src); |
||
1223 | if (maxLen >= 0 && len > (unsigned)maxLen) |
||
1224 | len = maxLen; |
||
1225 | // check something to append |
||
1226 | if (len) |
||
1227 | { |
||
1228 | if (!imp) |
||
1229 | imp = _IMP_Data(NewImp(src, len)); |
||
1230 | else |
||
1231 | { |
||
1232 | unsigned oldlen = _imp->len; |
||
1233 | unsigned nlen = oldlen + len; |
||
1234 | |||
1235 | // do we need a new one |
||
1236 | if (_imp->refs > 1 || nlen > _imp->capacity) |
||
1237 | { |
||
1238 | // need new imp - make copy with enough space |
||
1239 | dzstra_imp* nimp = NewImp(_imp->data, nlen); |
||
1240 | Release(); // out with the old |
||
1241 | imp = _IMP_Data(nimp); // in with the new |
||
1242 | _imp = nimp; |
||
1243 | } |
||
1244 | // append data |
||
1245 | char *bf = &_imp->data[_imp->len]; |
||
1246 | strncpy(bf, src, len); |
||
1247 | bf[len] = 0; // mark end |
||
1248 | _imp->len = strlen(_imp->data); |
||
1249 | } |
||
1250 | } |
||
1251 | } |
||
1252 | |||
1253 | __fastcall DZStrA::DZStrA(const DZStrA& other) |
||
1254 | { |
||
1255 | imp = other.imp; |
||
1256 | IncRefs(); |
||
1257 | } |
||
1258 | |||
1259 | __fastcall DZStrA::DZStrA(const DZStrW& other) |
||
1260 | { |
||
1261 | imp = 0; |
||
1262 | int len;// = other.Length(); |
||
1263 | if (other && ((len = other.length()) >0)) |
||
1264 | { |
||
1265 | int alen = len + (len / 2); // just in case |
||
1266 | // make new imp with enough space |
||
1267 | dzstra_imp* _imp = NewImp(alen); |
||
1268 | imp = _IMP_Data(_imp); // new |
||
1269 | int cnt = WideCharToMultiByte(0, WC_NO_BEST_FIT_CHARS, other.c_str(), |
||
1270 | len, imp, alen, NULL, NULL); |
||
1271 | _imp->data[cnt] = 0; |
||
1272 | _imp->len = strlen(_imp->data); |
||
1273 | } |
||
1274 | } |
||
1275 | |||
1276 | __fastcall DZStrA::DZStrA(const char* str, int len) |
||
1277 | { |
||
1278 | imp = _IMP_Data(NewImp(str, len)); |
||
1279 | } |
||
1280 | |||
1281 | __fastcall DZStrA::DZStrA(const wchar_t* wstr) |
||
1282 | { |
||
1283 | int len; |
||
1284 | imp = 0; |
||
1285 | if (wstr && ((len = wcslen(wstr)) > 0)) |
||
1286 | { |
||
1287 | int alen = len + (len / 2); // just in case |
||
1288 | // make new imp with enough space |
||
1289 | dzstra_imp* nimp = NewImp(alen); |
||
1290 | imp = _IMP_Data(nimp); // new |
||
1291 | int cnt = WideCharToMultiByte(0, WC_NO_BEST_FIT_CHARS, wstr, len, imp, |
||
1292 | alen, NULL, NULL); |
||
1293 | nimp->data[cnt] = 0; |
||
1294 | nimp->len = strlen(nimp->data); |
||
1295 | } |
||
1296 | } |
||
1297 | |||
1298 | const char hx[16] = "0123456789ABCDEF"; |
||
1299 | __fastcall DZStrA::DZStrA(unsigned val, unsigned cnt) |
||
1300 | { |
||
1301 | imp = _IMP_Data(NewImp(cnt)); |
||
1302 | |||
1303 | char* bp = imp + cnt; |
||
1304 | int x = cnt; |
||
1305 | *bp = 0; |
||
1306 | while (val && x-- > 0) |
||
1307 | { |
||
1308 | *--bp = hx[val & 0x0f]; |
||
1309 | val >>= 4; |
||
1310 | } |
||
1311 | while (bp > imp) |
||
1312 | *--bp = '0'; |
||
1313 | } |
||
1314 | |||
1315 | DZStrA& __fastcall DZStrA::operator =(const DZStrA& other) |
||
1316 | { |
||
1317 | if (this != &other) |
||
1318 | { |
||
1319 | Release(); |
||
1320 | imp = other.imp; |
||
1321 | IncRefs(); |
||
1322 | } |
||
1323 | return *this; |
||
1324 | } |
||
1325 | |||
1326 | DZStrA& __fastcall DZStrA::operator =(const char* str) |
||
1327 | { |
||
1328 | Release(); |
||
1329 | imp = _IMP_Data(NewImp(str, -1)); |
||
1330 | return *this; |
||
1331 | } |
||
1332 | |||
1333 | DZStrA __fastcall DZStrA::operator +(const DZStrA& other) |
||
1334 | { |
||
1335 | DZStrA res(*this); |
||
1336 | res._Append(other.c_str(), -1); |
||
1337 | return res; |
||
1338 | } |
||
1339 | |||
1340 | DZStrA __fastcall DZStrA::operator +(const char* str) |
||
1341 | { |
||
1342 | DZStrA res(*this); |
||
1343 | res._Append(str, -1); |
||
1344 | return res; |
||
1345 | } |
||
1346 | |||
1347 | DZStrA& __fastcall DZStrA::operator +=(const DZStrA& other) |
||
1348 | { |
||
1349 | _Append(other.c_str(), -1); |
||
1350 | return *this; |
||
1351 | } |
||
1352 | |||
1353 | DZStrA& __fastcall DZStrA::operator +=(const char* str) |
||
1354 | { |
||
1355 | _Append(str, -1); |
||
1356 | return *this; |
||
1357 | } |
||
1358 | |||
1359 | DZStrA& __fastcall DZStrA::operator +=(char ch) |
||
1360 | { |
||
1361 | char buf[2]; |
||
1362 | buf[0] = ch; |
||
1363 | buf[1] = 0; |
||
1364 | _Append(buf, 1); |
||
1365 | return *this; |
||
1366 | } |
||
1367 | |||
1368 | char __fastcall DZStrA::operator [](unsigned idx) const |
||
1369 | { |
||
1370 | if (!imp || idx >= Length()) |
||
1371 | return 0; |
||
1372 | return *(imp + idx); |
||
1373 | } |
||
1374 | |||
1375 | __fastcall DZStrA::~DZStrA(void) |
||
1376 | { |
||
1377 | Release(); |
||
1378 | } |
||
1379 | |||
1380 | char * __fastcall DZStrA::GetBuffer(int minsize) |
||
1381 | { |
||
1382 | dzstra_imp* _imp = _IMP_Ptr(imp); |
||
1383 | |||
1384 | int nlen = _imp ? _imp->len : 0; |
||
1385 | if (minsize >= 0) |
||
1386 | nlen = minsize; |
||
1387 | // need new imp - make copy with enough space |
||
1388 | dzstra_imp* nimp; |
||
1389 | if (!_imp) |
||
1390 | nimp = NewImp(nlen); |
||
1391 | else |
||
1392 | { |
||
1393 | nimp = NewImp(_imp->data, nlen); |
||
1394 | Release(); // out with the old |
||
1395 | } |
||
1396 | imp = _IMP_Data(nimp); // in with the new |
||
1397 | return imp; |
||
1398 | } |
||
1399 | |||
1400 | void __fastcall DZStrA::ReleaseBuffer(int newlen) |
||
1401 | { |
||
1402 | if (imp) |
||
1403 | { |
||
1404 | dzstra_imp* _imp = _IMP_Ptr(imp); |
||
1405 | _imp->data[_imp->capacity] = 0; //ensure end marked |
||
1406 | int len = strlen(imp); |
||
1407 | if (newlen >=0 && newlen < len) { |
||
1408 | len = newlen; |
||
1409 | _imp->data[len] = 0; // truncate |
||
1410 | } |
||
1411 | _imp->len = len; |
||
1412 | } |
||
1413 | } |
||
1414 | |||
1415 | bool __fastcall DZStrA::BadDOS(void) const |
||
1416 | { |
||
1417 | if (IsEmpty()) |
||
1418 | return false; |
||
1419 | |||
1420 | char tmp; |
||
1421 | for (const char* p = imp; (tmp = *p) != 0; p++) |
||
1422 | if (tmp < 32 || tmp > 126) |
||
1423 | return true; |
||
1424 | return false; |
||
1425 | } |
||
1426 | |||
1427 | int __fastcall DZStrA::Compare(const char* other) const |
||
1428 | { |
||
1429 | if (!imp) |
||
1430 | return (other && *other)? -1 : 0; |
||
1431 | if (!other || !*other) |
||
1432 | return -1; |
||
1433 | |||
1434 | return strcmp(imp, other); |
||
1435 | } |
||
1436 | |||
1437 | |||
1438 | |||
1439 | int __fastcall DZStrA::CompareNoCase(const char* other) const |
||
1440 | { |
||
1441 | if (!imp) |
||
1442 | return (other && *other)? -1 : 0; |
||
1443 | if (!other || !*other) |
||
1444 | return -1; |
||
1445 | |||
1446 | DZStrA me(*this); |
||
1447 | me.ToUpper(); |
||
1448 | DZStrA theOther(other); |
||
1449 | theOther.ToUpper(); |
||
1450 | return strcmp(me.imp, theOther.imp); |
||
1451 | } |
||
1452 | |||
1453 | |||
1454 | int __fastcall DZStrA::Find(char ch) const |
||
1455 | { |
||
1456 | if (!imp) |
||
1457 | return -1; |
||
1458 | |||
1459 | int i = 0; |
||
1460 | for (const char* p = imp; *p && *p != ch; p++) |
||
1461 | i++; |
||
1462 | return (unsigned)i >= Length() ? -1 : i; |
||
1463 | } |
||
1464 | |||
1465 | int __fastcall DZStrA::FindOneOf(const char *chars, unsigned start) const |
||
1466 | { |
||
1467 | if (!imp || start > Length()) |
||
1468 | return -1; |
||
1469 | |||
1470 | int i = start; |
||
1471 | for (const char* p = &imp[start]; *p; p++) |
||
1472 | { |
||
1473 | bool found = false; |
||
1474 | char ch = *p; |
||
1475 | for (const char* q = chars; *q; q++) |
||
1476 | { |
||
1477 | if (*q == ch) |
||
1478 | { |
||
1479 | found = true; |
||
1480 | break; |
||
1481 | } |
||
1482 | } |
||
1483 | if (found) |
||
1484 | break; |
||
1485 | i++; |
||
1486 | } |
||
1487 | return (unsigned)i >= Length() ? -1 : i; |
||
1488 | } |
||
1489 | |||
1490 | |||
1491 | DZStrA __fastcall DZStrA::Left(unsigned len) const |
||
1492 | { |
||
1493 | if (!imp) |
||
1494 | return DZStrA(); |
||
1495 | return DZStrA(imp, DZ_MIN(len, Length())); |
||
1496 | } |
||
1497 | |||
1498 | DZStrA __fastcall DZStrA::Mid(unsigned pos, unsigned len) const |
||
1499 | { |
||
1500 | if (!imp || pos > Length()) |
||
1501 | return DZStrA(); |
||
1502 | return DZStrA(imp + pos, DZ_MIN(len, Length() - pos)); |
||
1503 | } |
||
1504 | |||
1505 | int __fastcall DZStrA::ReverseFind(char ch, unsigned int pos) const |
||
1506 | { |
||
1507 | if (!imp) |
||
1508 | return -1; |
||
1509 | int i = Length(); |
||
1510 | if (pos < (unsigned)i) |
||
1511 | i = pos; |
||
1512 | const char* p = &imp[i]; |
||
1513 | while (i >= 0 && *p != ch) |
||
1514 | { |
||
1515 | i--; |
||
1516 | p--; |
||
1517 | } |
||
1518 | return i; |
||
1519 | } |
||
1520 | |||
1521 | |||
1522 | DZStrA& __fastcall DZStrA::ToUpper(void) |
||
1523 | { |
||
1524 | if (imp) |
||
1525 | { |
||
1526 | char * bf = GetBuffer(); // make unique |
||
1527 | CharUpperBuffA(bf, Length()); |
||
1528 | ReleaseBuffer(); |
||
1529 | } |
||
1530 | return *this; |
||
1531 | } |
||
1532 |