DCL 3.7.4
Loading...
Searching...
No Matches
__STRING.cpp
Go to the documentation of this file.
1#ifdef __DCL_INTERNAL__
2
3#undef _T
4#undef CHAR_T
5#undef UCHAR_T
6#undef BUFFER_T
7#undef STRING_T
8#undef ARRAY_T
9
10#undef STRLEN
11#undef STRCMP
12#undef STRNCMP
13#undef STRCASECMP
14#undef STRNCASECMP
15#undef VSNPRINTF
16#undef STRCHR
17#undef STRSTR
18#undef ISSPACE
19#undef ISALNUM
20#undef TOUPPER
21#undef TOLOWER
22#undef TOUPPER_L
23#undef TOLOWER_L
24
25#ifdef __DCL_COMPILE_UNICODE__
26 #define _T(s) L ## s
27 #define CHAR_T wchar_t
28 #define UCHAR_T wint_t
29 #define BUFFER_T CharBuffer
30 #define STRING_T String
31 #define ARRAY_T StringArray
32 #define STRING_BUILDER_T StringBuilder
33
34 #define STRLEN(s) wcslen(s)
35 #define STRCMP(s1, s2) wcscmp(s1, s2)
36 #define STRNCMP(s1, s2, n) wcsncmp(s1, s2, n)
37
38 #ifdef __WINNT__
39 #define STRCASECMP(s1, s2) _wcsicmp(s1, s2)
40 #define STRNCASECMP(s1, s2, n) _wcsnicmp(s1, s2, n)
41 #define VSNPRINTF(buf, len, fmt, args) _vsnwprintf(buf, len, fmt, args)
42 #else
43 #define STRCASECMP(s1, s2) wcscasecmp(s1, s2)
44 #define STRNCASECMP(s1, s2, n) wcsncasecmp(s1, s2, n)
45 #define VSNPRINTF(buf, len, fmt, args) vswprintf(buf, len, fmt, args)
46 #endif
47
48 #define STRCHR(s, c) wcschr(s, c)
49 #define STRSTR(s, cs) wcsstr(s, cs)
50 #define ISSPACE(c) iswspace(c)
51 #define ISALNUM(c) iswalnum(c)
52 #define TOUPPER(c) towupper(c)
53 #define TOLOWER(c) towlower(c)
54 #define TOUPPER_L(c, l) towupper(c, l)
55 #define TOLOWER_L(c, l) towlower(c, l)
56#else // __DCL_COMPILE_UNICODE__
57 #define _T(s) s
58 #define CHAR_T char
59 #define UCHAR_T unsigned char
60 #define BUFFER_T ByteBuffer
61 #define STRING_T ByteString
62 #define ARRAY_T ByteStringArray
63 #define STRING_BUILDER_T ByteStringBuilder
64
65 #define STRLEN(s) strlen(s)
66 #define STRCMP(s1, s2) strcmp(s1, s2)
67 #define STRNCMP(s1, s2, n) strncmp(s1, s2, n)
68
69 #ifdef __WINNT__
70 #define STRCASECMP(s1, s2) _stricmp(s1, s2)
71 #define STRNCASECMP(s1, s2, n) _strnicmp(s1, s2, n)
72 #define VSNPRINTF(buf, len, fmt, args) _vsnprintf(buf, len, fmt, args)
73 #else
74 #define STRCASECMP(s1, s2) strcasecmp(s1, s2)
75 #define STRNCASECMP(s1, s2, n) strncasecmp(s1, s2, n)
76 #define VSNPRINTF(buf, len, fmt, args) vsnprintf(buf, len, fmt, args)
77 #endif
78
79 #define STRCHR(s, c) strchr(s, c)
80 #define STRSTR(s, cs) strstr(s, cs)
81 #define ISSPACE(c) isspace(c)
82 #define ISALNUM(c) isalnum(c)
83 #define TOUPPER(c) toupper(c)
84 #define TOLOWER(c) tolower(c)
85 #define TOUPPER_L(c, l) toupper_l(c, l)
86 #define TOLOWER_L(c, l) tolower_l(c, l)
87#endif
88
89#if __DCL_HAVE_THIS_FILE__
90 #undef __THIS_FILE__
91 static const char_t __CONCAT(__sz_STRING_T_cpp, CHAR_T)[] =
92 __CONCAT_TEXT("dcl/__STRING.cpp/", CHAR_T);
93 #define __THIS_FILE__ __CONCAT(__sz_STRING_T_cpp, CHAR_T)
94#endif
95
97{
99 return n;
100}
101
103{
104 __DCL_ASSERT_PARAM(__refCount > 0); // __DCL_ASSERT_VALID(this);
106 if (n == 0)
107 BUFFER_T::destroy(this);
108 return n;
109}
110
111#ifndef __EXTENDED_LENGTH_DEFINED
112#define __EXTENDED_LENGTH_DEFINED
113size_t __extended_length(size_t _allocLength)
114{
115 if (_allocLength <= 32)
116 _allocLength = 32;
117 else if (_allocLength <= 64)
118 _allocLength = 64;
119 else if (_allocLength <= 128)
120 _allocLength = 128;
121 else if (_allocLength <= 256)
122 _allocLength = 256;
123 else if (_allocLength <= 512)
124 _allocLength = 512;
125 else if (_allocLength <= 1024)
126 _allocLength = 1024;
127 else {
128 size_t m = _allocLength / 2048;
129 if (_allocLength % 2048)
130 m++;
131 _allocLength = m * 2048;
132 }
133 return _allocLength;
134}
135#endif
136
137#if defined(__GNUC__) && !defined(__clang__)
138#pragma GCC diagnostic push
139#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
140#endif
142{
143 free(_buf);
144}
145#if defined(__GNUC__) && !defined(__clang__)
146#pragma GCC diagnostic pop
147#endif
148
150{
151 BUFFER_T* buf = (BUFFER_T*)
152 malloc(sizeof(BUFFER_T) + (sizeof(CHAR_T) * (_len + 1)));
153
154 if (buf) {
155 buf->__refCount = 1;
156 buf->__allocLength = _len;
157 buf->__dataLength = 0;
158 buf->data()[buf->__dataLength] = _T('\0');
159 }
160 /*
161 else {
162 throw BadAllocException
163 }
164 */
165 return buf;
166}
167
169{
171}
172
173void BUFFER_T::extend(BUFFER_T*& _buf, size_t _len)
174{
175 __DCL_ASSERT_PARAM(_buf != NULL);
176 __DCL_ASSERT_PARAM(_buf->__allocLength < _len);
177
178 _len = __extended_length(_len);
179
180 BUFFER_T* buf = (BUFFER_T*)
181 realloc(_buf, sizeof(BUFFER_T) + (sizeof(CHAR_T) * (_len + 1)));
182
183 // buf와 _buf는 같지 않을 수 있다.
184 if (buf) {
185 _buf = buf;
186 _buf->__allocLength = _len;
187 }
188 /*
189 else {
190 throw BadAllocException
191 }
192 */
193}
194
196{
197 __DCL_ASSERT_PARAM(_buf != NULL);
198 if (_buf->__dataLength < _buf->__allocLength) {
199 size_t _len = _buf->__dataLength;
200 BUFFER_T* buf = (BUFFER_T*)
201 realloc(_buf, sizeof(BUFFER_T) + (sizeof(CHAR_T) * (_len + 1)));
202
203 if (buf) {
204 _buf = buf;
205 _buf->__allocLength = _len;
206 _buf->data()[_buf->__dataLength] = _T('\0');
207 }
208 else {
209 // throw new BadAllocException
210 }
211 }
212}
213
214void BUFFER_T::write(BUFFER_T*& _buf, const CHAR_T* _p, size_t _len)
215{
216 size_t avail = _buf->__allocLength - _buf->__dataLength;
217 if (avail < _len) {
218 BUFFER_T::extend(_buf, _buf->__allocLength + _len);
219 }
220 memcpy(_buf->data() + _buf->__dataLength, _p, _len * sizeof(CHAR_T));
221 _buf->__dataLength += _len;
222 _buf->data()[_buf->__dataLength] = _T('\0');
223}
224
226{
227 write(_buf, &_ch, 1);
228}
229
230int BUFFER_T::vformat(BUFFER_T*& _buf, const CHAR_T* _format, va_list _arglist)
231{
232 __DCL_ASSERT_PARAM(_format != NULL);
233
234#if defined(__DCL_COMPILE_UNICODE__) && defined(_MSC_VER)
235 String format;
236 if (STRSTR(_format, L"%s")) {
237 __DCL_TRACE3(L"Warning!! vformat _format [%ls] included [%ls]. replaced to [%ls]\n",
238 _format, L"%s", L"%hs");
239 format.assign(_format);
240 format = format.replace(L"%s", L"%hs");
241 _format = format;
242 }
243#endif
244
245#define __EXTENDED_MAX 1024 * 1024
246#define __EXTEND_MIN 32
247 int n = 0;
248 size_t extend = __MAX(_buf->__allocLength - _buf->__dataLength, __EXTEND_MIN);
249 size_t extended = _buf->__dataLength + extend;
250 while (extended < __EXTENDED_MAX) {
251 if (_buf->__allocLength < extended) {
252 BUFFER_T::extend(_buf, extended);
253 }
254
255 va_list arglist;
256 va_copy(arglist, _arglist);
257 n = VSNPRINTF(
258 _buf->data() + _buf->__dataLength,
259 _buf->__allocLength - _buf->__dataLength,
260 _format,
261 arglist
262 );
263 va_end(arglist);
264
265 // 버퍼가 부족한 경우, MSVC는 -1을 반환한다.
266 // GNUC는 버퍼의 size로 문자열이 잘려지고, 만들어진 문자의 개수를 반환한다.
267 // GNUC의 경우 arg 중 하나라도 문자열의 길이가 버퍼보다 길면 -1을 반환한다.
268 if (0 <= n && (size_t)n <= (_buf->__allocLength - _buf->__dataLength)) {
269 _buf->__dataLength += n;
270 _buf->data()[_buf->__dataLength] = _T('\0');
271 return n;
272 }
273
274 extend *= 2;
275 if (n > 0) {
276 extend = __MAX(extend, n);
277 }
278 extended += extend;
279 __DCL_TRACE2(__T("VSNPRINTF Failed(%d) extend[%zd] and Retry\n"), n, extend);
280 }
281 // throw new BadAllocException;
282
283 // EXTEND_MAX 10MB 만큼 버퍼를 할당했음에도 불구하고 VSNPRINTF를 실패했다.
284 __DCL_TRACE2(__T("Warning!! VSNPRINTF Failed(%d) extend[%zd]\n"), n, extend);
285 return n;
286}
287
288#undef __EMPTY_STR
289#undef __EMPTY
290
291static const struct __CONCAT(__EMPTY_STRING, CHAR_T) {
292 BUFFER_T __buf;
293 CHAR_T __nil;
294} __CONCAT(__empty__, CHAR_T) = { {0, 0, 0}, _T('\0') };
295
296#define __EMPTY_STR __CONCAT(__empty, CHAR_T)
298 return ((CHAR_T*)& __CONCAT(__empty__, CHAR_T).__nil);
299}
300
301#define __EMPTY __EMPTY_STR()
302
303void STRING_T::assignAlloc(size_t _len)
304{
305 __DCL_ASSERT_PARAM(_len > 0);
306
307 BUFFER_T* buf = __buf();
308 if (buf->__refCount == 0) {
310 buf = BUFFER_T::create(_len);
311 }
312 else {
314 buf->release();
315 buf = BUFFER_T::create(_len);
316 }
317 __psz = buf->data();
318 // assignAlloc을 호출한 곳에는 '\0' 설정하지 않는다.
319 __psz[_len] = _T('\0');
320}
321
323{
324 if (__psz != __EMPTY) {
325 __DCL_ASSERT(__buf()->__refCount != 0);
326 __buf()->release();
327 }
328}
329
334
336{
337 __DCL_ASSERT_PARAM(_buf != NULL);
338 __DCL_ASSERT(_buf->__refCount >= 1);
339
340 __psz = __EMPTY;
341 assign(_buf);
342}
343
345{
346 __psz = __EMPTY;
347 assign(_str);
348}
349
350STRING_T::STRING_T(CHAR_T _ch, size_t _repeat) // = 1);
351{
352 __psz = __EMPTY;
353 assign(_ch, _repeat);
354}
355
356STRING_T::STRING_T(const CHAR_T* _psz, size_t _start, size_t _len)
357{
358 __psz = __EMPTY;
359 assign(_psz, _start, _len);
360}
361
362STRING_T::STRING_T(const CHAR_T* _psz, size_t _len) // = (size_t)-1 )
363{
364 __psz = __EMPTY;
365 assign(_psz, _len);
366}
367
368STRING_T::STRING_T(const CHAR_T* _begin, const CHAR_T* _end)
369{
370 __psz = __EMPTY;
371 assign(_begin, _end);
372}
373
375{
376 __DCL_ASSERT_PARAM(_buf != NULL);
377 __DCL_ASSERT(_buf->__refCount >= 1);
378 if (__psz != _buf->data()) {
379 if (__psz != __EMPTY)
380 __buf()->release();
381 __psz = _buf->data();
382 _buf->addRef();
383 }
384 return *this;
385}
386
388{
389 if (__psz != _str.__psz) {
390 if (_str.__buf()->__refCount > 0) {
391 __DCL_ASSERT(_str.__psz != __EMPTY);
392 if (__psz != __EMPTY)
393 __buf()->release();
394 __psz = _str.__psz;
395 __buf()->addRef();
396 }
397 else {
398 // -1, 0
399 assign(_str, _str.length());
400 }
401 }
402 return *this;
403}
404
405STRING_T& STRING_T::assign(CHAR_T _ch, size_t _repeat) // = 1)
406{
407 if (_repeat) {
408 assignAlloc(_repeat);
409
410 CHAR_T* p = __psz;
411 CHAR_T* _end = p + _repeat;
412 while(p < _end)
413 *p++ = _ch;
414
415 __buf()->__dataLength = _repeat;
416 __DCL_ASSERT(__psz[_repeat] == _T('\0'));
417 }
418 else
419 clear();
420
421 return *this;
422}
423
424STRING_T& STRING_T::assign(const CHAR_T* _ps, size_t _start, size_t _len)
425{
426 __DCL_ASSERT_PARAM(_ps != NULL);
427 if (_len) {
428 assignAlloc(_len);
429
430 memcpy(__psz, _ps + _start, _len * sizeof(CHAR_T));
431
432 __buf()->__dataLength = _len;
433 __DCL_ASSERT(__psz[_len] == _T('\0'));
434 }
435 else
436 clear();
437
438 return *this;
439}
440
441STRING_T& STRING_T::assign(const CHAR_T* _psz, size_t _len) // = (size_t)-1);
442{
443 if (_len == (size_t)-1)
444 _len = STRING_T::length(_psz);
445 return assign(_psz, 0, _len);
446}
447
448STRING_T& STRING_T::assign(const CHAR_T* _begin, const CHAR_T* _end)
449{
450 __DCL_ASSERT_PARAM(_begin <= _end);
451 return assign(_begin, 0, _end - _begin);
452}
453
455 const CHAR_T* _ps1, size_t _len1,
456 const CHAR_T* _ps2, size_t _len2
457)
458{
459 __DCL_ASSERT_PARAM(_ps1 != NULL && _ps2 != NULL);
460
461 size_t _len = _len1 + _len2;
462 if (_len) {
463 assignAlloc(_len);
464
465 memcpy(__psz, _ps1, _len1 * sizeof(CHAR_T));
466 memcpy(__psz + _len1, _ps2, _len2 * sizeof(CHAR_T));
467
468 __buf()->__dataLength = _len;
469 __DCL_ASSERT(__psz[_len] == _T('\0'));
470 }
471 else
472 clear();
473}
474
476{
477 if (__psz != __EMPTY) {
478 __buf()->release();
479 __psz = __EMPTY;
480 }
481}
482
483DCLCAPI STRING_T operator + (const STRING_T& _str1, const STRING_T& _str2)
484{
485 STRING_T r;
486 r.assign(_str1, _str1.length(), _str2, _str2.length());
487 return r;
488}
489
491{
492 STRING_T r;
493 r.assign(_str, _str.length(), &_ch, 1);
494 return r;
495}
496
498{
499 STRING_T r;
500 r.assign(&_ch, 1, _str, _str.length());
501 return r;
502}
503
504DCLCAPI STRING_T operator + (const STRING_T& _str, const CHAR_T* _psz)
505{
506 __DCL_ASSERT_PARAM(_psz != NULL);
507 STRING_T r;
508 r.assign(_str, _str.length(), _psz, STRING_T::length(_psz));
509 return r;
510}
511
512DCLCAPI STRING_T operator + (const CHAR_T* _psz, const STRING_T& _str)
513{
514 __DCL_ASSERT_PARAM(_psz != NULL);
515 STRING_T r;
516 r.assign(_psz, STRING_T::length(_psz), _str, _str.length());
517 return r;
518}
519
520// return (size_t)-1 not found
521size_t STRING_T::indexOf(CHAR_T _ch, size_t _start) const
522{
523 __DCL_ASSERT_PARAM(_start <= length());
524 const CHAR_T* p = STRING_T::find(__psz + _start,
525 __psz + length(), _ch);
526 if (p)
527 return p - __psz;
528 return (size_t)-1;
529}
530
531size_t STRING_T::indexOf(const CHAR_T* _psz, size_t _start) const
532{
533 __DCL_ASSERT_PARAM(_start <= length());
534 __DCL_ASSERT_PARAM(_psz != NULL);
535
536 const CHAR_T* p = STRSTR(__psz + _start, _psz);
537 if (p)
538 return p - __psz;
539 return (size_t)-1;
540}
541
542size_t STRING_T::indexOf(const STRING_T& _str, size_t _start) const
543{
544 __DCL_ASSERT_PARAM(_start <= length());
545 const CHAR_T* p = STRING_T::find(
546 __psz + _start, __psz + length(),
547 _str, _str.length()
548 );
549 if (p)
550 return p - __psz;
551 return (size_t)-1;
552}
553
554size_t STRING_T::lastIndexOf(CHAR_T _ch, size_t _start) const
555{
556 __DCL_ASSERT_PARAM(_start <= length());
557 const CHAR_T* p = STRING_T::rfind(
558 __psz, __psz + length() - _start,
559 _ch
560 );
561 if (p)
562 return p - __psz;
563 return (size_t)-1;
564}
565
566size_t STRING_T::lastIndexOf(const CHAR_T* _psz, size_t _start) const
567{
568 __DCL_ASSERT_PARAM(_start <= length());
569 __DCL_ASSERT_PARAM(_psz != NULL);
570 const CHAR_T* p = STRING_T::rfind(
571 __psz, __psz + length() - _start,
572 _psz, STRING_T::length(_psz)
573 );
574 if (p)
575 return p - __psz;
576 return (size_t)-1;
577}
578
579size_t STRING_T::lastIndexOf(const STRING_T& _str, size_t _start) const
580{
581 __DCL_ASSERT_PARAM(_start <= length());
582 const CHAR_T* p = STRING_T::rfind(
583 __psz, __psz + length() - _start,
584 _str, _str.length()
585 );
586 if (p)
587 return p - __psz;
588 return (size_t)-1;
589}
590
592 const CHAR_T* psz1,
593 const CHAR_T* psz2, size_t _len // = (size_t)-1);
594)
595{
596 __DCL_ASSERT_PARAM(psz1 != NULL && psz2 != NULL);
597
598 if (_len == (size_t)-1)
599 return STRCMP(psz1, psz2);
600 else
601 return STRNCMP(psz1, psz2, _len);
602}
603
605 const CHAR_T* psz1,
606 const CHAR_T* psz2, size_t _len // = (size_t)-1);
607)
608{
609 __DCL_ASSERT_PARAM(psz1 != NULL && psz2 != NULL);
610
611 if (_len == (size_t)-1)
612 return STRCASECMP(psz1, psz2);
613 else
614 return STRNCASECMP(psz1, psz2, _len);
615}
616
618 size_t _first, size_t _len // = (size_t)-1) const;
619) const
620{
621 __DCL_ASSERT_PARAM(_first <= length());
622
623 if (_len == (size_t)-1)
624 _len = length() - _first;
625
626 __DCL_ASSERT((_first + _len) <= length());
627
628 if (_first == 0 && _len == length())
629 return *this;
630
631 return STRING_T(__psz, _first, _len);
632}
633
634STRING_T STRING_T::left(size_t _len) const
635{
636 return mid(0, _len);
637}
638
639STRING_T STRING_T::right(size_t _len) const
640{
641 if (length() < _len)
642 _len = length();
643 return mid(length() - _len, _len);
644}
645
646STRING_T STRING_T::padCenter(size_t _len, CHAR_T _ch) const
647{
648 if (_len <= length()) {
649 return mid((length() - _len) / 2, _len);
650 }
651
652 BUFFER_T* buf = BUFFER_T::create(_len);
653 buf->__dataLength = _len;
654
655 CHAR_T* dst = buf->data();
656 CHAR_T* end = dst + ((_len - length()) / 2);
657 while (dst < end) {
658 *dst++ = _ch;
659 }
660
661 end = dst + length();
662 const CHAR_T* src = __psz;
663 while (dst < end) {
664 *dst++ = *src++;
665 }
666
667 end = buf->data() + _len;
668 *end = _T('\0');
669 while (dst < end) {
670 *dst++ = _ch;
671 }
672 __DCL_ASSERT(*(buf->data() + _len) == _T('\0'));
673
674 STRING_T r = buf;
675 buf->release();
676 return r;
677}
678
679STRING_T STRING_T::padLeft(size_t _len, CHAR_T _ch) const
680{
681 if (_len <= length()) {
682 return mid(length() - _len, _len);
683 }
684
685 BUFFER_T* buf = BUFFER_T::create(_len);
686 buf->__dataLength = _len;
687
688 CHAR_T* dst = buf->data();
689 CHAR_T* end = dst + (_len - length());
690 while (dst < end) {
691 *dst++ = _ch;
692 }
693
694 end = buf->data() + _len;
695 *end = _T('\0');
696 const CHAR_T* src = __psz;
697 while (dst < end) {
698 *dst++ = *src++;
699 }
700
701 __DCL_ASSERT(*(buf->data() + _len) == _T('\0'));
702
703 STRING_T r = buf;
704 buf->release();
705 return r;
706}
707
708STRING_T STRING_T::padRight(size_t _len, CHAR_T _ch) const
709{
710 if (_len <= length()) {
711 return mid(0, _len);
712 }
713
714 BUFFER_T* buf = BUFFER_T::create(_len);
715 buf->__dataLength = _len;
716
717 CHAR_T* dst = buf->data();
718 CHAR_T* end = dst + length();
719 const CHAR_T* src = __psz;
720 while (dst < end) {
721 *dst++ = *src++;
722 }
723
724 end = buf->data() + _len;
725 *end = _T('\0');
726 while (dst < end) {
727 *dst++ = _ch;
728 }
729 __DCL_ASSERT(*(buf->data() + _len) == _T('\0'));
730
731 STRING_T r = buf;
732 buf->release();
733 return r;
734}
735
737 size_t _start, size_t _len,
738 const CHAR_T* _new, size_t _newlen
739) const
740{
741 __DCL_ASSERT_PARAM((_start + _len) <= length());
742 __DCL_ASSERT_PARAM(_new != NULL);
743
744 if (_newlen == (size_t)-1)
745 _newlen = STRING_T::length(_new);
746
747 size_t len = length() - _len + _newlen;
748 BUFFER_T* buf = BUFFER_T::create(len);
749 buf->__dataLength = len;
750 CHAR_T* p = buf->data();
751 *(p + len) = _T('\0');
752
753 memcpy(p, __psz, _start * sizeof(CHAR_T));
754 memcpy(p + _start, _new, _newlen * sizeof(CHAR_T));
755 memcpy(p + _start + _newlen, __psz + _start + _len,
756 (length() - (_start + _len)) * sizeof(CHAR_T));
757
758 __DCL_ASSERT(p[buf->__dataLength] == _T('\0'));
759
760 STRING_T r(buf);
761 buf->release();
762 return r;
763}
764
766 size_t _start, size_t _len,
767 const CHAR_T* _new, size_t _newlen
768) const
769{
770 __DCL_ASSERT_PARAM((_start + _len) <= length());
771 __DCL_ASSERT_PARAM(_new != NULL);
772 return replace(length() - _start - _len, _len, _new, _newlen);
773}
774
776{
777 if (_old == _new || __psz == __EMPTY) {
778 return *this;
779 }
780
781 BUFFER_T* buf = BUFFER_T::create(length());
782 buf->__dataLength = length();
783
784 CHAR_T* dst = buf->data();
785 CHAR_T* end = dst + buf->__dataLength;
786 *end = _T('\0');
787 const CHAR_T* src = __psz;
788
789 while (dst < end) {
790 *dst++ = *src == _old ? _new : *src;
791 src++;
792 }
793 __DCL_ASSERT(*(buf->data() + buf->__dataLength) == _T('\0'));
794
795 STRING_T r = buf;
796 buf->release();
797 return r;
798}
799
801 const CHAR_T* _old, size_t _oldlen,
802 const CHAR_T* _new, size_t _newlen
803) const
804{
805 __DCL_ASSERT_PARAM(_old != NULL && _new != NULL);
806
807 if (_oldlen == 0 || __psz == __EMPTY) {
808 return *this;
809 }
810
811 size_t count = 0;
812 const CHAR_T* _start = __psz;
813 const CHAR_T* _end = _start + length();
814 const CHAR_T* _sub;
815 while ((_sub = STRING_T::find(_start, _end, _old, _oldlen)) != NULL) {
816 count++;
817 _start = _sub + _oldlen;
818 }
819
820 if (!count) {
821 return *this;
822 }
823
824 size_t allocLength = length() + (count * _newlen) - (count * _oldlen);
825 BUFFER_T* buf = BUFFER_T::create(allocLength);
826 buf->__dataLength = allocLength;
827 CHAR_T* dst = buf->data();
828 *(dst + allocLength) = _T('\0');
829 size_t _len = 0;
830 _start = __psz;
831 while ((_sub = STRING_T::find(_start, _end, _old, _oldlen)) != NULL) {
832 _len = _sub - _start;
833 memcpy(dst, _start, _len * sizeof(CHAR_T));
834 dst += _len;
835 memcpy(dst, _new, _newlen * sizeof(CHAR_T));
836 dst += _newlen;
837
838 _start = _sub + _oldlen;
839 }
840 _len = _end - _start;
841 memcpy(dst, _start, _len * sizeof(CHAR_T));
842#ifdef __DCL_DEBUG
843 dst += _len;
844 __DCL_ASSERT((dst >= buf->data()) && ((size_t) (dst - buf->data()) == allocLength));
845#endif
846 __DCL_ASSERT(*(buf->data() + buf->__dataLength) == _T('\0'));
847
848 STRING_T r = buf;
849 buf->release();
850 return r;
851}
852
854 const CHAR_T* _regex,
855 bool _icase
857{
858 __DCL_ASSERT_PARAM(_regex != NULL);
859 return __regex_search(
860 _regex, _regex + STRING_T::length(_regex),
861 __psz, __psz + length(),
862 _icase
863 );
864}
865
867 const STRING_T& _regex,
868 bool _icase
870{
871 return __regex_search(
872 _regex.__psz, _regex.__psz + _regex.length(),
873 __psz, __psz + length(),
874 _icase
875 );
876}
877
879 const CHAR_T* _regex,
880 bool _icase
882{
883 __DCL_ASSERT_PARAM(_regex != NULL);
884 return __regex_substring(
885 _regex, _regex + STRING_T::length(_regex),
886 __psz, __psz + length(),
887 _icase
888 );
889}
890
892 const STRING_T& _regex,
893 bool _icase
895{
896 return __regex_substring(
897 _regex.__psz, _regex.__psz + _regex.length(),
898 __psz, __psz + length(),
899 _icase
900 );
901}
902
904 const CHAR_T* _regex,
905 bool _icase
907{
908 __DCL_ASSERT_PARAM(_regex != NULL);
909 return __regex_search(
910 _regex, _regex + STRING_T::length(_regex),
911 __psz, __psz + length(),
912 _icase
913 ) != (size_t)-1;
914}
915
917 const STRING_T& _regex,
918 bool _icase
920{
921 return __regex_search(
922 _regex.__psz, _regex.__psz + _regex.length(),
923 __psz, __psz + length(),
924 _icase
925 ) != (size_t)-1;
926}
927
929 const CHAR_T* _regex,
930 bool _icase
932{
933 __DCL_ASSERT_PARAM(_regex != NULL);
934 return __regex_matches(
935 _regex, _regex + STRING_T::length(_regex),
936 __psz, __psz + length(),
937 _icase
938 );
939}
940
942 const STRING_T& _regex,
943 bool _icase
945{
946 return __regex_matches(
947 _regex.__psz, _regex.__psz + _regex.length(),
948 __psz, __psz + length(),
949 _icase
950 );
951}
952
954 const CHAR_T* _regex,
955 const CHAR_T* _replacment,
956 bool _icase,
957 size_t _limit // = (size_t)-1
959{
960 __DCL_ASSERT_PARAM(_regex != NULL);
961 __DCL_ASSERT_PARAM(_replacment != NULL);
962 return __regex_replace(
963 _regex, _regex + STRING_T::length(_regex),
964 __psz, __psz + length(),
965 _replacment, _replacment + STRING_T::length(_replacment),
966 _icase,
967 _limit
968 );
969}
970
972 const STRING_T& _regex,
973 const STRING_T& _replacement,
974 bool _icase,
975 size_t _limit // = (size_t)-1
977{
978 return __regex_replace(
979 _regex.__psz, _regex.__psz + _regex.length(),
980 __psz, __psz + length(),
981 _replacement.__psz, _replacement.__psz + _replacement.length(),
982 _icase,
983 _limit
984 );
985}
986
988 const CHAR_T* _regex,
989 bool _icase,
990 ARRAY_T& _results,
991 size_t _limit // = (size_t)-1
993{
994 __DCL_ASSERT_PARAM(_regex != NULL);
995 return __regex_split(
996 _regex, _regex + STRING_T::length(_regex),
997 __psz, __psz + length(),
998 _icase,
999 _results,
1000 _limit
1001 );
1002}
1003
1005 const STRING_T& _regex,
1006 bool _icase,
1007 ARRAY_T& _results,
1008 size_t _limit // = (size_t)-1
1010{
1011 return __regex_split(
1012 _regex.__psz, _regex.__psz + _regex.length(),
1013 __psz, __psz + length(),
1014 _icase,
1015 _results,
1016 _limit
1017 );
1018}
1019
1021{
1022 BUFFER_T* buf = BUFFER_T::create(length());
1023 CHAR_T* dst = buf->data();
1024 const CHAR_T* src = __psz;
1025 const CHAR_T* _end = __psz + length();
1026 while (src < _end) {
1027 *dst = TOUPPER((UCHAR_T)*src);
1028 src++;
1029 dst++;
1030 }
1031 *dst = _T('\0');
1032 buf->__dataLength = dst - buf->data();
1033
1034 STRING_T r(buf);
1035 buf->release();
1036 return r;
1037}
1038
1040{
1041 BUFFER_T* buf = BUFFER_T::create(length());
1042 CHAR_T* dst = buf->data();
1043 const CHAR_T* src = __psz;
1044 const CHAR_T* _end = __psz + length();
1045 while (src < _end) {
1046 *dst = TOLOWER((UCHAR_T)*src);
1047 src++;
1048 dst++;
1049 }
1050 *dst = _T('\0');
1051 buf->__dataLength = dst - buf->data();
1052
1053 STRING_T r(buf);
1054 buf->release();
1055 return r;
1056}
1057
1058#ifdef __DCL_INCLUDED_LOCALE_H
1059STRING_T STRING_T::toUpperCase(locale_t _locale) const
1060{
1061 BUFFER_T* buf = BUFFER_T::create(length());
1062 CHAR_T* dst = buf->data();
1063 const CHAR_T* src = __psz;
1064 const CHAR_T* _end = __psz + length();
1065 while (src < _end) {
1066 *dst = TOUPPER_L((UCHAR_T)*src, __locale);
1067 src++;
1068 dst++;
1069 }
1070 *dst = _T('\0');
1071 buf->__dataLength = dst - buf->data();
1072
1073 STRING_T r(buf);
1074 buf->release();
1075 return r;
1076}
1077
1078STRING_T STRING_T::toLowerCase(locale_t _locale) const
1079{
1081 CHAR_T* dst = buf->data();
1082 const CHAR_T* src = __psz;
1083 const CHAR_T* _end = __psz + length();
1084 while (src < _end) {
1085 *dst = TOLOWER_L((UCHAR_T)*src, __locale);
1086 src++;
1087 dst++;
1088 }
1089 *dst = _T('\0');
1090 buf->__dataLength = dst - buf->data();
1091
1092 STRING_T r(buf);
1093 buf->release();
1094 return r;
1095}
1096#endif
1097
1098#ifdef __DCL_COMPILE_UNICODE__
1099String STRING_T::toString() const
1100{
1101 return *this;
1102}
1103#else
1105{
1106 return String::toHexString(*this, 20);
1107}
1108#endif
1109
1111{
1112 CHAR_T* first = __psz;
1113 CHAR_T* last = __psz + length();
1114
1115 while(first < last) {
1116 if (!ISSPACE((UCHAR_T)*first))
1117 break;
1118 first++;
1119 }
1120
1121 while(first < last) {
1122 if (!ISSPACE((UCHAR_T)*(last - 1)))
1123 break;
1124 last--;
1125 }
1126
1127 __DCL_ASSERT(first <= last);
1128
1129 if (__psz < first || last < __psz + length()) {
1130 size_t len = last - first;
1131 if (len) {
1132 BUFFER_T* buf = BUFFER_T::create(len);
1133 buf->__dataLength = len;
1134 CHAR_T* p = buf->data();
1135 *(p + len) = _T('\0');
1136 memcpy(p, first, len * sizeof(CHAR_T));
1137
1138 STRING_T r = buf;
1139 buf->release();
1140 return r;
1141 }
1142 }
1143 return *this;
1144}
1145
1147{
1148 CHAR_T* first = __psz;
1149 CHAR_T* last = __psz + length();
1150
1151 while (first < last) {
1152 if (!ISSPACE((UCHAR_T)*first))
1153 break;
1154 first++;
1155 }
1156
1157 if (__psz < first) {
1158 size_t len = last - first;
1159 if (len) {
1160 BUFFER_T* buf = BUFFER_T::create(len);
1161 buf->__dataLength = len;
1162 CHAR_T* p = buf->data();
1163 *(p + len) = _T('\0');
1164 memcpy(p, first, len * sizeof(CHAR_T));
1165
1166 STRING_T r = buf;
1167 buf->release();
1168 return r;
1169 }
1170 }
1171 return *this;
1172}
1173
1175{
1176 CHAR_T* first = __psz;
1177 CHAR_T* last = __psz + length();
1178
1179 while(first < last) {
1180 if (!ISSPACE((UCHAR_T)*(last - 1)))
1181 break;
1182 last--;
1183 }
1184
1185 if (last < __psz + length()) {
1186 size_t len = last - first;
1187 if (len) {
1188 BUFFER_T* buf = BUFFER_T::create(len);
1189 buf->__dataLength = len;
1190 CHAR_T* p = buf->data();
1191 *(p + len) = _T('\0');
1192 memcpy(p, first, len * sizeof(CHAR_T));
1193
1194 STRING_T r = buf;
1195 buf->release();
1196 return r;
1197 }
1198 }
1199 return *this;
1200}
1201
1202STRING_T STRING_T::trim(const CHAR_T* _chars) const
1203{
1204 CHAR_T* first = __psz;
1205 CHAR_T* last = __psz + length();
1206
1207 while (first < last) {
1208 if (STRCHR(_chars, (UCHAR_T)*first) == NULL)
1209 break;
1210 first++;
1211 }
1212
1213 while (first < last) {
1214 if (STRCHR(_chars, (UCHAR_T)*(last - 1)) == NULL)
1215 break;
1216 last--;
1217 }
1218
1219 __DCL_ASSERT(first <= last);
1220
1221 if (__psz < first || last < __psz + length()) {
1222 size_t len = last - first;
1223 if (len) {
1224 BUFFER_T* buf = BUFFER_T::create(len);
1225 buf->__dataLength = len;
1226 CHAR_T* p = buf->data();
1227 *(p + len) = _T('\0');
1228 memcpy(p, first, len * sizeof(CHAR_T));
1229
1230 STRING_T r = buf;
1231 buf->release();
1232 return r;
1233 }
1234 return STRING_T();
1235 }
1236 return *this;
1237}
1238
1240{
1241 CHAR_T* first = __psz;
1242 CHAR_T* last = __psz + length();
1243
1244 while (first < last) {
1245 if (STRCHR(_chars, (UCHAR_T)*first) == NULL)
1246 break;
1247 first++;
1248 }
1249
1250 if (__psz < first) {
1251 size_t len = last - first;
1252 if (len)
1253 {
1254 BUFFER_T* buf = BUFFER_T::create(len);
1255 buf->__dataLength = len;
1256 CHAR_T* p = buf->data();
1257 *(p + len) = _T('\0');
1258 memcpy(p, first, len * sizeof(CHAR_T));
1259
1260 STRING_T r = buf;
1261 buf->release();
1262 return r;
1263 }
1264 }
1265 return *this;
1266}
1267
1269{
1270 CHAR_T* first = __psz;
1271 CHAR_T* last = __psz + length();
1272
1273 while (first < last) {
1274 if (STRCHR(_chars, (UCHAR_T)*(last - 1)) == NULL)
1275 break;
1276 last--;
1277 }
1278
1279 if (last < __psz + length()) {
1280 size_t len = last - first;
1281 if (len) {
1282 BUFFER_T* buf = BUFFER_T::create(len);
1283 buf->__dataLength = len;
1284 CHAR_T* p = buf->data();
1285 *(p + len) = _T('\0');
1286 memcpy(p, first, len * sizeof(CHAR_T));
1287
1288 STRING_T r = buf;
1289 buf->release();
1290 return r;
1291 }
1292 }
1293 return *this;
1294}
1295
1296CHAR_T STRING_T::operator[](size_t _index) const
1297{
1298 __DCL_ASSERT(0 < length() && _index < length());
1299// if (!(_index < __buf->__dataLength))
1300// throw(new InvalidIndexException(0, __buf->__dataLength - 1, _index));
1301 return __psz[_index];
1302}
1303
1304// static members
1306 const CHAR_T* _psz,
1307 size_t _max // = (size_t)-1,
1308)
1309{
1310 __DCL_ASSERT_PARAM(_psz != NULL);
1311 size_t r = 0;
1312 while (*_psz++ && r < _max) {
1313 r++;
1314 }
1315 return r;
1316}
1317
1319{
1320 size_t len = STRING_T::length(_format) * 4;
1321 BUFFER_T* buf = BUFFER_T::create_e(len);
1322
1323 va_list arglist;
1324 va_start(arglist, _format);
1325 int __UNUSED__ n = BUFFER_T::vformat(buf, _format, arglist);
1326 va_end(arglist);
1327
1328 STRING_T r = buf;
1329 buf->release();
1330#ifdef __DCL_DEBUG
1331 const CHAR_T* p = r;
1332 __DCL_ASSERT(p[r.length()] == __T('\0'));
1333#endif
1334 return r;
1335}
1336
1337#ifndef __A_HEX_DEFINED
1338#define __A_HEX_DEFINED
1339static const CHAR_T __hex__[] = _T("0123456789abcdef");
1340#endif
1341
1342#define ASCII_32 _T(' ')
1343#define ASCII_126 _T('~')
1344
1345bool __escapeable(unsigned int c, STRING_T::EscapeFlags _flag)
1346{
1347 bool r = false;
1348 if (_flag == STRING_T::ESCAPE_DEFAULT) {
1349 r = (c <= 0xff) && (c < ASCII_32 || ASCII_126 < c
1350 || c == _T('\"') || c == _T('\'') || c == _T('\\'));
1351 }
1352 else if (_flag == STRING_T::ESCAPE_EXTENDED) {
1353 r = ISALNUM(c) != 0;
1354 }
1355 else
1356 r = true;
1357
1358 return r;
1359}
1360
1362 const CHAR_T* _ps,
1363 size_t _len,
1364 EscapeFlags _flag // = ESCAPE_DEFAULT
1365)
1366{
1367 __DCL_ASSERT_PARAM(_ps != NULL);
1368
1369 if (_len == 0)
1370 return STRING_T();
1371
1372 // javascript
1373 // byte_t sizeof(CHAR_T) == 1 "\xff" "%ff"
1374 // Windows sizeof(CHAR_T) == 2 "\uffff" "%uffff"
1375 // Linux sizeof(CHAR_T) == 4 "\u00ffffff" "%uffffff" ??
1376
1377 BUFFER_T* buf = BUFFER_T::create(_len * 4);
1378 const UCHAR_T* src = (const UCHAR_T*) _ps;
1379 const UCHAR_T* _end = src + _len;
1380
1381 if (_flag == ESCAPE_XML) {
1382 for( ; src < _end; src++) {
1383 CHAR_T c = *src;
1384 switch (c) {
1385 case _T('&') : BUFFER_T::write(buf, _T("&amp;"), 5); break;
1386 case _T('<') : BUFFER_T::write(buf, _T("&lt;"), 4); break;
1387 case _T('>') : BUFFER_T::write(buf, _T("&gt;"), 4); break;
1388 case _T('\"') : BUFFER_T::write(buf, _T("&quot;"), 6); break;
1389 case _T('\'') : BUFFER_T::write(buf, _T("&#39;"), 5); break;
1390 default:
1391 BUFFER_T::write(buf, c);
1392 }
1393 }
1394 }
1395 else {
1396 // ESCAPE_DEFAULT, ESCAPE_EXTENDED, ESCAPE_ALL
1397 for ( ; src < _end; src++) {
1398 unsigned int c = *src;
1399 if (__escapeable(c, _flag)) {
1400 BUFFER_T::write(buf, _T('\\'));
1401 switch(c) {
1402 case _T('\0') : BUFFER_T::write(buf, _T('0')); break; // NULL
1403 case _T('\a') : BUFFER_T::write(buf, _T('a')); break; // BEL, alert
1404 case _T('\b') : BUFFER_T::write(buf, _T('b')); break; // backspace
1405 case _T('\t') : BUFFER_T::write(buf, _T('t')); break; // horizontal tab
1406 case _T('\n') : BUFFER_T::write(buf, _T('n')); break; // line feed, new line
1407 case _T('\v') : BUFFER_T::write(buf, _T('v')); break; // vertical tab
1408 case _T('\f') : BUFFER_T::write(buf, _T('f')); break; // form feed
1409 case _T('\r') : BUFFER_T::write(buf, _T('r')); break; // carriage return
1410 case _T('\"') : // double quotation mark
1411 case _T('\'') : // single quotation mark
1412 case _T('\\') : // back slash
1413 BUFFER_T::write(buf, c);
1414 break;
1415 default :
1416 if ( c <= 0xff) {
1417 BUFFER_T::write(buf, _T('x'));
1418 BUFFER_T::write(buf, __hex__[c >> 4]);
1419 BUFFER_T::write(buf, __hex__[c & 0x0f]);
1420 }
1421 else if (c <= 0xffff) {
1422 // 16bit unicode BMP
1423 BUFFER_T::write(buf, _T('u'));
1424 unsigned char a[4];
1425 a[3] = c & 0x0f;
1426 c >>= 4;
1427 a[2] = c & 0x0f;
1428 c >>= 4;
1429 a[1] = c & 0x0f;
1430 c >>= 4;
1431 a[0] = c;
1432
1433 for(int i = 0; i < 4; i++)
1434 BUFFER_T::write(buf, __hex__[a[i]]);
1435 }
1436 else {
1437 BUFFER_T::write(buf, c);
1438 }
1439 }
1440 }
1441 else
1442 BUFFER_T::write(buf, c);
1443 }
1444 }
1445
1446 BUFFER_T::shrink(buf);
1447
1448 STRING_T r(buf);
1449 buf->release();
1450 return r;
1451}
1452
1453static int __hex2int(CHAR_T _c)
1454{
1455 if (_T('0') <= _c && _c <= _T('9'))
1456 return _c - _T('0');
1457 else if (_T('A') <= _c && _c <= _T('F'))
1458 return _c - _T('A') + 10;
1459 else if (_T('a') <= _c && _c <= _T('f'))
1460 return _c - _T('a') + 10;
1461 else {
1462 return -1;
1463 }
1464}
1465
1467 const CHAR_T* _psz,
1468 size_t _len
1469)
1470{
1471 __DCL_ASSERT_PARAM(_psz != NULL);
1472 if (_len == (size_t)-1)
1473 _len = STRING_T::length(_psz);
1474
1475 if (_len == 0)
1476 return STRING_T();
1477
1478 BUFFER_T* buf = BUFFER_T::create(_len);
1479 const CHAR_T* src = (const CHAR_T*)_psz;
1480 const CHAR_T* end = src + _len;
1481
1482 for ( ; src < end; src++) {
1483 if (*src == _T('\\') && (src + 1) < end) {
1484 switch (*++src) {
1485 case _T('0') : BUFFER_T::write(buf, _T('\0')); break;
1486 case _T('a') : BUFFER_T::write(buf, _T('\a')); break;
1487 case _T('b') : BUFFER_T::write(buf, _T('\b')); break;
1488 case _T('t') : BUFFER_T::write(buf, _T('\t')); break;
1489 case _T('n') : BUFFER_T::write(buf, _T('\n')); break;
1490 case _T('v') : BUFFER_T::write(buf, _T('\v')); break;
1491 case _T('f') : BUFFER_T::write(buf, _T('\f')); break;
1492 case _T('r') : BUFFER_T::write(buf, _T('\r')); break;
1493 case _T('\"') :
1494 case _T('\'') :
1495// case _T('\?') :
1496 case _T('\\') :
1497 BUFFER_T::write(buf, *src);
1498 break;
1499 case _T('x') :
1500 case _T('X') :
1501 if ((src + 2) < end) {
1502 int high = __hex2int(src[1]);
1503 int low = __hex2int(src[2]);
1504 if (high >= 0 && low >= 0)
1505 {
1506 BUFFER_T::write(buf, (high << 4) | low);
1507 src += 2;
1508 break;
1509 }
1510 }
1511 goto __no_escape;
1512 case _T('u') :
1513 case _T('U') :
1514 if ((src + 4) < end) {
1515 int n;
1516 UCHAR_T c = 0;
1517#ifdef __DCL_COMPILE_UNICODE__
1518 for (int i = 1; i <= 4; i++) {
1519 if ((n = __hex2int(src[i])) < 0)
1520 goto __no_escape;
1521 c = (c << 4) | n;
1522 }
1523#else
1524 for (int i = 1; i <= 4; i++) {
1525 if ((n = __hex2int(src[i])) < 0)
1526 goto __no_escape;
1527 c = (c << 4) | n;
1528 if (i == 1) {
1529 BUFFER_T::write(buf, c);
1530 c = 0;
1531 }
1532 }
1533#endif
1534 BUFFER_T::write(buf, c);
1535 src += 4;
1536 break;
1537 }
1538 default :
1539__no_escape:
1540 BUFFER_T::write(buf, _T('\\'));
1541 BUFFER_T::write(buf, *src);
1542 }
1543 }
1544 else {
1545 // normal
1546 BUFFER_T::write(buf, *src);
1547 }
1548 }
1549 BUFFER_T::shrink(buf);
1550
1551 STRING_T r(buf);
1552 buf->release();
1553 return r;
1554}
1555
1557 const char* _bytes,
1558 size_t _len,
1559 size_t _max, // = (size_t)-1,
1560 bool _prefix // = true
1561)
1562{
1563 __DCL_ASSERT_PARAM(_bytes != NULL);
1564
1565 size_t len = __MIN(_len, _max);
1566 /*
1567 size_t dstlen = len * 2;
1568 if (_prefix) // "0x"
1569 dstlen += 2;
1570 if (_max <= _len) // "..."
1571 dstlen += 3;
1572 */
1573 size_t dstlen = len * 2 + 5;
1574
1575 BUFFER_T* buf = BUFFER_T::create(dstlen);
1576 CHAR_T* dst = buf->data();
1577 if (_prefix) {
1578 *dst++ = _T('\\');
1579 *dst++ = _T('x');
1580 }
1581
1582 const byte_t* src = (const byte_t*) _bytes;
1583 const byte_t* end = src + len;
1584
1585 while (src < end) {
1586 *dst++ = __hex__[*src >> 4];
1587 *dst++ = __hex__[*src & 0x0f];
1588 src++;
1589 }
1590
1591 if (_max < _len) {
1592 *dst++ = _T('.');
1593 *dst++ = _T('.');
1594 *dst++ = _T('.');
1595 }
1596
1597 *dst = _T('\0');
1598 //__DCL_TRACE2(__T("[%zd] [%zd]\n"), dstlen, dst - buf->data());
1599 __DCL_ASSERT(dst <= buf->data() + dstlen);
1600 buf->__dataLength = dst - buf->data();
1601
1602 STRING_T r(buf);
1603 buf->release();
1604 return r;
1605}
1606
1608 const char* _bytes,
1609 size_t _len,
1610 size_t _max // = (size_t)-1
1611)
1612{
1613 // "12345\0\1\2\3\4\5"
1614 // "12345\x00\x01\x02\x03\x04\x05"
1615
1616 __DCL_ASSERT_PARAM(_bytes != NULL);
1617
1618 size_t len = __MIN(_len, _max);
1619 /*
1620 size_t dstlen = len * 4; // \x01
1621 if (_max <= len)
1622 dstlen += 3; // ...
1623 */
1624 size_t dstlen = len * 4 + 3;
1625
1626 BUFFER_T* buf = BUFFER_T::create(dstlen);
1627 CHAR_T* dst = buf->data();
1628 const byte_t* src = (const byte_t*)_bytes;
1629 const byte_t* end = src + len;
1630
1631 while (src < end) {
1632 if (isprint(*src)) {
1633 *dst++ = *src;
1634 }
1635 else {
1636 *dst++ = _T('\\');
1637 *dst++ = _T('x');
1638 *dst++ = __hex__[*src >> 4];
1639 *dst++ = __hex__[*src & 0x0f];
1640 }
1641 src++;
1642 }
1643
1644 if (_max < _len) {
1645 *dst++ = _T('.');
1646 *dst++ = _T('.');
1647 *dst++ = _T('.');
1648 }
1649
1650 *dst = _T('\0');
1651 //__DCL_TRACE2(__T("[%zd] [%zd]\n"), dstlen, dst - buf->data());
1652 __DCL_ASSERT(dst <= buf->data() + dstlen);
1653 buf->__dataLength = dst - buf->data();
1654
1655 STRING_T r(buf);
1656 buf->release();
1657 return r;
1658}
1659
1661 const CHAR_T* _begin,
1662 const CHAR_T* _end,
1663 CHAR_T _ch
1664)
1665{
1666 __DCL_ASSERT_PARAM(_begin != NULL && _begin <= _end);
1667
1668 while (_begin < _end) {
1669 if (*_begin == _ch)
1670 return (CHAR_T*)_begin;
1671 _begin++;
1672 }
1673 return NULL;
1674}
1675
1677 const CHAR_T* _begin,
1678 const CHAR_T* _end,
1679 CHAR_T _ch
1680)
1681{
1682 __DCL_ASSERT_PARAM(_begin != NULL && _begin <= _end);
1683
1684 while (_begin <= --_end) {
1685 if (*_end == _ch)
1686 return (CHAR_T*)_end;;
1687 }
1688 return NULL;
1689}
1690
1692 const CHAR_T* _begin,
1693 const CHAR_T* _end,
1694 const CHAR_T* _sub,
1695 size_t _sublen
1696)
1697{
1698 __DCL_ASSERT_PARAM(_begin != NULL && _begin <= _end);
1699 __DCL_ASSERT_PARAM(_sub != NULL);
1700
1701 const CHAR_T* subbegin = _sub;
1702 const CHAR_T* subend = _sub + _sublen;
1703
1704 if (_begin == _end) {
1705 if (subbegin == subend)
1706 return (CHAR_T*)_begin;
1707 return NULL;
1708 }
1709
1710 CHAR_T c = *subbegin++;
1711 while (_begin < _end) {
1712 if (c == *_begin++) {
1713 // found first char
1714 const CHAR_T* s = _begin;// s++;
1715 const CHAR_T* _sub = subbegin;
1716 while (s < _end && _sub < subend && *s == *_sub)
1717 s++, _sub++;
1718
1719 if (_sub == subend)
1720// return (CHAR_T*)_begin;
1721 return (CHAR_T*)--_begin;
1722 }
1723// _begin++;
1724 }
1725
1726 return NULL;
1727}
1728
1730 const CHAR_T* _begin,
1731 const CHAR_T* _end,
1732 const CHAR_T* _sub,
1733 size_t _sublen
1734)
1735{
1736 __DCL_ASSERT_PARAM(_begin != NULL && _begin <= _end);
1737 __DCL_ASSERT_PARAM(_sub != NULL);
1738
1739 const CHAR_T* subbegin = _sub;
1740 const CHAR_T* subend = _sub + _sublen;
1741
1742 if (_begin == _end) {
1743 if (subbegin == subend)
1744 return (CHAR_T*)_begin;
1745 return NULL;
1746 }
1747
1748 _end -= _sublen;
1749 CHAR_T c = *subbegin++;
1750 while (_begin <= _end) {
1751 if (c == *_end) {
1752 // found first char
1753 const CHAR_T* s = _end; s++;
1754 const CHAR_T* _sub = subbegin;
1755 while (_sub < subend && *s == *_sub)
1756 s++, _sub++;
1757
1758 if (_sub == subend)
1759 return (CHAR_T*)_end;
1760 }
1761 _end--;
1762 }
1763 return NULL;
1764}
1765
1767 const CHAR_T* _begin,
1768 const CHAR_T* _end,
1769 const CHAR_T* _delimiter,
1770 size_t _delimiterlen,
1771 ARRAY_T& _results,
1772 size_t _limit // = (size_t)-1
1773)
1774{
1775 size_t count = 0;
1776 while (_begin < _end && count < _limit) {
1777 const CHAR_T* s = STRING_T::find(_begin, _end, _delimiter, _delimiterlen);
1778 if (s) {
1779 _results.add(STRING_T(_begin, s));
1780 _begin = s + _delimiterlen;
1781 count++;
1782 }
1783 else
1784 break;
1785 }
1786
1787 if ((count < _limit) && ((_begin < _end) || (count == 0 && _begin == _end))) {
1788 _results.add(STRING_T(_begin, _end));
1789 count++;
1790 }
1791
1792 return count;
1793}
1794
1796 const CHAR_T* _begin,
1797 const CHAR_T* _end,
1798 CHAR_T _delimiter,
1799 ARRAY_T& _results,
1800 size_t _limit // = (size_t)-1
1801)
1802{
1803 size_t count = 0;
1804 while (_begin < _end && count < _limit) {
1805 const CHAR_T* s = STRING_T::find(_begin, _end, _delimiter);
1806 if (s) {
1807 _results.add(STRING_T(_begin, s));
1808 _begin = s + 1;
1809 count++;
1810 }
1811 else
1812 break;
1813 }
1814
1815 if ((count < _limit) && ((_begin < _end) || (count == 0 && _begin == _end))) {
1816 _results.add(STRING_T(_begin, _end));
1817 count++;
1818 }
1819
1820 return count;
1821}
1822
1824 const ARRAY_T& _array,
1825 CHAR_T _delimiter,
1826 bool _hasEmpty // = false
1827)
1828{
1830 ARRAY_T::ConstIterator it = _array.begin();
1831 if (it != _array.end()) {
1832 for ( ; ; ) {
1833 const STRING_T& s = *it;
1834 r += s;
1835 if (++it == _array.end()) {
1836 break;
1837 }
1838
1839 if (s.isEmpty()) {
1840 if (_hasEmpty) {
1841 r += _delimiter;
1842 }
1843 }
1844 else {
1845 r += _delimiter;
1846 }
1847 }
1848 }
1849
1850 return r;
1851}
1852
1854{
1855 return _b ? _T("true") : _T("false");
1856}
1857
1859{
1860#ifdef __DCL_COMPILE_UNICODE__
1861 return Int32::toString((int32_t) _n, 10);
1862#else
1863 return Int32::toByteString((int32_t) _n, 10);
1864#endif
1865}
1866
1868{
1869#ifdef __DCL_COMPILE_UNICODE__
1870 return UInt32::toString((uint32_t) _n, 10);
1871#else
1872 return UInt32::toByteString((uint32_t) _n, 10);
1873#endif
1874}
1875
1877{
1878#ifdef __DCL_COMPILE_UNICODE__
1879 return Int32::toString((int32_t) _n, 10);
1880#else
1881 return Int32::toByteString((int32_t) _n, 10);
1882#endif
1883}
1884
1885STRING_T STRING_T::valueOf(unsigned short _n)
1886{
1887#ifdef __DCL_COMPILE_UNICODE__
1888 return UInt32::toString((uint32_t) _n, 10);
1889#else
1890 return UInt32::toByteString((uint32_t) _n, 10);
1891#endif
1892}
1893
1895{
1896#ifdef __DCL_COMPILE_UNICODE__
1897 return Int32::toString((int32_t) _n, 10);
1898#else
1899 return Int32::toByteString((int32_t) _n, 10);
1900#endif
1901}
1902
1904{
1905#ifdef __DCL_COMPILE_UNICODE__
1906 return UInt32::toString((uint32_t) _n, 10);
1907#else
1908 return UInt32::toByteString((uint32_t) _n, 10);
1909#endif
1910}
1911
1913{
1914#if __WORDSIZE == 64
1915#ifdef __DCL_COMPILE_UNICODE__
1916 return Int64::toString((int64_t) _n, 10);
1917#else
1918 return Int64::toByteString((int64_t) _n, 10);
1919#endif
1920#else
1921#ifdef __DCL_COMPILE_UNICODE__
1922 return UInt32::toString((uint32_t) _n, 10);
1923#else
1924 return UInt32::toByteString((uint32_t) _n, 10);
1925#endif
1926#endif
1927}
1928
1930{
1931#if __WORDSIZE == 64
1932#ifdef __DCL_COMPILE_UNICODE__
1933 return UInt64::toString((uint64_t) _n, 10);
1934#else
1935 return UInt64::toByteString((uint64_t) _n, 10);
1936#endif
1937#else
1938#ifdef __DCL_COMPILE_UNICODE__
1939 return UInt32::toString((uint32_t) _n, 10);
1940#else
1941 return UInt32::toByteString((uint32_t) _n, 10);
1942#endif
1943#endif
1944}
1945
1947{
1948#ifdef __DCL_COMPILE_UNICODE__
1949 return Int64::toString((int64_t) _n, 10);
1950#else
1951 return Int64::toByteString((int64_t) _n, 10);
1952#endif
1953}
1954
1955STRING_T STRING_T::valueOf(unsigned long long _n)
1956{
1957#ifdef __DCL_COMPILE_UNICODE__
1958 return UInt64::toString((uint64_t) _n, 10);
1959#else
1960 return UInt64::toByteString((uint64_t) _n, 10);
1961#endif
1962}
1963
1965{
1966#ifdef __DCL_COMPILE_UNICODE__
1967 return String::format(L"%.8g", _n);
1968#else
1969 return ByteString::format("%.8g", _n);
1970#endif
1971}
1972
1974{
1975#ifdef __DCL_COMPILE_UNICODE__
1976 return String::format(L"%.16g", _n);
1977#else
1978 return ByteString::format("%.16g", _n);
1979#endif
1980}
1981
1983{
1984#ifdef __DCL_COMPILE_UNICODE__
1985 return String::format(L"%.32Lg", _n);
1986#else
1987 return ByteString::format("%.32Lg", _n);
1988#endif
1989}
1990
1991#if __DCL_HAVE_THIS_FILE__
1992 #undef __THIS_FILE__
1993#endif
1994
1995#endif // __DCL_INTERNAL__
#define STRCASECMP(s1, s2)
Definition __STRING.cpp:74
#define TOUPPER_L(c, l)
Definition __STRING.cpp:85
size_t __extended_length(size_t _allocLength)
Definition __STRING.cpp:113
#define STRCMP(s1, s2)
Definition __STRING.cpp:66
#define ASCII_32
#define STRNCMP(s1, s2, n)
Definition __STRING.cpp:67
#define ASCII_126
#define VSNPRINTF(buf, len, fmt, args)
Definition __STRING.cpp:76
#define _T(s)
Definition __STRING.cpp:57
#define ISALNUM(c)
Definition __STRING.cpp:82
#define __EMPTY
Definition __STRING.cpp:301
#define TOUPPER(c)
Definition __STRING.cpp:83
#define STRCHR(s, c)
Definition __STRING.cpp:79
#define __EXTEND_MIN
bool __escapeable(unsigned int c, STRING_T::EscapeFlags _flag)
#define TOLOWER(c)
Definition __STRING.cpp:84
#define __EMPTY_STR
Definition __STRING.cpp:297
DCLCAPI STRING_T operator+(const STRING_T &_str1, const STRING_T &_str2)
Definition __STRING.cpp:483
#define ISSPACE(c)
Definition __STRING.cpp:81
#define __EXTENDED_MAX
#define TOLOWER_L(c, l)
Definition __STRING.cpp:86
#define STRSTR(s, cs)
Definition __STRING.cpp:80
#define STRNCASECMP(s1, s2, n)
Definition __STRING.cpp:75
#define STRING_T
Definition __STRING.h:23
#define _T(s)
Definition __STRING.h:19
#define BUFFER_T
Definition __STRING.h:22
#define CHAR_T
Definition __STRING.h:20
#define ARRAY_T
Definition __STRING.h:25
#define UCHAR_T
Definition __STRING.h:21
StringArray & __regex_split(const wchar_t *_regex, const wchar_t *_regexend, const wchar_t *_begin, const wchar_t *_end, bool _icase, StringArray &_results, size_t _limit=(size_t) -1) __DCL_THROWS1(RegexException *)
Definition _regex.cpp:452
bool __regex_search(regex_handle _handle, const wchar_t *_begin, const wchar_t *_end, match_result **_results, unsigned int _flags)
Definition _regex.cpp:143
String __regex_substring(const wchar_t *_regex, const wchar_t *_regexend, const wchar_t *_begin, const wchar_t *_end, bool _icase) __DCL_THROWS1(RegexException *)
Definition _regex.cpp:305
bool __regex_matches(const wchar_t *_regex, const wchar_t *_regexend, const wchar_t *_begin, const wchar_t *_end, bool _icase) __DCL_THROWS1(RegexException *)
Definition _regex.cpp:191
String __regex_replace(const wchar_t *_regex, const wchar_t *_regexend, const wchar_t *_begin, const wchar_t *_end, const wchar_t *_replacement, const wchar_t *_replacementend, bool _icase, size_t _limit=(size_t) -1) __DCL_THROWS1(RegexException *)
Definition _regex.cpp:370
#define NULL
Definition Config.h:312
#define __UNUSED__
Definition Config.h:341
#define DCLCAPI
Definition Config.h:95
wchar_t char_t
Definition Config.h:247
unsigned char byte_t
Definition Config.h:246
#define __DCL_THROWS1(e)
Definition Config.h:152
IOException *size_t r
Definition MediaInfo.cpp:82
#define __DCL_ASSERT_PARAM(expr)
Definition Object.h:409
#define __DCL_TRACE3(fmt, arg1, arg2, arg3)
Definition Object.h:401
#define __CONCAT_TEXT(str, expr)
Definition Object.h:63
#define __CONCAT(x, y)
Definition Object.h:54
#define __DCL_ASSERT(expr)
Definition Object.h:394
#define __T(str)
Definition Object.h:60
#define __DCL_TRACE2(fmt, arg1, arg2)
Definition Object.h:400
ARRAY_T & add(CONST_ELEMENT_REF _element)
Definition __ARRAY.h:155
ConstIterator end() const
Definition __ARRAY.h:134
ConstIterator begin() const
Definition __ARRAY.h:127
static ByteString toByteString(int32_t _n, unsigned _base=10)
Definition Numeric.cpp:355
String toString(unsigned _base=10) const
Definition Numeric.inl:93
static ByteString toByteString(int64_t _n, unsigned _base=10)
Definition Numeric.cpp:587
String toString(unsigned _base=10) const
Definition Numeric.inl:117
int compare(const CHAR_T *_psz, size_t _len=(size_t) -1) const
Definition __STRING.h:377
STRING_T padCenter(size_t _len, CHAR_T _ch) const
Definition __STRING.cpp:646
STRING_T toUpperCase() const
static STRING_T escape(const CHAR_T *_ps, size_t _len, EscapeFlags _flag=ESCAPE_DEFAULT)
bool isEmpty() const
Definition __STRING.h:621
static size_t split(const CHAR_T *_begin, const CHAR_T *_end, const CHAR_T *_delimiter, size_t _delimiterlen, ARRAY_T &_results, size_t _limit=(size_t) -1)
const CHAR_T * data() const
Definition __STRING.h:631
STRING_T trim() const
static STRING_T toHexString(const char *_bytes, size_t _len, size_t _max=(size_t) -1, bool _prefix=true)
size_t lastIndexOf(CHAR_T _ch, size_t _start=0) const
Definition __STRING.cpp:554
static STRING_T tryString(const char *_bytes, size_t _len, size_t _max=(size_t) -1)
static CHAR_T * rfind(const CHAR_T *_begin, const CHAR_T *_end, CHAR_T _ch)
static STRING_T join(const ARRAY_T &_array, CHAR_T _delimiter, bool _hasEmpty=false)
@ ESCAPE_XML
Definition __STRING.h:241
STRING_T mid(size_t _first, size_t _len=(size_t) -1) const
Definition __STRING.cpp:617
STRING_T trimLeft() const
ARRAY_T & split_r(const CHAR_T *_regex, bool _icase, ARRAY_T &_results, size_t _limit=(size_t) -1) const __DCL_THROWS1(RegexException *)
Definition __STRING.cpp:987
STRING_T trimRight() const
STRING_T padRight(size_t _len, CHAR_T _ch) const
Definition __STRING.cpp:708
friend class STRING_BUILDER_T
Definition __STRING.h:56
STRING_T padLeft(size_t _len, CHAR_T _ch) const
Definition __STRING.cpp:679
STRING_T replace(size_t _start, size_t _len, const CHAR_T *_new, size_t _newlen=(size_t) -1) const
Definition __STRING.cpp:736
bool matches(const CHAR_T *_regex, bool _icase) const __DCL_THROWS1(RegexException *)
Definition __STRING.cpp:928
size_t length() const
Definition __STRING.h:626
void assignAlloc(size_t _len)
Definition __STRING.cpp:303
static STRING_T format(const CHAR_T *_format,...)
void clear()
Definition __STRING.cpp:475
static CHAR_T * find(const CHAR_T *_begin, const CHAR_T *_end, CHAR_T _ch)
STRING_T left(size_t _len) const
Definition __STRING.cpp:634
static STRING_T unescape(const CHAR_T *_psz, size_t _len)
STRING_T replace_r(const CHAR_T *_regex, const CHAR_T *_replacment, bool _icase, size_t _limit=(size_t) -1) const __DCL_THROWS1(RegexException *)
Definition __STRING.cpp:953
CHAR_T operator[](size_t _index) const
int compareNoCase(const CHAR_T *_psz, size_t _len=(size_t) -1) const
Definition __STRING.h:382
size_t indexOf(CHAR_T _ch, size_t _start=0) const
Definition __STRING.cpp:521
STRING_T right(size_t _len) const
Definition __STRING.cpp:639
bool searches(const CHAR_T *_regex, bool _icase) const __DCL_THROWS1(RegexException *)
Definition __STRING.cpp:903
String toString() const
size_t search(const CHAR_T *_regex, bool _icase) const __DCL_THROWS1(RegexException *)
Definition __STRING.cpp:853
STRING_T toLowerCase() const
static STRING_T valueOf(bool _b)
CHAR_T * __psz
Definition __STRING.h:58
STRING_T & assign(const STRING_T &_str)
Definition __STRING.cpp:387
BUFFER_T * __buf() const
Definition __STRING.h:59
STRING_T substring(size_t _first) const
Definition __STRING.h:590
STRING_T rreplace(size_t _start, size_t _len, const CHAR_T *_new, size_t _newlen=(size_t) -1) const
Definition __STRING.cpp:765
static long incrementAndGet(volatile long &_n)
static long decrementAndGet(volatile long &_n)
static ByteString toByteString(uint32_t _u, unsigned _base=10)
Definition Numeric.cpp:470
String toString(unsigned _base=10) const
Definition Numeric.inl:105
static ByteString toByteString(uint64_t _u, unsigned _base=10)
Definition Numeric.cpp:692
String toString(unsigned _base=10) const
Definition Numeric.inl:129
size_t __MAX(size_t x, size_t y)
Definition size_t.h:43
size_t __MIN(size_t x, size_t y)
Definition size_t.h:27
size_t __allocLength
Definition __STRING.h:33
static void destroy(BUFFER_T *_buf)
Definition __STRING.cpp:141
long addRef()
Definition __STRING.cpp:96
CHAR_T * data()
Definition __STRING.h:36
static BUFFER_T * create(size_t _len)
Definition __STRING.cpp:149
static void extend(BUFFER_T *&_buf, size_t _len)
Definition __STRING.cpp:173
static BUFFER_T * create_e(size_t _len)
Definition __STRING.cpp:168
long release()
Definition __STRING.cpp:102
volatile long __refCount
Definition __STRING.h:32
static void write(BUFFER_T *&_buf, const CHAR_T *_str, size_t _len)
Definition __STRING.cpp:214
size_t __dataLength
Definition __STRING.h:34
static void shrink(BUFFER_T *&_buf)
Definition __STRING.cpp:195
static int vformat(BUFFER_T *&_buf, const CHAR_T *_format, va_list _arglist)
Definition __STRING.cpp:230