Duckcpp 2.1.0
Duckcpp is a high-performance c++ graphics engine.
Loading...
Searching...
No Matches
irrString.hpp
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine" and the "irrXML" project.
3// For conditions of distribution and use, see copyright notice in duckcpp/duckcpp.hpp and irrXML.h
4
5#ifndef DCPP_STRING_HPP_INCLUDED
6#define DCPP_STRING_HPP_INCLUDED
7
8#include <duckcpp/core/engine/dcpp_types.hpp>
9#include <duckcpp/core/engine/irrAllocator.hpp>
10#include <duckcpp/core/engine/irrMath.hpp>
11#include <sstream>
12#include <iomanip>
13#include <string>
14
15namespace dcpp::nub
16{
17
19
33// forward declarations
34template <typename T, typename TAlloc = irrAllocator<T> >
35class basic_string;
36
39
42
43static size_t multibyteToWString(dcpp::nub::wstring & destination, const char* source, dcpp::u32 sourceSize);
45
46enum eLocaleID
47{
48 DCPP_LOCALE_ANSI = 0,
49 DCPP_LOCALE_GERMAN = 1
50};
51
52static eLocaleID locale_current = DCPP_LOCALE_ANSI;
53static inline void locale_set ( eLocaleID id )
54{
55 locale_current = id;
56}
57
59static inline dcpp::u32 locale_lower ( dcpp::u32 x )
60{
61 switch ( locale_current )
62 {
63 case DCPP_LOCALE_GERMAN:
64 case DCPP_LOCALE_ANSI:
65 break;
66 }
67 // ansi
68 return x >= 'A' && x <= 'Z' ? x + 0x20 : x;
69}
70
72static inline dcpp::u32 locale_upper ( dcpp::u32 x )
73{
74 switch ( locale_current )
75 {
76 case DCPP_LOCALE_GERMAN:
77 case DCPP_LOCALE_ANSI:
78 break;
79 }
80
81 // ansi
82 return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x;
83}
84
86
89DUCKCPP_API void utf8ToWchar(const char *in, wchar_t *out, const dcpp::u64 len);
90
92
95DUCKCPP_API void wcharToUtf8(const wchar_t *in, char *out, const dcpp::u64 len);
96
97
98template <typename T, typename TAlloc>
100{
101private:
103public:
104 using char_type = T;
105
106public:
107// constructor-list-begin
108
111 : array(0), allocated(1), used(1)
112 {
113 array = allocator.allocate(1); // new T[1];
114 array[0] = 0;
115 }
116
117
120 : array(0), allocated(0), used(0)
121 {
122 *this = other;
123 }
124
126 template <class B, class A>
128 : array(0), allocated(0), used(0)
129 {
130 *this = other;
131 }
132
133
135 explicit basic_string(const double number)
136 : array(0), allocated(0), used(0)
137 {
138 std::ostringstream tmpbuf; // new: do not limit tmpbuf string size.
139 tmpbuf << std::fixed << std::setprecision(6) << number;
140 *this = tmpbuf.str().data();
141 }
142
143
145 explicit basic_string(int number)
146 : array(0), allocated(0), used(0)
147 {
148 // store if negative and make positive
149
150 bool negative = false;
151 if (number < 0)
152 {
153 number *= -1;
154 negative = true;
155 }
156
157 // temporary buffer for 16 numbers
158
159 dcpp::c8 tmpbuf[16]={0};
160 dcpp::u32 idx = 15;
161
162 // special case '0'
163
164 if (!number)
165 {
166 tmpbuf[14] = '0';
167 *this = &tmpbuf[14];
168 return;
169 }
170
171 // add numbers
172
173 while(number && idx)
174 {
175 --idx;
176 tmpbuf[idx] = (dcpp::c8)('0' + (number % 10));
177 number /= 10;
178 }
179
180 // add sign
181
182 if (negative)
183 {
184 --idx;
185 tmpbuf[idx] = '-';
186 }
187
188 *this = &tmpbuf[idx];
189 }
190
191
193 explicit basic_string(unsigned int number)
194 : array(0), allocated(0), used(0)
195 {
196 // temporary buffer for 16 numbers
197
198 dcpp::c8 tmpbuf[16]={0};
199 dcpp::u32 idx = 15;
200
201 // special case '0'
202
203 if (!number)
204 {
205 tmpbuf[14] = '0';
206 *this = &tmpbuf[14];
207 return;
208 }
209
210 // add numbers
211
212 while(number && idx)
213 {
214 --idx;
215 tmpbuf[idx] = (dcpp::c8)('0' + (number % 10));
216 number /= 10;
217 }
218
219 *this = &tmpbuf[idx];
220 }
221
222
224 explicit basic_string(long number)
225 : array(0), allocated(0), used(0)
226 {
227 // store if negative and make positive
228
229 bool negative = false;
230 if (number < 0)
231 {
232 number *= -1;
233 negative = true;
234 }
235
236 // temporary buffer for 16 numbers
237
238 dcpp::c8 tmpbuf[16]={0};
239 dcpp::u32 idx = 15;
240
241 // special case '0'
242
243 if (!number)
244 {
245 tmpbuf[14] = '0';
246 *this = &tmpbuf[14];
247 return;
248 }
249
250 // add numbers
251
252 while(number && idx)
253 {
254 --idx;
255 tmpbuf[idx] = (dcpp::c8)('0' + (number % 10));
256 number /= 10;
257 }
258
259 // add sign
260
261 if (negative)
262 {
263 --idx;
264 tmpbuf[idx] = '-';
265 }
266
267 *this = &tmpbuf[idx];
268 }
269
270
272 explicit basic_string(unsigned long number)
273 : array(0), allocated(0), used(0)
274 {
275 // temporary buffer for 16 numbers
276
277 dcpp::c8 tmpbuf[16]={0};
278 dcpp::u32 idx = 15;
279
280 // special case '0'
281
282 if (!number)
283 {
284 tmpbuf[14] = '0';
285 *this = &tmpbuf[14];
286 return;
287 }
288
289 // add numbers
290
291 while(number && idx)
292 {
293 --idx;
294 tmpbuf[idx] = (dcpp::c8)('0' + (number % 10));
295 number /= 10;
296 }
297
298 *this = &tmpbuf[idx];
299 }
300
301
303 template <class B>
305 : array(0), allocated(0), used(0)
306 {
307 if (!c)
308 {
309 // correctly init the string to an empty one
310 *this="";
311 return;
312 }
313
314 allocated = used = length+1;
315 array = allocator.allocate(used); // new T[used];
316
317 for (dcpp::u32 l = 0; l<length; ++l)
318 array[l] = (T)c[l];
319
320 array[length] = 0;
321 }
322
323
325 template <class B>
326 basic_string(const B* const c)
327 : array(0), allocated(0), used(0)
328 {
329 *this = c;
330 }
331
332// constructor-list-end
333
334public:
337 {
338 allocator.deallocate(array); // delete [] array;
339 }
340
341public:
344 {
345 if (this == &other)
346 return *this;
347
348 used = other.size()+1;
349 if (used>allocated)
350 {
351 allocator.deallocate(array); // delete [] array;
352 allocated = used;
353 array = allocator.allocate(used); //new T[used];
354 }
355
356 const T* p = other.data();
357 for (dcpp::u32 i=0; i<used; ++i, ++p)
358 array[i] = *p;
359
360 return *this;
361 }
362
364 template <class B, class A>
366 {
367 *this = other.data();
368 return *this;
369 }
370
371
373 template <class B>
374 self_type & operator=(const B* const c)
375 {
376 if (!c)
377 {
378 if (!array)
379 {
380 array = allocator.allocate(1); //new T[1];
381 allocated = 1;
382 }
383 used = 1;
384 array[0] = 0x0;
385 return *this;
386 }
387
388 if ((void*)c == (void*)array)
389 return *this;
390
391 dcpp::u32 len = 0;
392 const B* p = c;
393 do
394 {
395 ++len;
396 } while(*p++);
397
398 // we'll keep the old string for a while, because the new
399 // string could be a part of the current string.
400 T* oldArray = array;
401
402 used = len;
403 if (used>allocated)
404 {
405 allocated = used;
406 array = allocator.allocate(used); //new T[used];
407 }
408
409 for (dcpp::u32 l = 0; l<len; ++l)
410 array[l] = (T)c[l];
411
412 if (oldArray != array)
413 allocator.deallocate(oldArray); // delete [] oldArray;
414
415 return *this;
416 }
417
418
421 {
422 self_type str(*this);
423 str.append(other);
424
425 return str;
426 }
427
428
430 template <class B>
431 self_type operator+(const B* const c) const
432 {
433 self_type str(*this);
434 str.append(c);
435
436 return str;
437 }
438
439
441 T& operator[](const dcpp::u32 index)
442 {
443 DCPP_DEBUG_BREAK_IF(index>=used) // bad index
444 return array[index];
445 }
446
447
449 const T& operator[](const dcpp::u32 index) const
450 {
451 DCPP_DEBUG_BREAK_IF(index>=used) // bad index
452 return array[index];
453 }
454
455
457 bool operator==(const T* const str) const
458 {
459 if (!str)
460 return false;
461
462 dcpp::u32 i;
463 for (i=0; array[i] && str[i]; ++i)
464 if (array[i] != str[i])
465 return false;
466
467 return (!array[i] && !str[i]);
468 }
469
470
472 bool operator==(const self_type & other) const
473 {
474 for (dcpp::u32 i=0; array[i] && other.array[i]; ++i)
475 if (array[i] != other.array[i])
476 return false;
477
478 return used == other.used;
479 }
480
481
483 bool operator<(const self_type & other) const
484 {
485 for (dcpp::u32 i=0; array[i] && other.array[i]; ++i)
486 {
487 const dcpp::i32 diff = array[i] - other.array[i];
488 if (diff)
489 return (diff < 0);
490 }
491
492 return (used < other.used);
493 }
494
495
497 bool operator!=(const T* const str) const
498 {
499 return !(*this == str);
500 }
501
502
504 bool operator!=(const self_type & other) const
505 {
506 return !(*this == other);
507 }
508
509
511
514 {
515 return used-1;
516 }
517
520 bool empty() const
521 {
522 return (size() == 0);
523 }
524
525 void clear(bool releaseMemory=true)
526 {
527 if ( releaseMemory )
528 {
529 reallocate(1);
530 }
531 array[0] = 0;
532 used = 1;
533 }
534
536
537 const T* data() const
538 {
539 return array;
540 }
541
543
545 std::basic_string<T> str() const
546 {
547 return array;
548 }
549
551
552 explicit operator std::basic_string<T> () const
553 {
554 return this->str();
555 }
556
559 {
560 for (dcpp::u32 i=0; array[i]; ++i)
561 array[i] = locale_lower ( array[i] );
562 return *this;
563 }
564
565
568 {
569 for (dcpp::u32 i=0; array[i]; ++i)
570 array[i] = locale_upper ( array[i] );
571 return *this;
572 }
573
574
576
579 {
580 for(dcpp::u32 i=0; array[i] && other[i]; ++i)
581 if (locale_lower( array[i]) != locale_lower(other[i]))
582 return false;
583
584 return used == other.used;
585 }
586
588
592 {
593 if ( (dcpp::u32) sourcePos >= used )
594 return false;
595
596 dcpp::u32 i;
597 for( i=0; array[sourcePos + i] && other[i]; ++i)
598 if (locale_lower( array[sourcePos + i]) != locale_lower(other[i]))
599 return false;
600
601 return array[sourcePos + i] == 0 && other[i] == 0;
602 }
603
604
606
609 {
610 for(dcpp::u32 i=0; array[i] && other.array[i]; ++i)
611 {
612 dcpp::i32 diff = (dcpp::i32) locale_lower ( array[i] ) - (dcpp::i32) locale_lower ( other.array[i] );
613 if ( diff )
614 return diff < 0;
615 }
616
617 return used < other.used;
618 }
619
620
622
625 bool equalsn(const self_type & other, dcpp::u32 n) const
626 {
627 dcpp::u32 i;
628 for(i=0; i < n && array[i] && other[i]; ++i)
629 if (array[i] != other[i])
630 return false;
631
632 // if one (or both) of the strings was smaller then they
633 // are only equal if they have the same length
634 return (i == n) || (used == other.used);
635 }
636
637
639
642 bool equalsn(const T* const str, dcpp::u32 n) const
643 {
644 if (!str)
645 return false;
646 dcpp::u32 i;
647 for(i=0; i < n && array[i] && str[i]; ++i)
648 if (array[i] != str[i])
649 return false;
650
651 // if one (or both) of the strings was smaller then they
652 // are only equal if they have the same length
653 return (i == n) || (array[i] == 0 && str[i] == 0);
654 }
655
656
658
660 {
661 if (used + 1 > allocated)
662 reallocate(used + 1);
663
664 ++used;
665
666 array[used-2] = character;
667 array[used-1] = 0;
668
669 return *this;
670 }
671
672
674
676 self_type & append(const T* const other, dcpp::u32 length=0xffffffff)
677 {
678 if (!other)
679 return *this;
680
681 dcpp::u32 len = 0;
682 const T* p = other;
683 while(*p)
684 {
685 ++len;
686 ++p;
687 }
688 if (len > length)
689 len = length;
690
691 if (used + len > allocated)
692 reallocate(used + len);
693
694 --used;
695 ++len;
696
697 for (dcpp::u32 l=0; l<len; ++l)
698 array[l+used] = *(other+l);
699
700 used += len;
701
702 return *this;
703 }
704
705
707
709 {
710 if (other.size() == 0)
711 return *this;
712
713 --used;
714 const dcpp::u32 len = other.size()+1;
715
716 if (used + len > allocated)
717 reallocate(used + len);
718
719 for (dcpp::u32 l=0; l<len; ++l)
720 array[used+l] = other[l];
721
722 used += len;
723
724 return *this;
725 }
726
727
729
732 {
733 if (other.size() == 0)
734 return *this;
735
736 if (other.size() < length)
737 {
738 append(other);
739 return *this;
740 }
741
742 if (used + length > allocated)
743 reallocate(used + length);
744
745 --used;
746
747 for (dcpp::u32 l=0; l<length; ++l)
748 array[l+used] = other[l];
749 used += length;
750
751 // ensure proper termination
752 array[used]=0;
753 ++used;
754
755 return *this;
756 }
757
759 //\param pos Insert the characters before this index
760 //\param s String to insert. Must be at least of size n
761 //\param n Number of characters from string s to use.
762 self_type & insert(dcpp::u32 pos, const char* s, dcpp::u32 n)
763 {
764 if ( pos < used )
765 {
766 reserve(used+n);
767
768 // move stuff behind insert point
769 const dcpp::u32 end = used+n-1;
770 for (dcpp::u32 i=0; i<used-pos; ++i)
771 {
772 array[end-i] = array[end-(i+n)];
773 }
774 used += n;
775
776 for (dcpp::u32 i=0; i<n; ++i)
777 {
778 array[pos+i] = s[i];
779 }
780 }
781
782 return *this;
783 }
784
786
787 void reserve(dcpp::u32 count)
788 {
789 if (count < allocated)
790 return;
791
792 reallocate(count);
793 }
794
795
797
801 {
802 for (dcpp::u32 i=0; i<used-1; ++i)
803 if (array[i] == c)
804 return i;
805
806 return -1;
807 }
808
810
816 dcpp::i32 findFirstChar(const T* const c, dcpp::u32 count=1) const
817 {
818 if (!c || !count)
819 return -1;
820
821 for (dcpp::u32 i=0; i<used-1; ++i)
822 for (dcpp::u32 j=0; j<count; ++j)
823 if (array[i] == c[j])
824 return i;
825
826 return -1;
827 }
828
829
831
837 template <class B>
838 dcpp::i32 findFirstCharNotInList(const B* const c, dcpp::u32 count=1) const
839 {
840 if (!c || !count)
841 return -1;
842
843 for (dcpp::u32 i=0; i<used-1; ++i)
844 {
845 dcpp::u32 j;
846 for (j=0; j<count; ++j)
847 if (array[i] == c[j])
848 break;
849
850 if (j==count)
851 return i;
852 }
853
854 return -1;
855 }
856
858
864 template <class B>
865 dcpp::i32 findLastCharNotInList(const B* const c, dcpp::u32 count=1) const
866 {
867 if (!c || !count)
868 return -1;
869
870 for (dcpp::i32 i=(dcpp::i32)(used-2); i>=0; --i)
871 {
872 dcpp::u32 j;
873 for (j=0; j<count; ++j)
874 if (array[i] == c[j])
875 break;
876
877 if (j==count)
878 return i;
879 }
880
881 return -1;
882 }
883
885
890 {
891 for (dcpp::u32 i=startPos; i<used-1; ++i)
892 if (array[i] == c)
893 return i;
894
895 return -1;
896 }
897
898
900
904 dcpp::i32 findLast(T c, dcpp::i32 start = -1) const
905 {
906 start = nub::clamp ( start < 0 ? (dcpp::i32)(used) - 2 : start, 0, (dcpp::i32)(used) - 2 );
907 for (dcpp::i32 i=start; i>=0; --i)
908 if (array[i] == c)
909 return i;
910
911 return -1;
912 }
913
915
921 dcpp::i32 findLastChar(const T* const c, dcpp::u32 count=1) const
922 {
923 if (!c || !count)
924 return -1;
925
926 for (dcpp::i32 i=(dcpp::i32)used-2; i>=0; --i)
927 for (dcpp::u32 j=0; j<count; ++j)
928 if (array[i] == c[j])
929 return i;
930
931 return -1;
932 }
933
934
936
940 template <class B>
941 dcpp::i32 find(const B* const str, const dcpp::u32 start = 0) const
942 {
943 if (str && *str)
944 {
945 dcpp::u32 len = 0;
946
947 while (str[len])
948 ++len;
949
950 if (len > used-1)
951 return -1;
952
953 for (dcpp::u32 i=start; i<used-len; ++i)
954 {
955 dcpp::u32 j=0;
956
957 while(str[j] && array[i+j] == str[j])
958 ++j;
959
960 if (!str[j])
961 return i;
962 }
963 }
964
965 return -1;
966 }
967
968
970
974 {
975 // clamp length to maximal value
976 if ((length+begin) > size())
977 length = size()-begin;
978 // if start after string
979 // or no proper substring length
980 if ((length <= 0) || (begin>=size()))
981 return self_type{""};
982
983 self_type o;
984 o.reserve(length+1);
985
986 if ( !make_lower )
987 {
988 for (dcpp::i32 i=0; i<length; ++i)
989 o.array[i] = array[i+begin];
990 }
991 else
992 {
993 for (dcpp::i32 i=0; i<length; ++i)
994 o.array[i] = locale_lower ( array[i+begin] );
995 }
996
997 o.array[length] = 0;
998 o.used = length + 1;
999
1000 return o;
1001 }
1002
1003
1005
1007 {
1008 append(c);
1009 return *this;
1010 }
1011
1012
1014
1015 self_type & operator += (const T* const c)
1016 {
1017 append(c);
1018 return *this;
1019 }
1020
1021
1023
1025 {
1026 append(other);
1027 return *this;
1028 }
1029
1030
1032
1034 {
1035 append(self_type(i));
1036 return *this;
1037 }
1038
1039
1041
1042 self_type & operator += (const unsigned int i)
1043 {
1044 append(self_type(i));
1045 return *this;
1046 }
1047
1048
1050
1051 self_type & operator += (const long i)
1052 {
1053 append(self_type(i));
1054 return *this;
1055 }
1056
1057
1059
1060 self_type & operator += (const unsigned long i)
1061 {
1062 append(self_type(i));
1063 return *this;
1064 }
1065
1066
1068
1069 self_type & operator += (const double i)
1070 {
1071 append(self_type(i));
1072 return *this;
1073 }
1074
1075
1077
1078 self_type & operator += (const float i)
1079 {
1080 append(self_type(i));
1081 return *this;
1082 }
1083
1084
1086
1089 {
1090 for (dcpp::u32 i=0; i<used-1; ++i)
1091 if (array[i] == toReplace)
1092 array[i] = replaceWith;
1093 return *this;
1094 }
1095
1096
1098
1101 {
1102 if (toReplace.size() == 0)
1103 return *this;
1104
1105 const T* other = toReplace.data();
1106 const T* replace = replaceWith.data();
1107 const dcpp::u32 other_size = toReplace.size();
1108 const dcpp::u32 replace_size = replaceWith.size();
1109
1110 // Determine the delta. The algorithm will change depending on the delta.
1112
1113 // A character for character replace. The string will not shrink or grow.
1114 if (delta == 0)
1115 {
1116 dcpp::i32 pos = 0;
1117 while ((pos = find(other, pos)) != -1)
1118 {
1119 for (dcpp::u32 i = 0; i < replace_size; ++i)
1120 array[pos + i] = replace[i];
1121 ++pos;
1122 }
1123 return *this;
1124 }
1125
1126 // We are going to be removing some characters. The string will shrink.
1127 if (delta < 0)
1128 {
1129 dcpp::u32 i = 0;
1130 for (dcpp::u32 pos = 0; pos < used; ++i, ++pos)
1131 {
1132 // Is this potentially a match?
1133 if (array[pos] == *other)
1134 {
1135 // Check to see if we have a match.
1136 dcpp::u32 j;
1137 for (j = 0; j < other_size; ++j)
1138 {
1139 if (array[pos + j] != other[j])
1140 break;
1141 }
1142
1143 // If we have a match, replace characters.
1144 if (j == other_size)
1145 {
1146 for (j = 0; j < replace_size; ++j)
1147 array[i + j] = replace[j];
1148 i += replace_size - 1;
1149 pos += other_size - 1;
1150 continue;
1151 }
1152 }
1153
1154 // No match found, just copy characters.
1155 array[i] = array[pos];
1156 }
1157 array[i-1] = 0;
1158 used = i;
1159
1160 return *this;
1161 }
1162
1163 // We are going to be adding characters, so the string size will increase.
1164 // Count the number of times toReplace exists in the string so we can allocate the new size.
1166 dcpp::i32 pos = 0;
1167 while ((pos = find(other, pos)) != -1)
1168 {
1169 ++find_count;
1170 ++pos;
1171 }
1172
1173 // Re-allocate the string now, if needed.
1175 if (used + len > allocated)
1176 reallocate(used + len);
1177
1178 // Start replacing.
1179 pos = 0;
1180 while ((pos = find(other, pos)) != -1)
1181 {
1182 T* start = array + pos + other_size - 1;
1183 T* ptr = array + used - 1;
1184 T* end = array + delta + used -1;
1185
1186 // Shift characters to make room for the string.
1187 while (ptr != start)
1188 {
1189 *end = *ptr;
1190 --ptr;
1191 --end;
1192 }
1193
1194 // Add the new string now.
1195 for (dcpp::u32 i = 0; i < replace_size; ++i)
1196 array[pos + i] = replace[i];
1197
1198 pos += replace_size;
1199 used += delta;
1200 }
1201
1202 return *this;
1203 }
1204
1205
1207
1209 {
1210 dcpp::u32 pos = 0;
1211 dcpp::u32 found = 0;
1212 for (dcpp::u32 i=0; i<used-1; ++i)
1213 {
1214 if (array[i] == c)
1215 {
1216 ++found;
1217 continue;
1218 }
1219
1220 array[pos++] = array[i];
1221 }
1222 used -= found;
1223 array[used-1] = 0;
1224 return *this;
1225 }
1226
1227
1229
1231 {
1232 dcpp::u32 size = toRemove.size();
1233 if ( size == 0 )
1234 return *this;
1235 dcpp::u32 pos = 0;
1236 dcpp::u32 found = 0;
1237 for (dcpp::u32 i=0; i<used-1; ++i)
1238 {
1239 dcpp::u32 j = 0;
1240 while (j < size)
1241 {
1242 if (array[i + j] != toRemove[j])
1243 break;
1244 ++j;
1245 }
1246 if (j == size)
1247 {
1248 found += size;
1249 i += size - 1;
1250 continue;
1251 }
1252
1253 array[pos++] = array[i];
1254 }
1255 used -= found;
1256 array[used-1] = 0;
1257 return *this;
1258 }
1259
1260
1262
1264 {
1265 if (characters.size() == 0)
1266 return *this;
1267
1268 dcpp::u32 pos = 0;
1269 dcpp::u32 found = 0;
1270 for (dcpp::u32 i=0; i<used-1; ++i)
1271 {
1272 // Don't use characters.findFirst as it finds the \0,
1273 // causing used to become incorrect.
1274 bool docontinue = false;
1275 for (dcpp::u32 j=0; j<characters.size(); ++j)
1276 {
1277 if (characters[j] == array[i])
1278 {
1279 ++found;
1280 docontinue = true;
1281 break;
1282 }
1283 }
1284 if (docontinue)
1285 continue;
1286
1287 array[pos++] = array[i];
1288 }
1289 used -= found;
1290 array[used-1] = 0;
1291
1292 return *this;
1293 }
1294
1295
1297
1299 self_type & trim(const self_type & whitespace = " \t\n\r")
1300 {
1301 // find start and end of the substring without the specified characters
1302 const dcpp::i32 begin = findFirstCharNotInList(whitespace.data(), whitespace.used);
1303 if (begin == -1)
1304 return (*this="");
1305
1306 const dcpp::i32 end = findLastCharNotInList(whitespace.data(), whitespace.used);
1307
1308 return (*this = subString(begin, (end +1) - begin));
1309 }
1310
1312
1321 {
1323 if ( i > 0 && (dcpp::u32)i < used-2 ) // non 0 must be found and not last char (also used is at least 2 when i > 0)
1324 {
1326 dcpp::u32 dot=0;
1327 if( nub::isdigit(array[i]) )
1328 {
1329 while( --i>0 && nub::isdigit(array[i]) );
1330 if ( array[i] == decimalPoint )
1331 dot = i;
1332 }
1333 else if ( array[i] == decimalPoint )
1334 {
1335 dot = i;
1336 eraseStart = i;
1337 }
1338 if ( dot > 0 && nub::isdigit(array[dot-1]) )
1339 {
1340 array[eraseStart] = 0;
1341 used = eraseStart+1;
1342 }
1343 }
1344 return *this;
1345 }
1346
1348
1352 {
1353 DCPP_DEBUG_BREAK_IF(index>=used) // access violation
1354
1355 for (dcpp::u32 i=index+1; i<used; ++i)
1356 array[i-1] = array[i];
1357
1358 --used;
1359 return *this;
1360 }
1361
1364 {
1365 // terminate on existing null
1366 for (dcpp::u32 i=0; i<allocated; ++i)
1367 {
1368 if (array[i] == 0)
1369 {
1370 used = i + 1;
1371 return *this;
1372 }
1373 }
1374
1375 // terminate
1376 if ( allocated > 0 )
1377 {
1378 used = allocated;
1379 array[used-1] = 0;
1380 }
1381 else
1382 {
1383 used = 0;
1384 }
1385
1386 return *this;
1387 }
1388
1390 T lastChar() const
1391 {
1392 return used > 1 ? array[used-2] : 0;
1393 }
1394
1396
1414 template<class container>
1416 {
1417 if (!delimiter)
1418 return 0;
1419
1420 const dcpp::u32 oldSize=ret.size();
1421
1423 for (dcpp::u32 i=0; i<used; ++i)
1424 {
1425 for (dcpp::u32 j=0; j<countDelimiters; ++j)
1426 {
1427 if (array[i] == delimiter[j])
1428 {
1429 if (i - tokenStartIdx > 0)
1430 ret.push_back(self_type(&array[tokenStartIdx], i - tokenStartIdx));
1431 else if ( !ignoreEmptyTokens )
1432 ret.push_back(self_type());
1433 if ( keepSeparators )
1434 {
1435 ret.push_back(self_type(&array[i], 1));
1436 }
1437
1438 tokenStartIdx = i+1;
1439 break;
1440 }
1441 }
1442 }
1443 if ((used - 1) > tokenStartIdx)
1444 ret.push_back(self_type(&array[tokenStartIdx], (used - 1) - tokenStartIdx));
1445 else if ( !ignoreEmptyTokens )
1446 ret.push_back(self_type());
1447
1448 return ret.size()-oldSize;
1449 }
1450
1452
1453private:
1454
1456 void reallocate(dcpp::u32 new_size)
1457 {
1458 T* old_array = array;
1459
1460 array = allocator.allocate(new_size); //new T[new_size];
1461 allocated = new_size;
1462
1463 const dcpp::u32 amount = used < new_size ? used : new_size;
1464 for (dcpp::u32 i=0; i<amount; ++i)
1465 array[i] = old_array[i];
1466
1467 if (allocated < used)
1468 used = allocated;
1469
1470 allocator.deallocate(old_array); // delete [] old_array;
1471 }
1472
1473 //--- member variables
1474
1475 T* array;
1476 dcpp::u32 allocated;
1477 dcpp::u32 used;
1478 TAlloc allocator;
1479}; // class basic_string
1480
1482
1487static inline size_t multibyteToWString(dcpp::nub::wstring & destination, const dcpp::nub::string & source)
1488{
1489 return multibyteToWString(destination, source.data(), (dcpp::u32)source.size());
1490}
1491
1493
1498static inline size_t multibyteToWString(dcpp::nub::wstring & destination, const char* source)
1499{
1500 const dcpp::u32 s = source ? (dcpp::u32)strlen(source) : 0;
1501 return multibyteToWString(destination, source, s);
1502}
1503
1505static size_t multibyteToWString(dcpp::nub::wstring & destination, const char* source, dcpp::u32 sourceSize)
1506{
1507 if ( sourceSize )
1508 {
1509 destination.reserve(sourceSize+1);
1510#if defined(_MSC_VER)
1511#pragma warning(push)
1512#pragma warning(disable: 4996) // 'mbstowcs': This function or variable may be unsafe. Consider using mbstowcs_s instead.
1513#endif
1514 const size_t written = mbstowcs(destination.array, source, (size_t)sourceSize);
1515#if defined(_MSC_VER)
1516#pragma warning(pop)
1517#endif
1518 if ( written != (size_t)-1 )
1519 {
1520 destination.used = (dcpp::u32)written+1;
1521 destination.array[destination.used-1] = 0;
1522 }
1523 else
1524 {
1525 // Likely character which got converted until the invalid character was encountered are in destination now.
1526 // And it seems even 0-terminated, but I found no documentation anywhere that this (the 0-termination) is guaranteed :-(
1527 destination.clear();
1528 }
1529 return written;
1530 }
1531 else
1532 {
1533 destination.clear();
1534 return 0;
1535 }
1536}
1537
1538} // namespace dcpp::nub
1539
1540#endif
1541
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.hpp:22
Self reallocating template array (like stl vector) with additional features.
Definition irrArray.hpp:23
self_type & insert(dcpp::u32 pos, const char *s, dcpp::u32 n)
Insert a certain amount of characters into the string before the given index.
Definition irrString.hpp:762
self_type & replace(T toReplace, T replaceWith)
Replaces all characters of a special type with another one.
Definition irrString.hpp:1088
self_type & erase(dcpp::u32 index)
Erases a character from the string.
Definition irrString.hpp:1351
basic_string(const dcpp::nub::basic_string< B, A > &other)
Constructor from other string types.
Definition irrString.hpp:127
self_type & append(const self_type &other, dcpp::u32 length)
Appends a string of the length l to this string.
Definition irrString.hpp:731
dcpp::i32 findFirst(T c) const
finds first occurrence of character in string
Definition irrString.hpp:800
dcpp::i32 findFirstCharNotInList(const B *const c, dcpp::u32 count=1) const
Finds first position of a character not in a given list.
Definition irrString.hpp:838
dcpp::i32 findFirstChar(const T *const c, dcpp::u32 count=1) const
finds first occurrence of a character of a list in string
Definition irrString.hpp:816
dcpp::i32 find(const B *const str, const dcpp::u32 start=0) const
finds another string in this string
Definition irrString.hpp:941
self_type & operator=(const self_type &other)
Assignment operator.
Definition irrString.hpp:343
basic_string(const B *const c)
Constructor for Unicode and ASCII strings.
Definition irrString.hpp:326
self_type & append(T character)
Appends a character to this string.
Definition irrString.hpp:659
bool operator!=(const T *const str) const
Inequality operator.
Definition irrString.hpp:497
self_type operator+(const B *const c) const
Append operator for strings, ASCII and Unicode.
Definition irrString.hpp:431
self_type & operator+=(T c)
Appends a character to this string.
Definition irrString.hpp:1006
bool empty() const
Definition irrString.hpp:520
bool operator==(const self_type &other) const
Equality operator.
Definition irrString.hpp:472
basic_string(const B *const c, dcpp::u32 length)
Constructor for copying a string from a pointer with a given length.
Definition irrString.hpp:304
dcpp::i32 findLast(T c, dcpp::i32 start=-1) const
finds last occurrence of character in string
Definition irrString.hpp:904
self_type & operator=(const B *const c)
Assignment operator for strings, ASCII and Unicode.
Definition irrString.hpp:374
self_type subString(dcpp::u32 begin, dcpp::i32 length, bool make_lower=false) const
Returns a substring.
Definition irrString.hpp:973
self_type & make_lower()
Makes the string lower case.
Definition irrString.hpp:558
bool operator==(const T *const str) const
Equality operator.
Definition irrString.hpp:457
std::basic_string< T > str() const
Returns std::string or std::wstring. The traits_type and allocator_type of the returned std::basic_st...
Definition irrString.hpp:545
virtual ~basic_string()
Destructor.
Definition irrString.hpp:336
dcpp::i32 findLastChar(const T *const c, dcpp::u32 count=1) const
finds last occurrence of a character of a list in string
Definition irrString.hpp:921
bool operator!=(const self_type &other) const
Inequality operator.
Definition irrString.hpp:504
friend size_t multibyteToWString(dcpp::nub::wstring &destination, const char *source, dcpp::u32 sourceSize)
Internally used by the other multibyteToWString functions.
Definition irrString.hpp:1505
bool lower_ignore_case(const self_type &other) const
Compares the strings ignoring case.
Definition irrString.hpp:608
self_type & append(const T *const other, dcpp::u32 length=0xffffffff)
Appends a char string to this string.
Definition irrString.hpp:676
dcpp::i32 findLastCharNotInList(const B *const c, dcpp::u32 count=1) const
Finds last position of a character not in a given list.
Definition irrString.hpp:865
basic_string(unsigned long number)
Constructs a string from an unsigned long.
Definition irrString.hpp:272
bool operator<(const self_type &other) const
Is smaller comparator.
Definition irrString.hpp:483
self_type & append(const self_type &other)
Appends a string to this string.
Definition irrString.hpp:708
basic_string(int number)
Constructs a string from an int.
Definition irrString.hpp:145
self_type & replace(const self_type &toReplace, const self_type &replaceWith)
Replaces all instances of a string with another one.
Definition irrString.hpp:1100
basic_string()
Default constructor.
Definition irrString.hpp:110
bool equals_substring_ignore_case(const self_type &other, const dcpp::i32 sourcePos=0) const
Compares the strings ignoring case.
Definition irrString.hpp:591
void reserve(dcpp::u32 count)
Reserves some memory.
Definition irrString.hpp:787
self_type & remove(const self_type &toRemove)
Removes a string from the string.
Definition irrString.hpp:1230
T lastChar() const
gets the last char of a string or null
Definition irrString.hpp:1390
basic_string(long number)
Constructs a string from a long.
Definition irrString.hpp:224
dcpp::i32 findNext(T c, dcpp::u32 startPos) const
finds next occurrence of character in string
Definition irrString.hpp:889
self_type & eraseTrailingFloatZeros(char decimalPoint='.')
Erase 0's at the end when a string ends with a floating point number.
Definition irrString.hpp:1320
bool equals_ignore_case(const self_type &other) const
Compares the strings ignoring case.
Definition irrString.hpp:578
self_type & trim(const self_type &whitespace=" \t\n\r")
Trims the string.
Definition irrString.hpp:1299
self_type & removeChars(const self_type &characters)
Removes characters from a string.
Definition irrString.hpp:1263
self_type & remove(T c)
Removes characters from a string.
Definition irrString.hpp:1208
dcpp::u32 split(container &ret, const T *const delimiter, dcpp::u32 countDelimiters=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
Split string into parts (tokens).
Definition irrString.hpp:1415
dcpp::u32 size() const
Returns length of the string's content.
Definition irrString.hpp:513
const T * data() const
Returns character string.
Definition irrString.hpp:537
self_type operator+(const self_type &other) const
Append operator for other strings.
Definition irrString.hpp:420
const T & operator[](const dcpp::u32 index) const
Direct access operator.
Definition irrString.hpp:449
bool equalsn(const T *const str, dcpp::u32 n) const
compares the first n characters of the strings
Definition irrString.hpp:642
bool equalsn(const self_type &other, dcpp::u32 n) const
compares the first n characters of the strings
Definition irrString.hpp:625
T & operator[](const dcpp::u32 index)
Direct access operator.
Definition irrString.hpp:441
basic_string(const double number)
Constructs a string from a float.
Definition irrString.hpp:135
self_type & operator=(const dcpp::nub::basic_string< B, A > &other)
Assignment operator for other string types.
Definition irrString.hpp:365
self_type & make_upper()
Makes the string upper case.
Definition irrString.hpp:567
basic_string(unsigned int number)
Constructs a string from an unsigned int.
Definition irrString.hpp:193
self_type & validate()
verify the existing string.
Definition irrString.hpp:1363
basic_string(const self_type &other)
Constructor.
Definition irrString.hpp:119
Basic classes such as vectors, planes, arrays, lists, and so on can be found in this namespace.
Definition vector3d.hpp:13
DUCKCPP_API void wcharToUtf8(const wchar_t *in, char *out, const dcpp::u64 len)
Convert this wchar string to utf-8.
const T clamp(const T &value, const T &low, const T &high)
clamps a value between low and high
Definition irrMath.hpp:164
dcpp::i32 isdigit(dcpp::i32 c)
some standard function ( to remove dependencies )
Definition coreutil.hpp:197
DUCKCPP_API void utf8ToWchar(const char *in, wchar_t *out, const dcpp::u64 len)
Convert this utf-8-encoded string to the platform's wchar.
char c8
8 bit character variable.
Definition irrTypes.hpp:37
signed int i32
32 bit signed variable.
Definition irrTypes.hpp:72
unsigned int u32
32 bit unsigned variable.
Definition irrTypes.hpp:64

Duckcpp    @cppfx.xyz