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