Irrlicht 3D Engine
irrString.h
Go to the documentation of this file.
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 irrlicht.h and irrXML.h
4 
5 #ifndef __IRR_STRING_H_INCLUDED__
6 #define __IRR_STRING_H_INCLUDED__
7 
8 #include "irrTypes.h"
9 #include "irrAllocator.h"
10 #include "irrMath.h"
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 
15 namespace irr
16 {
17 namespace core
18 {
19 
21 
33 {
36 };
37 
38 static eLocaleID locale_current = IRR_LOCALE_ANSI;
39 static inline void locale_set ( eLocaleID id )
40 {
41  locale_current = id;
42 }
43 
45 static inline u32 locale_lower ( u32 x )
46 {
47  switch ( locale_current )
48  {
49  case IRR_LOCALE_GERMAN:
50  case IRR_LOCALE_ANSI:
51  break;
52  }
53  // ansi
54  return x >= 'A' && x <= 'Z' ? x + 0x20 : x;
55 }
56 
58 static inline u32 locale_upper ( u32 x )
59 {
60  switch ( locale_current )
61  {
62  case IRR_LOCALE_GERMAN:
63  case IRR_LOCALE_ANSI:
64  break;
65  }
66 
67  // ansi
68  return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x;
69 }
70 
71 
72 template <typename T, typename TAlloc = irrAllocator<T> >
73 class string
74 {
75 public:
76 
77  typedef T char_type;
78 
81  : array(0), allocated(1), used(1)
82  {
83  array = allocator.allocate(1); // new T[1];
84  array[0] = 0;
85  }
86 
87 
89  string(const string<T,TAlloc>& other)
90  : array(0), allocated(0), used(0)
91  {
92  *this = other;
93  }
94 
96  template <class B, class A>
97  string(const string<B, A>& other)
98  : array(0), allocated(0), used(0)
99  {
100  *this = other;
101  }
102 
103 
105  explicit string(const double number)
106  : array(0), allocated(0), used(0)
107  {
108  c8 tmpbuf[255];
109  snprintf(tmpbuf, 255, "%0.6f", number);
110  *this = tmpbuf;
111  }
112 
113 
115  explicit string(int number)
116  : array(0), allocated(0), used(0)
117  {
118  // store if negative and make positive
119 
120  bool negative = false;
121  if (number < 0)
122  {
123  number *= -1;
124  negative = true;
125  }
126 
127  // temporary buffer for 16 numbers
128 
129  c8 tmpbuf[16]={0};
130  u32 idx = 15;
131 
132  // special case '0'
133 
134  if (!number)
135  {
136  tmpbuf[14] = '0';
137  *this = &tmpbuf[14];
138  return;
139  }
140 
141  // add numbers
142 
143  while(number && idx)
144  {
145  --idx;
146  tmpbuf[idx] = (c8)('0' + (number % 10));
147  number /= 10;
148  }
149 
150  // add sign
151 
152  if (negative)
153  {
154  --idx;
155  tmpbuf[idx] = '-';
156  }
157 
158  *this = &tmpbuf[idx];
159  }
160 
161 
163  explicit string(unsigned int number)
164  : array(0), allocated(0), used(0)
165  {
166  // temporary buffer for 16 numbers
167 
168  c8 tmpbuf[16]={0};
169  u32 idx = 15;
170 
171  // special case '0'
172 
173  if (!number)
174  {
175  tmpbuf[14] = '0';
176  *this = &tmpbuf[14];
177  return;
178  }
179 
180  // add numbers
181 
182  while(number && idx)
183  {
184  --idx;
185  tmpbuf[idx] = (c8)('0' + (number % 10));
186  number /= 10;
187  }
188 
189  *this = &tmpbuf[idx];
190  }
191 
192 
194  explicit string(long number)
195  : array(0), allocated(0), used(0)
196  {
197  // store if negative and make positive
198 
199  bool negative = false;
200  if (number < 0)
201  {
202  number *= -1;
203  negative = true;
204  }
205 
206  // temporary buffer for 16 numbers
207 
208  c8 tmpbuf[16]={0};
209  u32 idx = 15;
210 
211  // special case '0'
212 
213  if (!number)
214  {
215  tmpbuf[14] = '0';
216  *this = &tmpbuf[14];
217  return;
218  }
219 
220  // add numbers
221 
222  while(number && idx)
223  {
224  --idx;
225  tmpbuf[idx] = (c8)('0' + (number % 10));
226  number /= 10;
227  }
228 
229  // add sign
230 
231  if (negative)
232  {
233  --idx;
234  tmpbuf[idx] = '-';
235  }
236 
237  *this = &tmpbuf[idx];
238  }
239 
240 
242  explicit string(unsigned long number)
243  : array(0), allocated(0), used(0)
244  {
245  // temporary buffer for 16 numbers
246 
247  c8 tmpbuf[16]={0};
248  u32 idx = 15;
249 
250  // special case '0'
251 
252  if (!number)
253  {
254  tmpbuf[14] = '0';
255  *this = &tmpbuf[14];
256  return;
257  }
258 
259  // add numbers
260 
261  while(number && idx)
262  {
263  --idx;
264  tmpbuf[idx] = (c8)('0' + (number % 10));
265  number /= 10;
266  }
267 
268  *this = &tmpbuf[idx];
269  }
270 
271 
273  template <class B>
274  string(const B* const c, u32 length)
275  : array(0), allocated(0), used(0)
276  {
277  if (!c)
278  {
279  // correctly init the string to an empty one
280  *this="";
281  return;
282  }
283 
284  allocated = used = length+1;
285  array = allocator.allocate(used); // new T[used];
286 
287  for (u32 l = 0; l<length; ++l)
288  array[l] = (T)c[l];
289 
290  array[length] = 0;
291  }
292 
293 
295  template <class B>
296  string(const B* const c)
297  : array(0), allocated(0), used(0)
298  {
299  *this = c;
300  }
301 
302 
305  {
306  allocator.deallocate(array); // delete [] array;
307  }
308 
309 
312  {
313  if (this == &other)
314  return *this;
315 
316  used = other.size()+1;
317  if (used>allocated)
318  {
319  allocator.deallocate(array); // delete [] array;
320  allocated = used;
321  array = allocator.allocate(used); //new T[used];
322  }
323 
324  const T* p = other.c_str();
325  for (u32 i=0; i<used; ++i, ++p)
326  array[i] = *p;
327 
328  return *this;
329  }
330 
332  template <class B, class A>
334  {
335  *this = other.c_str();
336  return *this;
337  }
338 
339 
341  template <class B>
342  string<T,TAlloc>& operator=(const B* const c)
343  {
344  if (!c)
345  {
346  if (!array)
347  {
348  array = allocator.allocate(1); //new T[1];
349  allocated = 1;
350  }
351  used = 1;
352  array[0] = 0x0;
353  return *this;
354  }
355 
356  if ((void*)c == (void*)array)
357  return *this;
358 
359  u32 len = 0;
360  const B* p = c;
361  do
362  {
363  ++len;
364  } while(*p++);
365 
366  // we'll keep the old string for a while, because the new
367  // string could be a part of the current string.
368  T* oldArray = array;
369 
370  used = len;
371  if (used>allocated)
372  {
373  allocated = used;
374  array = allocator.allocate(used); //new T[used];
375  }
376 
377  for (u32 l = 0; l<len; ++l)
378  array[l] = (T)c[l];
379 
380  if (oldArray != array)
381  allocator.deallocate(oldArray); // delete [] oldArray;
382 
383  return *this;
384  }
385 
386 
389  {
390  string<T,TAlloc> str(*this);
391  str.append(other);
392 
393  return str;
394  }
395 
396 
398  template <class B>
399  string<T,TAlloc> operator+(const B* const c) const
400  {
401  string<T,TAlloc> str(*this);
402  str.append(c);
403 
404  return str;
405  }
406 
407 
409  T& operator [](const u32 index)
410  {
411  _IRR_DEBUG_BREAK_IF(index>=used) // bad index
412  return array[index];
413  }
414 
415 
417  const T& operator [](const u32 index) const
418  {
419  _IRR_DEBUG_BREAK_IF(index>=used) // bad index
420  return array[index];
421  }
422 
423 
425  bool operator==(const T* const str) const
426  {
427  if (!str)
428  return false;
429 
430  u32 i;
431  for (i=0; array[i] && str[i]; ++i)
432  if (array[i] != str[i])
433  return false;
434 
435  return (!array[i] && !str[i]);
436  }
437 
438 
440  bool operator==(const string<T,TAlloc>& other) const
441  {
442  for (u32 i=0; array[i] && other.array[i]; ++i)
443  if (array[i] != other.array[i])
444  return false;
445 
446  return used == other.used;
447  }
448 
449 
451  bool operator<(const string<T,TAlloc>& other) const
452  {
453  for (u32 i=0; array[i] && other.array[i]; ++i)
454  {
455  const s32 diff = array[i] - other.array[i];
456  if (diff)
457  return (diff < 0);
458  }
459 
460  return (used < other.used);
461  }
462 
463 
465  bool operator!=(const T* const str) const
466  {
467  return !(*this == str);
468  }
469 
470 
472  bool operator!=(const string<T,TAlloc>& other) const
473  {
474  return !(*this == other);
475  }
476 
477 
479 
481  u32 size() const
482  {
483  return used-1;
484  }
485 
488  bool empty() const
489  {
490  return (size() == 0);
491  }
492 
494 
495  const T* c_str() const
496  {
497  return array;
498  }
499 
500 
503  {
504  for (u32 i=0; array[i]; ++i)
505  array[i] = locale_lower ( array[i] );
506  return *this;
507  }
508 
509 
512  {
513  for (u32 i=0; array[i]; ++i)
514  array[i] = locale_upper ( array[i] );
515  return *this;
516  }
517 
518 
520 
522  bool equals_ignore_case(const string<T,TAlloc>& other) const
523  {
524  for(u32 i=0; array[i] && other[i]; ++i)
525  if (locale_lower( array[i]) != locale_lower(other[i]))
526  return false;
527 
528  return used == other.used;
529  }
530 
532 
535  bool equals_substring_ignore_case(const string<T,TAlloc>&other, const s32 sourcePos = 0 ) const
536  {
537  if ( (u32) sourcePos >= used )
538  return false;
539 
540  u32 i;
541  for( i=0; array[sourcePos + i] && other[i]; ++i)
542  if (locale_lower( array[sourcePos + i]) != locale_lower(other[i]))
543  return false;
544 
545  return array[sourcePos + i] == 0 && other[i] == 0;
546  }
547 
548 
550 
552  bool lower_ignore_case(const string<T,TAlloc>& other) const
553  {
554  for(u32 i=0; array[i] && other.array[i]; ++i)
555  {
556  s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] );
557  if ( diff )
558  return diff < 0;
559  }
560 
561  return used < other.used;
562  }
563 
564 
566 
569  bool equalsn(const string<T,TAlloc>& other, u32 n) const
570  {
571  u32 i;
572  for(i=0; array[i] && other[i] && i < n; ++i)
573  if (array[i] != other[i])
574  return false;
575 
576  // if one (or both) of the strings was smaller then they
577  // are only equal if they have the same length
578  return (i == n) || (used == other.used);
579  }
580 
581 
583 
586  bool equalsn(const T* const str, u32 n) const
587  {
588  if (!str)
589  return false;
590  u32 i;
591  for(i=0; array[i] && str[i] && i < n; ++i)
592  if (array[i] != str[i])
593  return false;
594 
595  // if one (or both) of the strings was smaller then they
596  // are only equal if they have the same length
597  return (i == n) || (array[i] == 0 && str[i] == 0);
598  }
599 
600 
602 
603  string<T,TAlloc>& append(T character)
604  {
605  if (used + 1 > allocated)
606  reallocate(used + 1);
607 
608  ++used;
609 
610  array[used-2] = character;
611  array[used-1] = 0;
612 
613  return *this;
614  }
615 
616 
618 
620  string<T,TAlloc>& append(const T* const other, u32 length=0xffffffff)
621  {
622  if (!other)
623  return *this;
624 
625  u32 len = 0;
626  const T* p = other;
627  while(*p)
628  {
629  ++len;
630  ++p;
631  }
632  if (len > length)
633  len = length;
634 
635  if (used + len > allocated)
636  reallocate(used + len);
637 
638  --used;
639  ++len;
640 
641  for (u32 l=0; l<len; ++l)
642  array[l+used] = *(other+l);
643 
644  used += len;
645 
646  return *this;
647  }
648 
649 
651 
653  {
654  if (other.size() == 0)
655  return *this;
656 
657  --used;
658  u32 len = other.size()+1;
659 
660  if (used + len > allocated)
661  reallocate(used + len);
662 
663  for (u32 l=0; l<len; ++l)
664  array[used+l] = other[l];
665 
666  used += len;
667 
668  return *this;
669  }
670 
671 
673 
676  {
677  if (other.size() == 0)
678  return *this;
679 
680  if (other.size() < length)
681  {
682  append(other);
683  return *this;
684  }
685 
686  if (used + length > allocated)
687  reallocate(used + length);
688 
689  --used;
690 
691  for (u32 l=0; l<length; ++l)
692  array[l+used] = other[l];
693  used += length;
694 
695  // ensure proper termination
696  array[used]=0;
697  ++used;
698 
699  return *this;
700  }
701 
702 
704 
705  void reserve(u32 count)
706  {
707  if (count < allocated)
708  return;
709 
710  reallocate(count);
711  }
712 
713 
715 
718  s32 findFirst(T c) const
719  {
720  for (u32 i=0; i<used-1; ++i)
721  if (array[i] == c)
722  return i;
723 
724  return -1;
725  }
726 
728 
734  s32 findFirstChar(const T* const c, u32 count=1) const
735  {
736  if (!c || !count)
737  return -1;
738 
739  for (u32 i=0; i<used-1; ++i)
740  for (u32 j=0; j<count; ++j)
741  if (array[i] == c[j])
742  return i;
743 
744  return -1;
745  }
746 
747 
749 
755  template <class B>
756  s32 findFirstCharNotInList(const B* const c, u32 count=1) const
757  {
758  if (!c || !count)
759  return -1;
760 
761  for (u32 i=0; i<used-1; ++i)
762  {
763  u32 j;
764  for (j=0; j<count; ++j)
765  if (array[i] == c[j])
766  break;
767 
768  if (j==count)
769  return i;
770  }
771 
772  return -1;
773  }
774 
776 
782  template <class B>
783  s32 findLastCharNotInList(const B* const c, u32 count=1) const
784  {
785  if (!c || !count)
786  return -1;
787 
788  for (s32 i=(s32)(used-2); i>=0; --i)
789  {
790  u32 j;
791  for (j=0; j<count; ++j)
792  if (array[i] == c[j])
793  break;
794 
795  if (j==count)
796  return i;
797  }
798 
799  return -1;
800  }
801 
803 
807  s32 findNext(T c, u32 startPos) const
808  {
809  for (u32 i=startPos; i<used-1; ++i)
810  if (array[i] == c)
811  return i;
812 
813  return -1;
814  }
815 
816 
818 
822  s32 findLast(T c, s32 start = -1) const
823  {
824  start = core::clamp ( start < 0 ? (s32)(used) - 2 : start, 0, (s32)(used) - 2 );
825  for (s32 i=start; i>=0; --i)
826  if (array[i] == c)
827  return i;
828 
829  return -1;
830  }
831 
833 
839  s32 findLastChar(const T* 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  for (u32 j=0; j<count; ++j)
846  if (array[i] == c[j])
847  return i;
848 
849  return -1;
850  }
851 
852 
854 
858  template <class B>
859  s32 find(const B* const str, const u32 start = 0) const
860  {
861  if (str && *str)
862  {
863  u32 len = 0;
864 
865  while (str[len])
866  ++len;
867 
868  if (len > used-1)
869  return -1;
870 
871  for (u32 i=start; i<used-len; ++i)
872  {
873  u32 j=0;
874 
875  while(str[j] && array[i+j] == str[j])
876  ++j;
877 
878  if (!str[j])
879  return i;
880  }
881  }
882 
883  return -1;
884  }
885 
886 
888 
891  string<T> subString(u32 begin, s32 length, bool make_lower = false ) const
892  {
893  // if start after string
894  // or no proper substring length
895  if ((length <= 0) || (begin>=size()))
896  return string<T>("");
897  // clamp length to maximal value
898  if ((length+begin) > size())
899  length = size()-begin;
900 
901  string<T> o;
902  o.reserve(length+1);
903 
904  s32 i;
905  if ( !make_lower )
906  {
907  for (i=0; i<length; ++i)
908  o.array[i] = array[i+begin];
909  }
910  else
911  {
912  for (i=0; i<length; ++i)
913  o.array[i] = locale_lower ( array[i+begin] );
914  }
915 
916  o.array[length] = 0;
917  o.used = length + 1;
918 
919  return o;
920  }
921 
922 
924 
926  {
927  append(c);
928  return *this;
929  }
930 
931 
933 
934  string<T,TAlloc>& operator += (const T* const c)
935  {
936  append(c);
937  return *this;
938  }
939 
940 
942 
944  {
945  append(other);
946  return *this;
947  }
948 
949 
951 
953  {
955  return *this;
956  }
957 
958 
960 
961  string<T,TAlloc>& operator += (const unsigned int i)
962  {
964  return *this;
965  }
966 
967 
969 
971  {
973  return *this;
974  }
975 
976 
978 
979  string<T,TAlloc>& operator += (const unsigned long i)
980  {
982  return *this;
983  }
984 
985 
987 
989  {
991  return *this;
992  }
993 
994 
996 
998  {
1000  return *this;
1001  }
1002 
1003 
1005 
1007  string<T,TAlloc>& replace(T toReplace, T replaceWith)
1008  {
1009  for (u32 i=0; i<used-1; ++i)
1010  if (array[i] == toReplace)
1011  array[i] = replaceWith;
1012  return *this;
1013  }
1014 
1015 
1017 
1019  string<T,TAlloc>& replace(const string<T,TAlloc>& toReplace, const string<T,TAlloc>& replaceWith)
1020  {
1021  if (toReplace.size() == 0)
1022  return *this;
1023 
1024  const T* other = toReplace.c_str();
1025  const T* replace = replaceWith.c_str();
1026  const u32 other_size = toReplace.size();
1027  const u32 replace_size = replaceWith.size();
1028 
1029  // Determine the delta. The algorithm will change depending on the delta.
1030  s32 delta = replace_size - other_size;
1031 
1032  // A character for character replace. The string will not shrink or grow.
1033  if (delta == 0)
1034  {
1035  s32 pos = 0;
1036  while ((pos = find(other, pos)) != -1)
1037  {
1038  for (u32 i = 0; i < replace_size; ++i)
1039  array[pos + i] = replace[i];
1040  ++pos;
1041  }
1042  return *this;
1043  }
1044 
1045  // We are going to be removing some characters. The string will shrink.
1046  if (delta < 0)
1047  {
1048  u32 i = 0;
1049  for (u32 pos = 0; pos < used; ++i, ++pos)
1050  {
1051  // Is this potentially a match?
1052  if (array[pos] == *other)
1053  {
1054  // Check to see if we have a match.
1055  u32 j;
1056  for (j = 0; j < other_size; ++j)
1057  {
1058  if (array[pos + j] != other[j])
1059  break;
1060  }
1061 
1062  // If we have a match, replace characters.
1063  if (j == other_size)
1064  {
1065  for (j = 0; j < replace_size; ++j)
1066  array[i + j] = replace[j];
1067  i += replace_size - 1;
1068  pos += other_size - 1;
1069  continue;
1070  }
1071  }
1072 
1073  // No match found, just copy characters.
1074  array[i] = array[pos];
1075  }
1076  array[i-1] = 0;
1077  used = i;
1078 
1079  return *this;
1080  }
1081 
1082  // We are going to be adding characters, so the string size will increase.
1083  // Count the number of times toReplace exists in the string so we can allocate the new size.
1084  u32 find_count = 0;
1085  s32 pos = 0;
1086  while ((pos = find(other, pos)) != -1)
1087  {
1088  ++find_count;
1089  ++pos;
1090  }
1091 
1092  // Re-allocate the string now, if needed.
1093  u32 len = delta * find_count;
1094  if (used + len > allocated)
1095  reallocate(used + len);
1096 
1097  // Start replacing.
1098  pos = 0;
1099  while ((pos = find(other, pos)) != -1)
1100  {
1101  T* start = array + pos + other_size - 1;
1102  T* ptr = array + used - 1;
1103  T* end = array + delta + used -1;
1104 
1105  // Shift characters to make room for the string.
1106  while (ptr != start)
1107  {
1108  *end = *ptr;
1109  --ptr;
1110  --end;
1111  }
1112 
1113  // Add the new string now.
1114  for (u32 i = 0; i < replace_size; ++i)
1115  array[pos + i] = replace[i];
1116 
1117  pos += replace_size;
1118  used += delta;
1119  }
1120 
1121  return *this;
1122  }
1123 
1124 
1126 
1127  string<T,TAlloc>& remove(T c)
1128  {
1129  u32 pos = 0;
1130  u32 found = 0;
1131  for (u32 i=0; i<used-1; ++i)
1132  {
1133  if (array[i] == c)
1134  {
1135  ++found;
1136  continue;
1137  }
1138 
1139  array[pos++] = array[i];
1140  }
1141  used -= found;
1142  array[used-1] = 0;
1143  return *this;
1144  }
1145 
1146 
1148 
1149  string<T,TAlloc>& remove(const string<T,TAlloc>& toRemove)
1150  {
1151  u32 size = toRemove.size();
1152  if ( size == 0 )
1153  return *this;
1154  u32 pos = 0;
1155  u32 found = 0;
1156  for (u32 i=0; i<used-1; ++i)
1157  {
1158  u32 j = 0;
1159  while (j < size)
1160  {
1161  if (array[i + j] != toRemove[j])
1162  break;
1163  ++j;
1164  }
1165  if (j == size)
1166  {
1167  found += size;
1168  i += size - 1;
1169  continue;
1170  }
1171 
1172  array[pos++] = array[i];
1173  }
1174  used -= found;
1175  array[used-1] = 0;
1176  return *this;
1177  }
1178 
1179 
1181 
1183  {
1184  if (characters.size() == 0)
1185  return *this;
1186 
1187  u32 pos = 0;
1188  u32 found = 0;
1189  for (u32 i=0; i<used-1; ++i)
1190  {
1191  // Don't use characters.findFirst as it finds the \0,
1192  // causing used to become incorrect.
1193  bool docontinue = false;
1194  for (u32 j=0; j<characters.size(); ++j)
1195  {
1196  if (characters[j] == array[i])
1197  {
1198  ++found;
1199  docontinue = true;
1200  break;
1201  }
1202  }
1203  if (docontinue)
1204  continue;
1205 
1206  array[pos++] = array[i];
1207  }
1208  used -= found;
1209  array[used-1] = 0;
1210 
1211  return *this;
1212  }
1213 
1214 
1216 
1218  string<T,TAlloc>& trim(const string<T,TAlloc> & whitespace = " \t\n\r")
1219  {
1220  // find start and end of the substring without the specified characters
1221  const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used);
1222  if (begin == -1)
1223  return (*this="");
1224 
1225  const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used);
1226 
1227  return (*this = subString(begin, (end +1) - begin));
1228  }
1229 
1230 
1232 
1236  {
1237  _IRR_DEBUG_BREAK_IF(index>=used) // access violation
1238 
1239  for (u32 i=index+1; i<used; ++i)
1240  array[i-1] = array[i];
1241 
1242  --used;
1243  return *this;
1244  }
1245 
1248  {
1249  // terminate on existing null
1250  for (u32 i=0; i<allocated; ++i)
1251  {
1252  if (array[i] == 0)
1253  {
1254  used = i + 1;
1255  return *this;
1256  }
1257  }
1258 
1259  // terminate
1260  if ( allocated > 0 )
1261  {
1262  used = allocated;
1263  array[used-1] = 0;
1264  }
1265  else
1266  {
1267  used = 0;
1268  }
1269 
1270  return *this;
1271  }
1272 
1274  T lastChar() const
1275  {
1276  return used > 1 ? array[used-2] : 0;
1277  }
1278 
1280 
1297  template<class container>
1298  u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
1299  {
1300  if (!c)
1301  return 0;
1302 
1303  const u32 oldSize=ret.size();
1304  u32 lastpos = 0;
1305  bool lastWasSeparator = false;
1306  for (u32 i=0; i<used; ++i)
1307  {
1308  bool foundSeparator = false;
1309  for (u32 j=0; j<count; ++j)
1310  {
1311  if (array[i] == c[j])
1312  {
1313  if ((!ignoreEmptyTokens || i - lastpos != 0) &&
1314  !lastWasSeparator)
1315  ret.push_back(string<T,TAlloc>(&array[lastpos], i - lastpos));
1316  foundSeparator = true;
1317  lastpos = (keepSeparators ? i : i + 1);
1318  break;
1319  }
1320  }
1321  lastWasSeparator = foundSeparator;
1322  }
1323  if ((used - 1) > lastpos)
1324  ret.push_back(string<T,TAlloc>(&array[lastpos], (used - 1) - lastpos));
1325  return ret.size()-oldSize;
1326  }
1327 
1328 private:
1329 
1331  void reallocate(u32 new_size)
1332  {
1333  T* old_array = array;
1334 
1335  array = allocator.allocate(new_size); //new T[new_size];
1336  allocated = new_size;
1337 
1338  u32 amount = used < new_size ? used : new_size;
1339  for (u32 i=0; i<amount; ++i)
1340  array[i] = old_array[i];
1341 
1342  if (allocated < used)
1343  used = allocated;
1344 
1345  allocator.deallocate(old_array); // delete [] old_array;
1346  }
1347 
1348  //--- member variables
1349 
1350  T* array;
1351  u32 allocated;
1352  u32 used;
1353  TAlloc allocator;
1354 };
1355 
1356 
1359 
1362 
1363 
1364 } // end namespace core
1365 } // end namespace irr
1366 
1367 #endif
1368 
string(long number)
Constructs a string from a long.
Definition: irrString.h:194
bool empty() const
Definition: irrString.h:488
s32 findFirstCharNotInList(const B *const c, u32 count=1) const
Finds first position of a character not in a given list.
Definition: irrString.h:756
T & operator[](const u32 index)
Direct access operator.
Definition: irrString.h:409
u32 size() const
Returns length of the string&#39;s content.
Definition: irrString.h:481
array()
Default constructor for empty array.
Definition: irrArray.h:28
string< T, TAlloc > & append(T character)
Appends a character to this string.
Definition: irrString.h:603
bool equals_substring_ignore_case(const string< T, TAlloc > &other, const s32 sourcePos=0) const
Compares the strings ignoring case.
Definition: irrString.h:535
s32 findLast(T c, s32 start=-1) const
finds last occurrence of character in string
Definition: irrString.h:822
string(const B *const c)
Constructor for unicode and ascii strings.
Definition: irrString.h:296
string< T, TAlloc > operator+(const B *const c) const
Append operator for strings, ascii and unicode.
Definition: irrString.h:399
char c8
8 bit character variable.
Definition: irrTypes.h:31
string(const double number)
Constructs a string from a float.
Definition: irrString.h:105
s32 find(const B *const str, const u32 start=0) const
finds another string in this string
Definition: irrString.h:859
~string()
Destructor.
Definition: irrString.h:304
string< T, TAlloc > & operator=(const string< B, A > &other)
Assignment operator for other string types.
Definition: irrString.h:333
Everything in the Irrlicht Engine can be found in this namespace.
Definition: aabbox3d.h:12
void push_back(const T &element)
Adds an element at back of array.
Definition: irrArray.h:112
string< T, TAlloc > & operator=(const string< T, TAlloc > &other)
Assignment operator.
Definition: irrString.h:311
bool operator==(const string< T, TAlloc > &other) const
Equality operator.
Definition: irrString.h:440
bool operator!=(const T *const str) const
Inequality operator.
Definition: irrString.h:465
void reserve(u32 count)
Reserves some memory.
Definition: irrString.h:705
s32 findLastChar(const T *const c, u32 count=1) const
finds last occurrence of a character of a list in string
Definition: irrString.h:839
s32 findFirst(T c) const
finds first occurrence of character in string
Definition: irrString.h:718
string< T, TAlloc > & make_upper()
Makes the string upper case.
Definition: irrString.h:511
string(unsigned int number)
Constructs a string from an unsigned int.
Definition: irrString.h:163
s32 findLastCharNotInList(const B *const c, u32 count=1) const
Finds last position of a character not in a given list.
Definition: irrString.h:783
signed int s32
32 bit signed variable.
Definition: irrTypes.h:66
string< T, TAlloc > & append(const string< T, TAlloc > &other, u32 length)
Appends a string of the length l to this string.
Definition: irrString.h:675
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.h:1019
const T * c_str() const
Returns character string.
Definition: irrString.h:495
u32 split(container &ret, const T *const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
split string into parts.
Definition: irrString.h:1298
unsigned int u32
32 bit unsigned variable.
Definition: irrTypes.h:58
string(unsigned long number)
Constructs a string from an unsigned long.
Definition: irrString.h:242
bool operator==(const T *const str) const
Equality operator.
Definition: irrString.h:425
string< T, TAlloc > & make_lower()
Makes the string lower case.
Definition: irrString.h:502
T lastChar() const
gets the last char of a string or null
Definition: irrString.h:1274
string< T, TAlloc > & operator=(const B *const c)
Assignment operator for strings, ascii and unicode.
Definition: irrString.h:342
string< T, TAlloc > & removeChars(const string< T, TAlloc > &characters)
Removes characters from a string.
Definition: irrString.h:1182
#define _IRR_DEBUG_BREAK_IF(_CONDITION_)
define a break macro for debugging.
Definition: irrTypes.h:178
string< c8 > stringc
Typedef for character strings.
Definition: irrString.h:1358
bool equalsn(const T *const str, u32 n) const
compares the first n characters of the strings
Definition: irrString.h:586
string< T, TAlloc > & replace(T toReplace, T replaceWith)
Replaces all characters of a special type with another one.
Definition: irrString.h:1007
string()
Default constructor.
Definition: irrString.h:80
string(const string< B, A > &other)
Constructor from other string types.
Definition: irrString.h:97
string< T, TAlloc > & append(const T *const other, u32 length=0xffffffff)
Appends a char string to this string.
Definition: irrString.h:620
string< T > subString(u32 begin, s32 length, bool make_lower=false) const
Returns a substring.
Definition: irrString.h:891
Self reallocating template array (like stl vector) with additional features.
Definition: irrArray.h:22
s32 findFirstChar(const T *const c, u32 count=1) const
finds first occurrence of a character of a list in string
Definition: irrString.h:734
string(const string< T, TAlloc > &other)
Constructor.
Definition: irrString.h:89
bool equals_ignore_case(const string< T, TAlloc > &other) const
Compares the strings ignoring case.
Definition: irrString.h:522
bool lower_ignore_case(const string< T, TAlloc > &other) const
Compares the strings ignoring case.
Definition: irrString.h:552
bool equalsn(const string< T, TAlloc > &other, u32 n) const
compares the first n characters of the strings
Definition: irrString.h:569
string< T, TAlloc > & operator+=(T c)
Appends a character to this string.
Definition: irrString.h:925
s32 findNext(T c, u32 startPos) const
finds next occurrence of character in string
Definition: irrString.h:807
string< T, TAlloc > & append(const string< T, TAlloc > &other)
Appends a string to this string.
Definition: irrString.h:652
string< T, TAlloc > & validate()
verify the existing string.
Definition: irrString.h:1247
bool operator!=(const string< T, TAlloc > &other) const
Inequality operator.
Definition: irrString.h:472
string(const B *const c, u32 length)
Constructor for copying a string from a pointer with a given length.
Definition: irrString.h:274
string< T, TAlloc > operator+(const string< T, TAlloc > &other) const
Append operator for other strings.
Definition: irrString.h:388
eLocaleID
Very simple string class with some useful features.
Definition: irrString.h:32
string< T, TAlloc > & trim(const string< T, TAlloc > &whitespace=" \\)
Trims the string.
Definition: irrString.h:1218
const T clamp(const T &value, const T &low, const T &high)
clamps a value between low and high
Definition: irrMath.h:166
string< T, TAlloc > & erase(u32 index)
Erases a character from the string.
Definition: irrString.h:1235
string(int number)
Constructs a string from an int.
Definition: irrString.h:115
string< wchar_t > stringw
Typedef for wide character strings.
Definition: irrString.h:1361