Nirtcpp 2.1.0
Nirtcpp 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 nirtcpp/nirtcpp.hpp and irrXML.h
4
5#ifndef NIRT_STRING_HPP_INCLUDED
6#define NIRT_STRING_HPP_INCLUDED
7
8#include <nirtcpp/core/engine/nirt_types.hpp>
9#include <nirtcpp/core/engine/irrAllocator.hpp>
10#include <nirtcpp/core/engine/irrMath.hpp>
11#include <sstream>
12#include <iomanip>
13
14namespace nirt
15{
16namespace core
17{
18
20
34// forward declarations
35template <typename T, typename TAlloc = irrAllocator<T> >
36class string;
37static size_t multibyteToWString(string<wchar_t>& destination, const char* source, u32 sourceSize);
38inline s32 isdigit(s32 c);
39
40enum eLocaleID
41{
42 NIRT_LOCALE_ANSI = 0,
43 NIRT_LOCALE_GERMAN = 1
44};
45
46static eLocaleID locale_current = NIRT_LOCALE_ANSI;
47static inline void locale_set ( eLocaleID id )
48{
49 locale_current = id;
50}
51
53static inline u32 locale_lower ( u32 x )
54{
55 switch ( locale_current )
56 {
57 case NIRT_LOCALE_GERMAN:
58 case NIRT_LOCALE_ANSI:
59 break;
60 }
61 // ansi
62 return x >= 'A' && x <= 'Z' ? x + 0x20 : x;
63}
64
66static inline u32 locale_upper ( u32 x )
67{
68 switch ( locale_current )
69 {
70 case NIRT_LOCALE_GERMAN:
71 case NIRT_LOCALE_ANSI:
72 break;
73 }
74
75 // ansi
76 return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x;
77}
78
80
83NIRTCPP_API void utf8ToWchar(const char *in, wchar_t *out, const u64 len);
84
86
89NIRTCPP_API void wcharToUtf8(const wchar_t *in, char *out, const u64 len);
90
91
92template <typename T, typename TAlloc>
93class string
94{
95public:
96
97 using char_type = T;
98
101 : array(0), allocated(1), used(1)
102 {
103 array = allocator.allocate(1); // new T[1];
104 array[0] = 0;
105 }
106
107
110 : array(0), allocated(0), used(0)
111 {
112 *this = other;
113 }
114
116 template <class B, class A>
118 : array(0), allocated(0), used(0)
119 {
120 *this = other;
121 }
122
123
125 explicit string(const double number)
126 : array(0), allocated(0), used(0)
127 {
128 std::ostringstream tmpbuf; // new: do not limit tmpbuf string size.
129 tmpbuf << std::fixed << std::setprecision(6) << number;
130 *this = tmpbuf.str().data();
131 }
132
133
135 explicit string(int number)
136 : array(0), allocated(0), used(0)
137 {
138 // store if negative and make positive
139
140 bool negative = false;
141 if (number < 0)
142 {
143 number *= -1;
144 negative = true;
145 }
146
147 // temporary buffer for 16 numbers
148
149 c8 tmpbuf[16]={0};
150 u32 idx = 15;
151
152 // special case '0'
153
154 if (!number)
155 {
156 tmpbuf[14] = '0';
157 *this = &tmpbuf[14];
158 return;
159 }
160
161 // add numbers
162
163 while(number && idx)
164 {
165 --idx;
166 tmpbuf[idx] = (c8)('0' + (number % 10));
167 number /= 10;
168 }
169
170 // add sign
171
172 if (negative)
173 {
174 --idx;
175 tmpbuf[idx] = '-';
176 }
177
178 *this = &tmpbuf[idx];
179 }
180
181
183 explicit string(unsigned int number)
184 : array(0), allocated(0), used(0)
185 {
186 // temporary buffer for 16 numbers
187
188 c8 tmpbuf[16]={0};
189 u32 idx = 15;
190
191 // special case '0'
192
193 if (!number)
194 {
195 tmpbuf[14] = '0';
196 *this = &tmpbuf[14];
197 return;
198 }
199
200 // add numbers
201
202 while(number && idx)
203 {
204 --idx;
205 tmpbuf[idx] = (c8)('0' + (number % 10));
206 number /= 10;
207 }
208
209 *this = &tmpbuf[idx];
210 }
211
212
214 explicit string(long number)
215 : array(0), allocated(0), used(0)
216 {
217 // store if negative and make positive
218
219 bool negative = false;
220 if (number < 0)
221 {
222 number *= -1;
223 negative = true;
224 }
225
226 // temporary buffer for 16 numbers
227
228 c8 tmpbuf[16]={0};
229 u32 idx = 15;
230
231 // special case '0'
232
233 if (!number)
234 {
235 tmpbuf[14] = '0';
236 *this = &tmpbuf[14];
237 return;
238 }
239
240 // add numbers
241
242 while(number && idx)
243 {
244 --idx;
245 tmpbuf[idx] = (c8)('0' + (number % 10));
246 number /= 10;
247 }
248
249 // add sign
250
251 if (negative)
252 {
253 --idx;
254 tmpbuf[idx] = '-';
255 }
256
257 *this = &tmpbuf[idx];
258 }
259
260
262 explicit string(unsigned long number)
263 : array(0), allocated(0), used(0)
264 {
265 // temporary buffer for 16 numbers
266
267 c8 tmpbuf[16]={0};
268 u32 idx = 15;
269
270 // special case '0'
271
272 if (!number)
273 {
274 tmpbuf[14] = '0';
275 *this = &tmpbuf[14];
276 return;
277 }
278
279 // add numbers
280
281 while(number && idx)
282 {
283 --idx;
284 tmpbuf[idx] = (c8)('0' + (number % 10));
285 number /= 10;
286 }
287
288 *this = &tmpbuf[idx];
289 }
290
291
293 template <class B>
294 string(const B* const c, u32 length)
295 : array(0), allocated(0), used(0)
296 {
297 if (!c)
298 {
299 // correctly init the string to an empty one
300 *this="";
301 return;
302 }
303
304 allocated = used = length+1;
305 array = allocator.allocate(used); // new T[used];
306
307 for (u32 l = 0; l<length; ++l)
308 array[l] = (T)c[l];
309
310 array[length] = 0;
311 }
312
313
315 template <class B>
316 string(const B* const c)
317 : array(0), allocated(0), used(0)
318 {
319 *this = c;
320 }
321
322
325 {
326 allocator.deallocate(array); // delete [] array;
327 }
328
329
332 {
333 if (this == &other)
334 return *this;
335
336 used = other.size()+1;
337 if (used>allocated)
338 {
339 allocator.deallocate(array); // delete [] array;
340 allocated = used;
341 array = allocator.allocate(used); //new T[used];
342 }
343
344 const T* p = other.data();
345 for (u32 i=0; i<used; ++i, ++p)
346 array[i] = *p;
347
348 return *this;
349 }
350
352 template <class B, class A>
354 {
355 *this = other.data();
356 return *this;
357 }
358
359
361 template <class B>
362 string<T,TAlloc>& operator=(const B* const c)
363 {
364 if (!c)
365 {
366 if (!array)
367 {
368 array = allocator.allocate(1); //new T[1];
369 allocated = 1;
370 }
371 used = 1;
372 array[0] = 0x0;
373 return *this;
374 }
375
376 if ((void*)c == (void*)array)
377 return *this;
378
379 u32 len = 0;
380 const B* p = c;
381 do
382 {
383 ++len;
384 } while(*p++);
385
386 // we'll keep the old string for a while, because the new
387 // string could be a part of the current string.
388 T* oldArray = array;
389
390 used = len;
391 if (used>allocated)
392 {
393 allocated = used;
394 array = allocator.allocate(used); //new T[used];
395 }
396
397 for (u32 l = 0; l<len; ++l)
398 array[l] = (T)c[l];
399
400 if (oldArray != array)
401 allocator.deallocate(oldArray); // delete [] oldArray;
402
403 return *this;
404 }
405
406
409 {
410 string<T,TAlloc> str(*this);
411 str.append(other);
412
413 return str;
414 }
415
416
418 template <class B>
419 string<T,TAlloc> operator+(const B* const c) const
420 {
421 string<T,TAlloc> str(*this);
422 str.append(c);
423
424 return str;
425 }
426
427
429 T& operator [](const u32 index)
430 {
431 NIRT_DEBUG_BREAK_IF(index>=used) // bad index
432 return array[index];
433 }
434
435
437 const T& operator [](const u32 index) const
438 {
439 NIRT_DEBUG_BREAK_IF(index>=used) // bad index
440 return array[index];
441 }
442
443
445 bool operator==(const T* const str) const
446 {
447 if (!str)
448 return false;
449
450 u32 i;
451 for (i=0; array[i] && str[i]; ++i)
452 if (array[i] != str[i])
453 return false;
454
455 return (!array[i] && !str[i]);
456 }
457
458
461 {
462 for (u32 i=0; array[i] && other.array[i]; ++i)
463 if (array[i] != other.array[i])
464 return false;
465
466 return used == other.used;
467 }
468
469
472 {
473 for (u32 i=0; array[i] && other.array[i]; ++i)
474 {
475 const s32 diff = array[i] - other.array[i];
476 if (diff)
477 return (diff < 0);
478 }
479
480 return (used < other.used);
481 }
482
483
485 bool operator!=(const T* const str) const
486 {
487 return !(*this == str);
488 }
489
490
493 {
494 return !(*this == other);
495 }
496
497
499
501 u32 size() const
502 {
503 return used-1;
504 }
505
508 bool empty() const
509 {
510 return (size() == 0);
511 }
512
513 void clear(bool releaseMemory=true)
514 {
515 if ( releaseMemory )
516 {
517 reallocate(1);
518 }
519 array[0] = 0;
520 used = 1;
521 }
522
524
525 const T* data() const
526 {
527 return array;
528 }
529
530
533 {
534 for (u32 i=0; array[i]; ++i)
535 array[i] = locale_lower ( array[i] );
536 return *this;
537 }
538
539
542 {
543 for (u32 i=0; array[i]; ++i)
544 array[i] = locale_upper ( array[i] );
545 return *this;
546 }
547
548
550
553 {
554 for(u32 i=0; array[i] && other[i]; ++i)
555 if (locale_lower( array[i]) != locale_lower(other[i]))
556 return false;
557
558 return used == other.used;
559 }
560
562
566 {
567 if ( (u32) sourcePos >= used )
568 return false;
569
570 u32 i;
571 for( i=0; array[sourcePos + i] && other[i]; ++i)
572 if (locale_lower( array[sourcePos + i]) != locale_lower(other[i]))
573 return false;
574
575 return array[sourcePos + i] == 0 && other[i] == 0;
576 }
577
578
580
583 {
584 for(u32 i=0; array[i] && other.array[i]; ++i)
585 {
586 s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] );
587 if ( diff )
588 return diff < 0;
589 }
590
591 return used < other.used;
592 }
593
594
596
599 bool equalsn(const string<T,TAlloc>& other, u32 n) const
600 {
601 u32 i;
602 for(i=0; i < n && array[i] && other[i]; ++i)
603 if (array[i] != other[i])
604 return false;
605
606 // if one (or both) of the strings was smaller then they
607 // are only equal if they have the same length
608 return (i == n) || (used == other.used);
609 }
610
611
613
616 bool equalsn(const T* const str, u32 n) const
617 {
618 if (!str)
619 return false;
620 u32 i;
621 for(i=0; i < n && array[i] && str[i]; ++i)
622 if (array[i] != str[i])
623 return false;
624
625 // if one (or both) of the strings was smaller then they
626 // are only equal if they have the same length
627 return (i == n) || (array[i] == 0 && str[i] == 0);
628 }
629
630
632
634 {
635 if (used + 1 > allocated)
636 reallocate(used + 1);
637
638 ++used;
639
640 array[used-2] = character;
641 array[used-1] = 0;
642
643 return *this;
644 }
645
646
648
650 string<T,TAlloc>& append(const T* const other, u32 length=0xffffffff)
651 {
652 if (!other)
653 return *this;
654
655 u32 len = 0;
656 const T* p = other;
657 while(*p)
658 {
659 ++len;
660 ++p;
661 }
662 if (len > length)
663 len = length;
664
665 if (used + len > allocated)
666 reallocate(used + len);
667
668 --used;
669 ++len;
670
671 for (u32 l=0; l<len; ++l)
672 array[l+used] = *(other+l);
673
674 used += len;
675
676 return *this;
677 }
678
679
681
683 {
684 if (other.size() == 0)
685 return *this;
686
687 --used;
688 const u32 len = other.size()+1;
689
690 if (used + len > allocated)
691 reallocate(used + len);
692
693 for (u32 l=0; l<len; ++l)
694 array[used+l] = other[l];
695
696 used += len;
697
698 return *this;
699 }
700
701
703
706 {
707 if (other.size() == 0)
708 return *this;
709
710 if (other.size() < length)
711 {
712 append(other);
713 return *this;
714 }
715
716 if (used + length > allocated)
717 reallocate(used + length);
718
719 --used;
720
721 for (u32 l=0; l<length; ++l)
722 array[l+used] = other[l];
723 used += length;
724
725 // ensure proper termination
726 array[used]=0;
727 ++used;
728
729 return *this;
730 }
731
733 //\param pos Insert the characters before this index
734 //\param s String to insert. Must be at least of size n
735 //\param n Number of characters from string s to use.
736 string<T,TAlloc>& insert(u32 pos, const char* s, u32 n)
737 {
738 if ( pos < used )
739 {
740 reserve(used+n);
741
742 // move stuff behind insert point
743 const u32 end = used+n-1;
744 for (u32 i=0; i<used-pos; ++i)
745 {
746 array[end-i] = array[end-(i+n)];
747 }
748 used += n;
749
750 for (u32 i=0; i<n; ++i)
751 {
752 array[pos+i] = s[i];
753 }
754 }
755
756 return *this;
757 }
758
760
761 void reserve(u32 count)
762 {
763 if (count < allocated)
764 return;
765
766 reallocate(count);
767 }
768
769
771
774 s32 findFirst(T c) const
775 {
776 for (u32 i=0; i<used-1; ++i)
777 if (array[i] == c)
778 return i;
779
780 return -1;
781 }
782
784
790 s32 findFirstChar(const T* const c, u32 count=1) const
791 {
792 if (!c || !count)
793 return -1;
794
795 for (u32 i=0; i<used-1; ++i)
796 for (u32 j=0; j<count; ++j)
797 if (array[i] == c[j])
798 return i;
799
800 return -1;
801 }
802
803
805
811 template <class B>
812 s32 findFirstCharNotInList(const B* const c, u32 count=1) const
813 {
814 if (!c || !count)
815 return -1;
816
817 for (u32 i=0; i<used-1; ++i)
818 {
819 u32 j;
820 for (j=0; j<count; ++j)
821 if (array[i] == c[j])
822 break;
823
824 if (j==count)
825 return i;
826 }
827
828 return -1;
829 }
830
832
838 template <class B>
839 s32 findLastCharNotInList(const B* const c, u32 count=1) const
840 {
841 if (!c || !count)
842 return -1;
843
844 for (s32 i=(s32)(used-2); i>=0; --i)
845 {
846 u32 j;
847 for (j=0; j<count; ++j)
848 if (array[i] == c[j])
849 break;
850
851 if (j==count)
852 return i;
853 }
854
855 return -1;
856 }
857
859
864 {
865 for (u32 i=startPos; i<used-1; ++i)
866 if (array[i] == c)
867 return i;
868
869 return -1;
870 }
871
872
874
878 s32 findLast(T c, s32 start = -1) const
879 {
880 start = core::clamp ( start < 0 ? (s32)(used) - 2 : start, 0, (s32)(used) - 2 );
881 for (s32 i=start; i>=0; --i)
882 if (array[i] == c)
883 return i;
884
885 return -1;
886 }
887
889
895 s32 findLastChar(const T* const c, u32 count=1) const
896 {
897 if (!c || !count)
898 return -1;
899
900 for (s32 i=(s32)used-2; i>=0; --i)
901 for (u32 j=0; j<count; ++j)
902 if (array[i] == c[j])
903 return i;
904
905 return -1;
906 }
907
908
910
914 template <class B>
915 s32 find(const B* const str, const u32 start = 0) const
916 {
917 if (str && *str)
918 {
919 u32 len = 0;
920
921 while (str[len])
922 ++len;
923
924 if (len > used-1)
925 return -1;
926
927 for (u32 i=start; i<used-len; ++i)
928 {
929 u32 j=0;
930
931 while(str[j] && array[i+j] == str[j])
932 ++j;
933
934 if (!str[j])
935 return i;
936 }
937 }
938
939 return -1;
940 }
941
942
944
947 string<T> subString(u32 begin, s32 length, bool make_lower = false ) const
948 {
949 // clamp length to maximal value
950 if ((length+begin) > size())
951 length = size()-begin;
952 // if start after string
953 // or no proper substring length
954 if ((length <= 0) || (begin>=size()))
955 return string<T>("");
956
957 string<T> o;
958 o.reserve(length+1);
959
960 if ( !make_lower )
961 {
962 for (s32 i=0; i<length; ++i)
963 o.array[i] = array[i+begin];
964 }
965 else
966 {
967 for (s32 i=0; i<length; ++i)
968 o.array[i] = locale_lower ( array[i+begin] );
969 }
970
971 o.array[length] = 0;
972 o.used = length + 1;
973
974 return o;
975 }
976
977
979
981 {
982 append(c);
983 return *this;
984 }
985
986
988
990 {
991 append(c);
992 return *this;
993 }
994
995
997
999 {
1000 append(other);
1001 return *this;
1002 }
1003
1004
1006
1008 {
1010 return *this;
1011 }
1012
1013
1015
1016 string<T,TAlloc>& operator += (const unsigned int i)
1017 {
1019 return *this;
1020 }
1021
1022
1024
1026 {
1028 return *this;
1029 }
1030
1031
1033
1034 string<T,TAlloc>& operator += (const unsigned long i)
1035 {
1037 return *this;
1038 }
1039
1040
1042
1044 {
1046 return *this;
1047 }
1048
1049
1051
1053 {
1055 return *this;
1056 }
1057
1058
1060
1063 {
1064 for (u32 i=0; i<used-1; ++i)
1065 if (array[i] == toReplace)
1066 array[i] = replaceWith;
1067 return *this;
1068 }
1069
1070
1072
1075 {
1076 if (toReplace.size() == 0)
1077 return *this;
1078
1079 const T* other = toReplace.data();
1080 const T* replace = replaceWith.data();
1081 const u32 other_size = toReplace.size();
1082 const u32 replace_size = replaceWith.size();
1083
1084 // Determine the delta. The algorithm will change depending on the delta.
1086
1087 // A character for character replace. The string will not shrink or grow.
1088 if (delta == 0)
1089 {
1090 s32 pos = 0;
1091 while ((pos = find(other, pos)) != -1)
1092 {
1093 for (u32 i = 0; i < replace_size; ++i)
1094 array[pos + i] = replace[i];
1095 ++pos;
1096 }
1097 return *this;
1098 }
1099
1100 // We are going to be removing some characters. The string will shrink.
1101 if (delta < 0)
1102 {
1103 u32 i = 0;
1104 for (u32 pos = 0; pos < used; ++i, ++pos)
1105 {
1106 // Is this potentially a match?
1107 if (array[pos] == *other)
1108 {
1109 // Check to see if we have a match.
1110 u32 j;
1111 for (j = 0; j < other_size; ++j)
1112 {
1113 if (array[pos + j] != other[j])
1114 break;
1115 }
1116
1117 // If we have a match, replace characters.
1118 if (j == other_size)
1119 {
1120 for (j = 0; j < replace_size; ++j)
1121 array[i + j] = replace[j];
1122 i += replace_size - 1;
1123 pos += other_size - 1;
1124 continue;
1125 }
1126 }
1127
1128 // No match found, just copy characters.
1129 array[i] = array[pos];
1130 }
1131 array[i-1] = 0;
1132 used = i;
1133
1134 return *this;
1135 }
1136
1137 // We are going to be adding characters, so the string size will increase.
1138 // Count the number of times toReplace exists in the string so we can allocate the new size.
1139 u32 find_count = 0;
1140 s32 pos = 0;
1141 while ((pos = find(other, pos)) != -1)
1142 {
1143 ++find_count;
1144 ++pos;
1145 }
1146
1147 // Re-allocate the string now, if needed.
1148 u32 len = delta * find_count;
1149 if (used + len > allocated)
1150 reallocate(used + len);
1151
1152 // Start replacing.
1153 pos = 0;
1154 while ((pos = find(other, pos)) != -1)
1155 {
1156 T* start = array + pos + other_size - 1;
1157 T* ptr = array + used - 1;
1158 T* end = array + delta + used -1;
1159
1160 // Shift characters to make room for the string.
1161 while (ptr != start)
1162 {
1163 *end = *ptr;
1164 --ptr;
1165 --end;
1166 }
1167
1168 // Add the new string now.
1169 for (u32 i = 0; i < replace_size; ++i)
1170 array[pos + i] = replace[i];
1171
1172 pos += replace_size;
1173 used += delta;
1174 }
1175
1176 return *this;
1177 }
1178
1179
1181
1183 {
1184 u32 pos = 0;
1185 u32 found = 0;
1186 for (u32 i=0; i<used-1; ++i)
1187 {
1188 if (array[i] == c)
1189 {
1190 ++found;
1191 continue;
1192 }
1193
1194 array[pos++] = array[i];
1195 }
1196 used -= found;
1197 array[used-1] = 0;
1198 return *this;
1199 }
1200
1201
1203
1205 {
1206 u32 size = toRemove.size();
1207 if ( size == 0 )
1208 return *this;
1209 u32 pos = 0;
1210 u32 found = 0;
1211 for (u32 i=0; i<used-1; ++i)
1212 {
1213 u32 j = 0;
1214 while (j < size)
1215 {
1216 if (array[i + j] != toRemove[j])
1217 break;
1218 ++j;
1219 }
1220 if (j == size)
1221 {
1222 found += size;
1223 i += size - 1;
1224 continue;
1225 }
1226
1227 array[pos++] = array[i];
1228 }
1229 used -= found;
1230 array[used-1] = 0;
1231 return *this;
1232 }
1233
1234
1236
1238 {
1239 if (characters.size() == 0)
1240 return *this;
1241
1242 u32 pos = 0;
1243 u32 found = 0;
1244 for (u32 i=0; i<used-1; ++i)
1245 {
1246 // Don't use characters.findFirst as it finds the \0,
1247 // causing used to become incorrect.
1248 bool docontinue = false;
1249 for (u32 j=0; j<characters.size(); ++j)
1250 {
1251 if (characters[j] == array[i])
1252 {
1253 ++found;
1254 docontinue = true;
1255 break;
1256 }
1257 }
1258 if (docontinue)
1259 continue;
1260
1261 array[pos++] = array[i];
1262 }
1263 used -= found;
1264 array[used-1] = 0;
1265
1266 return *this;
1267 }
1268
1269
1271
1274 {
1275 // find start and end of the substring without the specified characters
1276 const s32 begin = findFirstCharNotInList(whitespace.data(), whitespace.used);
1277 if (begin == -1)
1278 return (*this="");
1279
1280 const s32 end = findLastCharNotInList(whitespace.data(), whitespace.used);
1281
1282 return (*this = subString(begin, (end +1) - begin));
1283 }
1284
1286
1295 {
1296 s32 i=findLastCharNotInList("0", 1);
1297 if ( i > 0 && (u32)i < used-2 ) // non 0 must be found and not last char (also used is at least 2 when i > 0)
1298 {
1299 u32 eraseStart=i+1;
1300 u32 dot=0;
1301 if( core::isdigit(array[i]) )
1302 {
1303 while( --i>0 && core::isdigit(array[i]) );
1304 if ( array[i] == decimalPoint )
1305 dot = i;
1306 }
1307 else if ( array[i] == decimalPoint )
1308 {
1309 dot = i;
1310 eraseStart = i;
1311 }
1312 if ( dot > 0 && core::isdigit(array[dot-1]) )
1313 {
1314 array[eraseStart] = 0;
1315 used = eraseStart+1;
1316 }
1317 }
1318 return *this;
1319 }
1320
1322
1326 {
1327 NIRT_DEBUG_BREAK_IF(index>=used) // access violation
1328
1329 for (u32 i=index+1; i<used; ++i)
1330 array[i-1] = array[i];
1331
1332 --used;
1333 return *this;
1334 }
1335
1338 {
1339 // terminate on existing null
1340 for (u32 i=0; i<allocated; ++i)
1341 {
1342 if (array[i] == 0)
1343 {
1344 used = i + 1;
1345 return *this;
1346 }
1347 }
1348
1349 // terminate
1350 if ( allocated > 0 )
1351 {
1352 used = allocated;
1353 array[used-1] = 0;
1354 }
1355 else
1356 {
1357 used = 0;
1358 }
1359
1360 return *this;
1361 }
1362
1364 T lastChar() const
1365 {
1366 return used > 1 ? array[used-2] : 0;
1367 }
1368
1370
1388 template<class container>
1389 u32 split(container& ret, const T* const delimiter, u32 countDelimiters=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
1390 {
1391 if (!delimiter)
1392 return 0;
1393
1394 const u32 oldSize=ret.size();
1395
1396 u32 tokenStartIdx = 0;
1397 for (u32 i=0; i<used; ++i)
1398 {
1399 for (u32 j=0; j<countDelimiters; ++j)
1400 {
1401 if (array[i] == delimiter[j])
1402 {
1403 if (i - tokenStartIdx > 0)
1405 else if ( !ignoreEmptyTokens )
1406 ret.push_back(string<T,TAlloc>());
1407 if ( keepSeparators )
1408 {
1409 ret.push_back(string<T,TAlloc>(&array[i], 1));
1410 }
1411
1412 tokenStartIdx = i+1;
1413 break;
1414 }
1415 }
1416 }
1417 if ((used - 1) > tokenStartIdx)
1418 ret.push_back(string<T,TAlloc>(&array[tokenStartIdx], (used - 1) - tokenStartIdx));
1419 else if ( !ignoreEmptyTokens )
1420 ret.push_back(string<T,TAlloc>());
1421
1422 return ret.size()-oldSize;
1423 }
1424
1426
1427private:
1428
1430 void reallocate(u32 new_size)
1431 {
1432 T* old_array = array;
1433
1434 array = allocator.allocate(new_size); //new T[new_size];
1435 allocated = new_size;
1436
1437 const u32 amount = used < new_size ? used : new_size;
1438 for (u32 i=0; i<amount; ++i)
1439 array[i] = old_array[i];
1440
1441 if (allocated < used)
1442 used = allocated;
1443
1444 allocator.deallocate(old_array); // delete [] old_array;
1445 }
1446
1447 //--- member variables
1448
1449 T* array;
1450 u32 allocated;
1451 u32 used;
1452 TAlloc allocator;
1453};
1454
1455
1458
1461
1463
1468static inline size_t multibyteToWString(string<wchar_t>& destination, const core::string<c8>& source)
1469{
1470 return multibyteToWString(destination, source.data(), (u32)source.size());
1471}
1472
1474
1479static inline size_t multibyteToWString(string<wchar_t>& destination, const char* source)
1480{
1481 const u32 s = source ? (u32)strlen(source) : 0;
1482 return multibyteToWString(destination, source, s);
1483}
1484
1486static size_t multibyteToWString(string<wchar_t>& destination, const char* source, u32 sourceSize)
1487{
1488 if ( sourceSize )
1489 {
1490 destination.reserve(sourceSize+1);
1491#if defined(_MSC_VER)
1492#pragma warning(push)
1493#pragma warning(disable: 4996) // 'mbstowcs': This function or variable may be unsafe. Consider using mbstowcs_s instead.
1494#endif
1495 const size_t written = mbstowcs(destination.array, source, (size_t)sourceSize);
1496#if defined(_MSC_VER)
1497#pragma warning(pop)
1498#endif
1499 if ( written != (size_t)-1 )
1500 {
1501 destination.used = (u32)written+1;
1502 destination.array[destination.used-1] = 0;
1503 }
1504 else
1505 {
1506 // Likely character which got converted until the invalid character was encountered are in destination now.
1507 // And it seems even 0-terminated, but I found no documentation anywhere that this (the 0-termination) is guaranteed :-(
1508 destination.clear();
1509 }
1510 return written;
1511 }
1512 else
1513 {
1514 destination.clear();
1515 return 0;
1516 }
1517}
1518
1519
1520} // end namespace core
1521} // end namespace nirt
1522
1523#endif
1524
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
Very simple string class with some useful features.
Definition irrString.hpp:94
bool equals_substring_ignore_case(const string< T, TAlloc > &other, const s32 sourcePos=0) const
Compares the strings ignoring case.
Definition irrString.hpp:565
bool operator!=(const T *const str) const
Inequality operator.
Definition irrString.hpp:485
string(const B *const c, u32 length)
Constructor for copying a string from a pointer with a given length.
Definition irrString.hpp:294
string< T, TAlloc > & erase(u32 index)
Erases a character from the string.
Definition irrString.hpp:1325
bool equalsn(const string< T, TAlloc > &other, u32 n) const
compares the first n characters of the strings
Definition irrString.hpp:599
string< T, TAlloc > & remove(T c)
Removes characters from a string.
Definition irrString.hpp:1182
T & operator[](const u32 index)
Direct access operator.
Definition irrString.hpp:429
string(int number)
Constructs a string from an int.
Definition irrString.hpp:135
string< T > subString(u32 begin, s32 length, bool make_lower=false) const
Returns a substring.
Definition irrString.hpp:947
string< T, TAlloc > & trim(const string< T, TAlloc > &whitespace=" \t\n\r")
Trims the string.
Definition irrString.hpp:1273
bool operator==(const string< T, TAlloc > &other) const
Equality operator.
Definition irrString.hpp:460
bool operator==(const T *const str) const
Equality operator.
Definition irrString.hpp:445
bool equals_ignore_case(const string< T, TAlloc > &other) const
Compares the strings ignoring case.
Definition irrString.hpp:552
bool equalsn(const T *const str, u32 n) const
compares the first n characters of the strings
Definition irrString.hpp:616
s32 findFirstChar(const T *const c, u32 count=1) const
finds first occurrence of a character of a list in string
Definition irrString.hpp:790
s32 findFirst(T c) const
finds first occurrence of character in string
Definition irrString.hpp:774
bool lower_ignore_case(const string< T, TAlloc > &other) const
Compares the strings ignoring case.
Definition irrString.hpp:582
s32 findLastChar(const T *const c, u32 count=1) const
finds last occurrence of a character of a list in string
Definition irrString.hpp:895
string< T, TAlloc > & removeChars(const string< T, TAlloc > &characters)
Removes characters from a string.
Definition irrString.hpp:1237
string(unsigned int number)
Constructs a string from an unsigned int.
Definition irrString.hpp:183
string< T, TAlloc > operator+(const B *const c) const
Append operator for strings, ASCII and Unicode.
Definition irrString.hpp:419
string(const string< B, A > &other)
Constructor from other string types.
Definition irrString.hpp:117
string< T, TAlloc > & operator+=(T c)
Appends a character to this string.
Definition irrString.hpp:980
string< T, TAlloc > & make_lower()
Makes the string lower case.
Definition irrString.hpp:532
bool operator<(const string< T, TAlloc > &other) const
Is smaller comparator.
Definition irrString.hpp:471
string< T, TAlloc > & remove(const string< T, TAlloc > &toRemove)
Removes a string from the string.
Definition irrString.hpp:1204
s32 findNext(T c, u32 startPos) const
finds next occurrence of character in string
Definition irrString.hpp:863
string< T, TAlloc > & replace(T toReplace, T replaceWith)
Replaces all characters of a special type with another one.
Definition irrString.hpp:1062
s32 findFirstCharNotInList(const B *const c, u32 count=1) const
Finds first position of a character not in a given list.
Definition irrString.hpp:812
const T * data() const
Returns character string.
Definition irrString.hpp:525
string(const B *const c)
Constructor for Unicode and ASCII strings.
Definition irrString.hpp:316
string< T, TAlloc > & operator=(const string< B, A > &other)
Assignment operator for other string types.
Definition irrString.hpp:353
string< T, TAlloc > & append(T character)
Appends a character to this string.
Definition irrString.hpp:633
string< T, TAlloc > & operator=(const string< T, TAlloc > &other)
Assignment operator.
Definition irrString.hpp:331
string< T, TAlloc > & append(const string< T, TAlloc > &other, u32 length)
Appends a string of the length l to this string.
Definition irrString.hpp:705
string< T, TAlloc > operator+(const string< T, TAlloc > &other) const
Append operator for other strings.
Definition irrString.hpp:408
string(const double number)
Constructs a string from a float.
Definition irrString.hpp:125
string()
Default constructor.
Definition irrString.hpp:100
bool operator!=(const string< T, TAlloc > &other) const
Inequality operator.
Definition irrString.hpp:492
bool empty() const
Definition irrString.hpp:508
string< T, TAlloc > & append(const string< T, TAlloc > &other)
Appends a string to this string.
Definition irrString.hpp:682
T lastChar() const
gets the last char of a string or null
Definition irrString.hpp:1364
u32 split(container &ret, const T *const delimiter, u32 countDelimiters=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
Split string into parts (tokens).
Definition irrString.hpp:1389
string(unsigned long number)
Constructs a string from an unsigned long.
Definition irrString.hpp:262
friend size_t multibyteToWString(string< wchar_t > &destination, const char *source, u32 sourceSize)
Internally used by the other multibyteToWString functions.
Definition irrString.hpp:1486
~string()
Destructor.
Definition irrString.hpp:324
string< T, TAlloc > & eraseTrailingFloatZeros(char decimalPoint='.')
Erase 0's at the end when a string ends with a floating point number.
Definition irrString.hpp:1294
s32 findLast(T c, s32 start=-1) const
finds last occurrence of character in string
Definition irrString.hpp:878
string(long number)
Constructs a string from a long.
Definition irrString.hpp:214
void reserve(u32 count)
Reserves some memory.
Definition irrString.hpp:761
string< T, TAlloc > & append(const T *const other, u32 length=0xffffffff)
Appends a char string to this string.
Definition irrString.hpp:650
u32 size() const
Returns length of the string's content.
Definition irrString.hpp:501
s32 findLastCharNotInList(const B *const c, u32 count=1) const
Finds last position of a character not in a given list.
Definition irrString.hpp:839
s32 find(const B *const str, const u32 start=0) const
finds another string in this string
Definition irrString.hpp:915
string< T, TAlloc > & validate()
verify the existing string.
Definition irrString.hpp:1337
string< T, TAlloc > & operator=(const B *const c)
Assignment operator for strings, ASCII and Unicode.
Definition irrString.hpp:362
string(const string< T, TAlloc > &other)
Constructor.
Definition irrString.hpp:109
string< T, TAlloc > & replace(const string< T, TAlloc > &toReplace, const string< T, TAlloc > &replaceWith)
Replaces all instances of a string with another one.
Definition irrString.hpp:1074
string< T, TAlloc > & make_upper()
Makes the string upper case.
Definition irrString.hpp:541
string< T, TAlloc > & insert(u32 pos, const char *s, u32 n)
Insert a certain amount of characters into the string before the given index.
Definition irrString.hpp:736
NIRTCPP_API void utf8ToWchar(const char *in, wchar_t *out, const u64 len)
Convert this utf-8-encoded string to the platform's wchar.
const T clamp(const T &value, const T &low, const T &high)
clamps a value between low and high
Definition irrMath.hpp:164
NIRTCPP_API void wcharToUtf8(const wchar_t *in, char *out, const u64 len)
Convert this wchar string to utf-8.
s32 isdigit(s32 c)
some standard function ( to remove dependencies )
Definition coreutil.hpp:197
As of Nirtcpp 1.6, position2d is a synonym for vector2d.
Definition vector3d.hpp:11
signed int s32
32 bit signed variable.
Definition irrTypes.hpp:72
unsigned int u32
32 bit unsigned variable.
Definition irrTypes.hpp:64
char c8
8 bit character variable.
Definition irrTypes.hpp:37

Nirtcpp    @cppfx.xyz

Esvcpp    esv::print