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

Jimcpp    @cppfx.xyz