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

Jimcpp    @cppfx.xyz

K