arsa  2.7
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 
35 // forward declarations
36 template <typename T, typename TAlloc = irrAllocator<T> >
37 class string;
38 static size_t multibyteToWString(string<wchar_t>& destination, const char* source, u32 sourceSize);
39 inline s32 isdigit(s32 c);
40 
42 {
45 };
46 
47 static eLocaleID locale_current = IRR_LOCALE_ANSI;
48 static inline void locale_set ( eLocaleID id )
49 {
50  locale_current = id;
51 }
52 
54 static inline u32 locale_lower ( u32 x )
55 {
56  switch ( locale_current )
57  {
58  case IRR_LOCALE_GERMAN:
59  case IRR_LOCALE_ANSI:
60  break;
61  }
62  // ansi
63  return x >= 'A' && x <= 'Z' ? x + 0x20 : x;
64 }
65 
67 static inline u32 locale_upper ( u32 x )
68 {
69  switch ( locale_current )
70  {
71  case IRR_LOCALE_GERMAN:
72  case IRR_LOCALE_ANSI:
73  break;
74  }
75 
76  // ansi
77  return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x;
78 }
79 
81 
84 IRRLICHT_API void utf8ToWchar(const char *in, wchar_t *out, const u64 len);
85 
87 
90 IRRLICHT_API void wcharToUtf8(const wchar_t *in, char *out, const u64 len);
91 
92 
93 template <typename T, typename TAlloc>
94 class string
95 {
96 public:
97 
98  typedef T char_type;
99 
102  : array(0), allocated(1), used(1)
103  {
104  array = allocator.allocate(1); // new T[1];
105  array[0] = 0;
106  }
107 
108 
110  string(const string<T,TAlloc>& other)
111  : array(0), allocated(0), used(0)
112  {
113  *this = other;
114  }
115 
117  template <class B, class A>
118  string(const string<B, A>& other)
119  : array(0), allocated(0), used(0)
120  {
121  *this = other;
122  }
123 
124 
126  explicit string(const double number)
127  : array(0), allocated(0), used(0)
128  {
129  c8 tmpbuf[255];
130  snprintf_irr(tmpbuf, 255, "%0.6f", number);
131  *this = tmpbuf;
132  }
133 
134 
136  explicit 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 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 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 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  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  string(const B* const c)
318  : array(0), allocated(0), used(0)
319  {
320  *this = c;
321  }
322 
323 
326  {
327  allocator.deallocate(array); // delete [] array;
328  }
329 
330 
333  {
334  if (this == &other)
335  return *this;
336 
337  used = other.size()+1;
338  if (used>allocated)
339  {
340  allocator.deallocate(array); // delete [] array;
341  allocated = used;
342  array = allocator.allocate(used); //new T[used];
343  }
344 
345  const T* p = other.c_str();
346  for (u32 i=0; i<used; ++i, ++p)
347  array[i] = *p;
348 
349  return *this;
350  }
351 
353  template <class B, class A>
355  {
356  *this = other.c_str();
357  return *this;
358  }
359 
360 
362  template <class B>
363  string<T,TAlloc>& operator=(const B* const c)
364  {
365  if (!c)
366  {
367  if (!array)
368  {
369  array = allocator.allocate(1); //new T[1];
370  allocated = 1;
371  }
372  used = 1;
373  array[0] = 0x0;
374  return *this;
375  }
376 
377  if ((void*)c == (void*)array)
378  return *this;
379 
380  u32 len = 0;
381  const B* p = c;
382  do
383  {
384  ++len;
385  } while(*p++);
386 
387  // we'll keep the old string for a while, because the new
388  // string could be a part of the current string.
389  T* oldArray = array;
390 
391  used = len;
392  if (used>allocated)
393  {
394  allocated = used;
395  array = allocator.allocate(used); //new T[used];
396  }
397 
398  for (u32 l = 0; l<len; ++l)
399  array[l] = (T)c[l];
400 
401  if (oldArray != array)
402  allocator.deallocate(oldArray); // delete [] oldArray;
403 
404  return *this;
405  }
406 
407 
410  {
411  string<T,TAlloc> str(*this);
412  str.append(other);
413 
414  return str;
415  }
416 
417 
419  template <class B>
420  string<T,TAlloc> operator+(const B* const c) const
421  {
422  string<T,TAlloc> str(*this);
423  str.append(c);
424 
425  return str;
426  }
427 
428 
431  {
432  _IRR_DEBUG_BREAK_IF(index>=used) // bad index
433  return array[index];
434  }
435 
436 
438  const T& operator [](const u32 index) const
439  {
440  _IRR_DEBUG_BREAK_IF(index>=used) // bad index
441  return array[index];
442  }
443 
444 
446  bool operator==(const T* const str) const
447  {
448  if (!str)
449  return false;
450 
451  u32 i;
452  for (i=0; array[i] && str[i]; ++i)
453  if (array[i] != str[i])
454  return false;
455 
456  return (!array[i] && !str[i]);
457  }
458 
459 
461  bool operator==(const string<T,TAlloc>& other) const
462  {
463  for (u32 i=0; array[i] && other.array[i]; ++i)
464  if (array[i] != other.array[i])
465  return false;
466 
467  return used == other.used;
468  }
469 
470 
472  bool operator<(const string<T,TAlloc>& other) const
473  {
474  for (u32 i=0; array[i] && other.array[i]; ++i)
475  {
476  const s32 diff = array[i] - other.array[i];
477  if (diff)
478  return (diff < 0);
479  }
480 
481  return (used < other.used);
482  }
483 
484 
486  bool operator!=(const T* const str) const
487  {
488  return !(*this == str);
489  }
490 
491 
493  bool operator!=(const string<T,TAlloc>& other) const
494  {
495  return !(*this == other);
496  }
497 
498 
500 
502  u32 size() const
503  {
504  return used-1;
505  }
506 
509  bool empty() const
510  {
511  return (size() == 0);
512  }
513 
514  void clear(bool releaseMemory=true)
515  {
516  if ( releaseMemory )
517  {
518  reallocate(1);
519  }
520  array[0] = 0;
521  used = 1;
522  }
523 
525 
526  const T* c_str() const
527  {
528  return array;
529  }
530 
531 
534  {
535  for (u32 i=0; array[i]; ++i)
536  array[i] = locale_lower ( array[i] );
537  return *this;
538  }
539 
540 
543  {
544  for (u32 i=0; array[i]; ++i)
545  array[i] = locale_upper ( array[i] );
546  return *this;
547  }
548 
549 
551 
553  bool equals_ignore_case(const string<T,TAlloc>& other) const
554  {
555  for(u32 i=0; array[i] && other[i]; ++i)
556  if (locale_lower( array[i]) != locale_lower(other[i]))
557  return false;
558 
559  return used == other.used;
560  }
561 
563 
566  bool equals_substring_ignore_case(const string<T,TAlloc>&other, const s32 sourcePos = 0 ) const
567  {
568  if ( (u32) sourcePos >= used )
569  return false;
570 
571  u32 i;
572  for( i=0; array[sourcePos + i] && other[i]; ++i)
573  if (locale_lower( array[sourcePos + i]) != locale_lower(other[i]))
574  return false;
575 
576  return array[sourcePos + i] == 0 && other[i] == 0;
577  }
578 
579 
581 
583  bool lower_ignore_case(const string<T,TAlloc>& other) const
584  {
585  for(u32 i=0; array[i] && other.array[i]; ++i)
586  {
587  s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] );
588  if ( diff )
589  return diff < 0;
590  }
591 
592  return used < other.used;
593  }
594 
595 
597 
600  bool equalsn(const string<T,TAlloc>& other, u32 n) const
601  {
602  u32 i;
603  for(i=0; i < n && array[i] && other[i]; ++i)
604  if (array[i] != other[i])
605  return false;
606 
607  // if one (or both) of the strings was smaller then they
608  // are only equal if they have the same length
609  return (i == n) || (used == other.used);
610  }
611 
612 
614 
617  bool equalsn(const T* const str, u32 n) const
618  {
619  if (!str)
620  return false;
621  u32 i;
622  for(i=0; i < n && array[i] && str[i]; ++i)
623  if (array[i] != str[i])
624  return false;
625 
626  // if one (or both) of the strings was smaller then they
627  // are only equal if they have the same length
628  return (i == n) || (array[i] == 0 && str[i] == 0);
629  }
630 
631 
633 
634  string<T,TAlloc>& append(T character)
635  {
636  if (used + 1 > allocated)
637  reallocate(used + 1);
638 
639  ++used;
640 
641  array[used-2] = character;
642  array[used-1] = 0;
643 
644  return *this;
645  }
646 
647 
649 
651  string<T,TAlloc>& append(const T* const other, u32 length=0xffffffff)
652  {
653  if (!other)
654  return *this;
655 
656  u32 len = 0;
657  const T* p = other;
658  while(*p)
659  {
660  ++len;
661  ++p;
662  }
663  if (len > length)
664  len = length;
665 
666  if (used + len > allocated)
667  reallocate(used + len);
668 
669  --used;
670  ++len;
671 
672  for (u32 l=0; l<len; ++l)
673  array[l+used] = *(other+l);
674 
675  used += len;
676 
677  return *this;
678  }
679 
680 
682 
684  {
685  if (other.size() == 0)
686  return *this;
687 
688  --used;
689  const u32 len = other.size()+1;
690 
691  if (used + len > allocated)
692  reallocate(used + len);
693 
694  for (u32 l=0; l<len; ++l)
695  array[used+l] = other[l];
696 
697  used += len;
698 
699  return *this;
700  }
701 
702 
704 
707  {
708  if (other.size() == 0)
709  return *this;
710 
711  if (other.size() < length)
712  {
713  append(other);
714  return *this;
715  }
716 
717  if (used + length > allocated)
718  reallocate(used + length);
719 
720  --used;
721 
722  for (u32 l=0; l<length; ++l)
723  array[l+used] = other[l];
724  used += length;
725 
726  // ensure proper termination
727  array[used]=0;
728  ++used;
729 
730  return *this;
731  }
732 
734  //\param pos Insert the characters before this index
735  //\param s String to insert. Must be at least of size n
736  //\param n Number of characters from string s to use.
737  string<T,TAlloc>& insert(u32 pos, const char* s, u32 n)
738  {
739  if ( pos < used )
740  {
741  reserve(used+n);
742 
743  // move stuff behind insert point
744  const u32 end = used+n-1;
745  for (u32 i=0; i<used-pos; ++i)
746  {
747  array[end-i] = array[end-(i+n)];
748  }
749  used += n;
750 
751  for (u32 i=0; i<n; ++i)
752  {
753  array[pos+i] = s[i];
754  }
755  }
756 
757  return *this;
758  }
759 
761 
763  {
764  if (count < allocated)
765  return;
766 
767  reallocate(count);
768  }
769 
770 
772 
775  s32 findFirst(T c) const
776  {
777  for (u32 i=0; i<used-1; ++i)
778  if (array[i] == c)
779  return i;
780 
781  return -1;
782  }
783 
785 
791  s32 findFirstChar(const T* const c, u32 count=1) const
792  {
793  if (!c || !count)
794  return -1;
795 
796  for (u32 i=0; i<used-1; ++i)
797  for (u32 j=0; j<count; ++j)
798  if (array[i] == c[j])
799  return i;
800 
801  return -1;
802  }
803 
804 
806 
812  template <class B>
813  s32 findFirstCharNotInList(const B* const c, u32 count=1) const
814  {
815  if (!c || !count)
816  return -1;
817 
818  for (u32 i=0; i<used-1; ++i)
819  {
820  u32 j;
821  for (j=0; j<count; ++j)
822  if (array[i] == c[j])
823  break;
824 
825  if (j==count)
826  return i;
827  }
828 
829  return -1;
830  }
831 
833 
839  template <class B>
840  s32 findLastCharNotInList(const B* const c, u32 count=1) const
841  {
842  if (!c || !count)
843  return -1;
844 
845  for (s32 i=(s32)(used-2); i>=0; --i)
846  {
847  u32 j;
848  for (j=0; j<count; ++j)
849  if (array[i] == c[j])
850  break;
851 
852  if (j==count)
853  return i;
854  }
855 
856  return -1;
857  }
858 
860 
864  s32 findNext(T c, u32 startPos) const
865  {
866  for (u32 i=startPos; i<used-1; ++i)
867  if (array[i] == c)
868  return i;
869 
870  return -1;
871  }
872 
873 
875 
879  s32 findLast(T c, s32 start = -1) const
880  {
881  start = core::clamp ( start < 0 ? (s32)(used) - 2 : start, 0, (s32)(used) - 2 );
882  for (s32 i=start; i>=0; --i)
883  if (array[i] == c)
884  return i;
885 
886  return -1;
887  }
888 
890 
896  s32 findLastChar(const T* const c, u32 count=1) const
897  {
898  if (!c || !count)
899  return -1;
900 
901  for (s32 i=(s32)used-2; i>=0; --i)
902  for (u32 j=0; j<count; ++j)
903  if (array[i] == c[j])
904  return i;
905 
906  return -1;
907  }
908 
909 
911 
915  template <class B>
916  s32 find(const B* const str, const u32 start = 0) const
917  {
918  if (str && *str)
919  {
920  u32 len = 0;
921 
922  while (str[len])
923  ++len;
924 
925  if (len > used-1)
926  return -1;
927 
928  for (u32 i=start; i<used-len; ++i)
929  {
930  u32 j=0;
931 
932  while(str[j] && array[i+j] == str[j])
933  ++j;
934 
935  if (!str[j])
936  return i;
937  }
938  }
939 
940  return -1;
941  }
942 
943 
945 
948  string<T> subString(u32 begin, s32 length, bool make_lower = false ) const
949  {
950  // if start after string
951  // or no proper substring length
952  if ((length <= 0) || (begin>=size()))
953  return string<T>("");
954  // clamp length to maximal value
955  if ((length+begin) > size())
956  length = size()-begin;
957 
958  string<T> o;
959  o.reserve(length+1);
960 
961  if ( !make_lower )
962  {
963  for (s32 i=0; i<length; ++i)
964  o.array[i] = array[i+begin];
965  }
966  else
967  {
968  for (s32 i=0; i<length; ++i)
969  o.array[i] = locale_lower ( array[i+begin] );
970  }
971 
972  o.array[length] = 0;
973  o.used = length + 1;
974 
975  return o;
976  }
977 
978 
980 
982  {
983  append(c);
984  return *this;
985  }
986 
987 
989 
990  string<T,TAlloc>& operator += (const T* const c)
991  {
992  append(c);
993  return *this;
994  }
995 
996 
998 
1000  {
1001  append(other);
1002  return *this;
1003  }
1004 
1005 
1007 
1009  {
1011  return *this;
1012  }
1013 
1014 
1016 
1017  string<T,TAlloc>& operator += (const unsigned int i)
1018  {
1020  return *this;
1021  }
1022 
1023 
1025 
1027  {
1029  return *this;
1030  }
1031 
1032 
1034 
1035  string<T,TAlloc>& operator += (const unsigned long i)
1036  {
1038  return *this;
1039  }
1040 
1041 
1043 
1045  {
1047  return *this;
1048  }
1049 
1050 
1052 
1054  {
1056  return *this;
1057  }
1058 
1059 
1061 
1063  string<T,TAlloc>& replace(T toReplace, T replaceWith)
1064  {
1065  for (u32 i=0; i<used-1; ++i)
1066  if (array[i] == toReplace)
1067  array[i] = replaceWith;
1068  return *this;
1069  }
1070 
1071 
1073 
1075  string<T,TAlloc>& replace(const string<T,TAlloc>& toReplace, const string<T,TAlloc>& replaceWith)
1076  {
1077  if (toReplace.size() == 0)
1078  return *this;
1079 
1080  const T* other = toReplace.c_str();
1081  const T* replace = replaceWith.c_str();
1082  const u32 other_size = toReplace.size();
1083  const u32 replace_size = replaceWith.size();
1084 
1085  // Determine the delta. The algorithm will change depending on the delta.
1086  s32 delta = replace_size - other_size;
1087 
1088  // A character for character replace. The string will not shrink or grow.
1089  if (delta == 0)
1090  {
1091  s32 pos = 0;
1092  while ((pos = find(other, pos)) != -1)
1093  {
1094  for (u32 i = 0; i < replace_size; ++i)
1095  array[pos + i] = replace[i];
1096  ++pos;
1097  }
1098  return *this;
1099  }
1100 
1101  // We are going to be removing some characters. The string will shrink.
1102  if (delta < 0)
1103  {
1104  u32 i = 0;
1105  for (u32 pos = 0; pos < used; ++i, ++pos)
1106  {
1107  // Is this potentially a match?
1108  if (array[pos] == *other)
1109  {
1110  // Check to see if we have a match.
1111  u32 j;
1112  for (j = 0; j < other_size; ++j)
1113  {
1114  if (array[pos + j] != other[j])
1115  break;
1116  }
1117 
1118  // If we have a match, replace characters.
1119  if (j == other_size)
1120  {
1121  for (j = 0; j < replace_size; ++j)
1122  array[i + j] = replace[j];
1123  i += replace_size - 1;
1124  pos += other_size - 1;
1125  continue;
1126  }
1127  }
1128 
1129  // No match found, just copy characters.
1130  array[i] = array[pos];
1131  }
1132  array[i-1] = 0;
1133  used = i;
1134 
1135  return *this;
1136  }
1137 
1138  // We are going to be adding characters, so the string size will increase.
1139  // Count the number of times toReplace exists in the string so we can allocate the new size.
1140  u32 find_count = 0;
1141  s32 pos = 0;
1142  while ((pos = find(other, pos)) != -1)
1143  {
1144  ++find_count;
1145  ++pos;
1146  }
1147 
1148  // Re-allocate the string now, if needed.
1149  u32 len = delta * find_count;
1150  if (used + len > allocated)
1151  reallocate(used + len);
1152 
1153  // Start replacing.
1154  pos = 0;
1155  while ((pos = find(other, pos)) != -1)
1156  {
1157  T* start = array + pos + other_size - 1;
1158  T* ptr = array + used - 1;
1159  T* end = array + delta + used -1;
1160 
1161  // Shift characters to make room for the string.
1162  while (ptr != start)
1163  {
1164  *end = *ptr;
1165  --ptr;
1166  --end;
1167  }
1168 
1169  // Add the new string now.
1170  for (u32 i = 0; i < replace_size; ++i)
1171  array[pos + i] = replace[i];
1172 
1173  pos += replace_size;
1174  used += delta;
1175  }
1176 
1177  return *this;
1178  }
1179 
1180 
1182 
1184  {
1185  u32 pos = 0;
1186  u32 found = 0;
1187  for (u32 i=0; i<used-1; ++i)
1188  {
1189  if (array[i] == c)
1190  {
1191  ++found;
1192  continue;
1193  }
1194 
1195  array[pos++] = array[i];
1196  }
1197  used -= found;
1198  array[used-1] = 0;
1199  return *this;
1200  }
1201 
1202 
1204 
1206  {
1207  u32 size = toRemove.size();
1208  if ( size == 0 )
1209  return *this;
1210  u32 pos = 0;
1211  u32 found = 0;
1212  for (u32 i=0; i<used-1; ++i)
1213  {
1214  u32 j = 0;
1215  while (j < size)
1216  {
1217  if (array[i + j] != toRemove[j])
1218  break;
1219  ++j;
1220  }
1221  if (j == size)
1222  {
1223  found += size;
1224  i += size - 1;
1225  continue;
1226  }
1227 
1228  array[pos++] = array[i];
1229  }
1230  used -= found;
1231  array[used-1] = 0;
1232  return *this;
1233  }
1234 
1235 
1237 
1239  {
1240  if (characters.size() == 0)
1241  return *this;
1242 
1243  u32 pos = 0;
1244  u32 found = 0;
1245  for (u32 i=0; i<used-1; ++i)
1246  {
1247  // Don't use characters.findFirst as it finds the \0,
1248  // causing used to become incorrect.
1249  bool docontinue = false;
1250  for (u32 j=0; j<characters.size(); ++j)
1251  {
1252  if (characters[j] == array[i])
1253  {
1254  ++found;
1255  docontinue = true;
1256  break;
1257  }
1258  }
1259  if (docontinue)
1260  continue;
1261 
1262  array[pos++] = array[i];
1263  }
1264  used -= found;
1265  array[used-1] = 0;
1266 
1267  return *this;
1268  }
1269 
1270 
1272 
1274  string<T,TAlloc>& trim(const string<T,TAlloc> & whitespace = " \t\n\r")
1275  {
1276  // find start and end of the substring without the specified characters
1277  const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used);
1278  if (begin == -1)
1279  return (*this="");
1280 
1281  const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used);
1282 
1283  return (*this = subString(begin, (end +1) - begin));
1284  }
1285 
1287 
1296  {
1297  s32 i=findLastCharNotInList("0", 1);
1298  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)
1299  {
1300  u32 eraseStart=i+1;
1301  u32 dot=0;
1302  if( core::isdigit(array[i]) )
1303  {
1304  while( --i>0 && core::isdigit(array[i]) );
1305  if ( array[i] == decimalPoint )
1306  dot = i;
1307  }
1308  else if ( array[i] == decimalPoint )
1309  {
1310  dot = i;
1311  eraseStart = i;
1312  }
1313  if ( dot > 0 && core::isdigit(array[dot-1]) )
1314  {
1315  array[eraseStart] = 0;
1316  used = eraseStart+1;
1317  }
1318  }
1319  return *this;
1320  }
1321 
1323 
1327  {
1328  _IRR_DEBUG_BREAK_IF(index>=used) // access violation
1329 
1330  for (u32 i=index+1; i<used; ++i)
1331  array[i-1] = array[i];
1332 
1333  --used;
1334  return *this;
1335  }
1336 
1339  {
1340  // terminate on existing null
1341  for (u32 i=0; i<allocated; ++i)
1342  {
1343  if (array[i] == 0)
1344  {
1345  used = i + 1;
1346  return *this;
1347  }
1348  }
1349 
1350  // terminate
1351  if ( allocated > 0 )
1352  {
1353  used = allocated;
1354  array[used-1] = 0;
1355  }
1356  else
1357  {
1358  used = 0;
1359  }
1360 
1361  return *this;
1362  }
1363 
1365  T lastChar() const
1366  {
1367  return used > 1 ? array[used-2] : 0;
1368  }
1369 
1371 
1389  template<class container>
1390  u32 split(container& ret, const T* const delimiter, u32 countDelimiters=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
1391  {
1392  if (!delimiter)
1393  return 0;
1394 
1395  const u32 oldSize=ret.size();
1396 
1397  u32 tokenStartIdx = 0;
1398  for (u32 i=0; i<used; ++i)
1399  {
1400  for (u32 j=0; j<countDelimiters; ++j)
1401  {
1402  if (array[i] == delimiter[j])
1403  {
1404  if (i - tokenStartIdx > 0)
1405  ret.push_back(string<T,TAlloc>(&array[tokenStartIdx], i - tokenStartIdx));
1406  else if ( !ignoreEmptyTokens )
1407  ret.push_back(string<T,TAlloc>());
1408  if ( keepSeparators )
1409  {
1410  ret.push_back(string<T,TAlloc>(&array[i], 1));
1411  }
1412 
1413  tokenStartIdx = i+1;
1414  break;
1415  }
1416  }
1417  }
1418  if ((used - 1) > tokenStartIdx)
1419  ret.push_back(string<T,TAlloc>(&array[tokenStartIdx], (used - 1) - tokenStartIdx));
1420  else if ( !ignoreEmptyTokens )
1421  ret.push_back(string<T,TAlloc>());
1422 
1423  return ret.size()-oldSize;
1424  }
1425 
1426  friend size_t multibyteToWString(string<wchar_t>& destination, const char* source, u32 sourceSize);
1427 
1428 private:
1429 
1431  void reallocate(u32 new_size)
1432  {
1433  T* old_array = array;
1434 
1435  array = allocator.allocate(new_size); //new T[new_size];
1436  allocated = new_size;
1437 
1438  const u32 amount = used < new_size ? used : new_size;
1439  for (u32 i=0; i<amount; ++i)
1440  array[i] = old_array[i];
1441 
1442  if (allocated < used)
1443  used = allocated;
1444 
1445  allocator.deallocate(old_array); // delete [] old_array;
1446  }
1447 
1448  //--- member variables
1449 
1450  T* array;
1451  u32 allocated;
1452  u32 used;
1453  TAlloc allocator;
1454 };
1455 
1456 
1459 
1462 
1464 
1469 static inline size_t multibyteToWString(string<wchar_t>& destination, const core::string<c8>& source)
1470 {
1471  return multibyteToWString(destination, source.c_str(), (u32)source.size());
1472 }
1473 
1475 
1480 static inline size_t multibyteToWString(string<wchar_t>& destination, const char* source)
1481 {
1482  const u32 s = source ? (u32)strlen(source) : 0;
1483  return multibyteToWString(destination, source, s);
1484 }
1485 
1487 static size_t multibyteToWString(string<wchar_t>& destination, const char* source, u32 sourceSize)
1488 {
1489  if ( sourceSize )
1490  {
1491  destination.reserve(sourceSize+1);
1492 #if defined(_MSC_VER)
1493 #pragma warning(push)
1494 #pragma warning(disable: 4996) // 'mbstowcs': This function or variable may be unsafe. Consider using mbstowcs_s instead.
1495 #endif
1496  const size_t written = mbstowcs(destination.array, source, (size_t)sourceSize);
1497 #if defined(_MSC_VER)
1498 #pragma warning(pop)
1499 #endif
1500  if ( written != (size_t)-1 )
1501  {
1502  destination.used = (u32)written+1;
1503  destination.array[destination.used-1] = 0;
1504  }
1505  else
1506  {
1507  // Likely character which got converted until the invalid character was encountered are in destination now.
1508  // And it seems even 0-terminated, but I found no documentation anywhere that this (the 0-termination) is guaranteed :-(
1509  destination.clear();
1510  }
1511  return written;
1512  }
1513  else
1514  {
1515  destination.clear();
1516  return 0;
1517  }
1518 }
1519 
1520 
1521 } // end namespace core
1522 } // end namespace irr
1523 
1524 #endif
1525 
string(long number)
Constructs a string from a long.
Definition: irrString.h:215
bool empty() const
Definition: irrString.h:509
s32 findFirstCharNotInList(const B *const c, u32 count=1) const
Finds first position of a character not in a given list.
Definition: irrString.h:813
unsigned long long u64
64 bit unsigned variable.
Definition: irrTypes.h:86
GLuint id
IRRLICHT_API void utf8ToWchar(const char *in, wchar_t *out, const u64 len)
Convert this utf-8-encoded string to the platform's wchar.
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.h:1390
T & operator [](const u32 index)
Direct access operator.
Definition: irrString.h:430
GLdouble n
u32 size() const
Returns length of the string's content.
Definition: irrString.h:502
GLsizei const GLchar *const * string
string< T, TAlloc > & append(T character)
Appends a character to this string.
Definition: irrString.h:634
string< T, TAlloc > & remove(T c)
Removes characters from a string.
Definition: irrString.h:1183
bool equals_substring_ignore_case(const string< T, TAlloc > &other, const s32 sourcePos=0) const
Compares the strings ignoring case.
Definition: irrString.h:566
s32 findLast(T c, s32 start=-1) const
finds last occurrence of character in string
Definition: irrString.h:879
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
string(const B *const c)
Constructor for Unicode and ASCII strings.
Definition: irrString.h:317
string< T, TAlloc > operator+(const B *const c) const
Append operator for strings, ASCII and Unicode.
Definition: irrString.h:420
GLuint GLuint end
Definition: SDL_opengl.h:1571
char c8
8 bit character variable.
Definition: irrTypes.h:35
GLfloat GLfloat p
string(const double number)
Constructs a string from a float.
Definition: irrString.h:126
s32 find(const B *const str, const u32 start=0) const
finds another string in this string
Definition: irrString.h:916
#define IRRLICHT_API
Set FPU settings.
~string()
Destructor.
Definition: irrString.h:325
GLuint start
Definition: SDL_opengl.h:1571
s32 isdigit(s32 c)
some standard function ( to remove dependencies )
Definition: coreutil.h:197
string< T, TAlloc > & operator=(const string< B, A > &other)
Assignment operator for other string types.
Definition: irrString.h:354
const T & operator [](const u32 index) const
Direct access operator.
Definition: irrString.h:438
Everything in the Irrlicht Engine can be found in this namespace.
Definition: CARSADPad.h:6
GLsizeiptr size
GLenum GLsizei len
Very simple string class with some useful features.
Definition: irrString.h:37
void push_back(const T &element)
Adds an element at back of array.
Definition: irrArray.h:111
string< T, TAlloc > & operator=(const string< T, TAlloc > &other)
Assignment operator.
Definition: irrString.h:332
bool operator==(const string< T, TAlloc > &other) const
Equality operator.
Definition: irrString.h:461
bool operator!=(const T *const str) const
Inequality operator.
Definition: irrString.h:486
void reserve(u32 count)
Reserves some memory.
Definition: irrString.h:762
string< T, TAlloc > & eraseTrailingFloatZeros(char decimalPoint='.')
Erase 0's at the end when a string ends with a floating point number.
Definition: irrString.h:1295
string< T, TAlloc > & trim(const string< T, TAlloc > &whitespace=" \t\n\r")
Trims the string.
Definition: irrString.h:1274
s32 findLastChar(const T *const c, u32 count=1) const
finds last occurrence of a character of a list in string
Definition: irrString.h:896
s32 findFirst(T c) const
finds first occurrence of character in string
Definition: irrString.h:775
string< T, TAlloc > & make_upper()
Makes the string upper case.
Definition: irrString.h:542
string(unsigned int number)
Constructs a string from an unsigned int.
Definition: irrString.h:184
s32 findLastCharNotInList(const B *const c, u32 count=1) const
Finds last position of a character not in a given list.
Definition: irrString.h:840
signed int s32
32 bit signed variable.
Definition: irrTypes.h:70
string< T, TAlloc > & append(const string< T, TAlloc > &other, u32 length)
Appends a string of the length l to this string.
Definition: irrString.h:706
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:1075
void clear(bool releaseMemory=true)
Definition: irrString.h:514
const T * c_str() const
Returns character string.
Definition: irrString.h:526
unsigned int u32
32 bit unsigned variable.
Definition: irrTypes.h:62
string(unsigned long number)
Constructs a string from an unsigned long.
Definition: irrString.h:263
IRRLICHT_API void wcharToUtf8(const wchar_t *in, char *out, const u64 len)
Convert this wchar string to utf-8.
bool operator==(const T *const str) const
Equality operator.
Definition: irrString.h:446
string< T, TAlloc > & make_lower()
Makes the string lower case.
Definition: irrString.h:533
T lastChar() const
gets the last char of a string or null
Definition: irrString.h:1365
string< T, TAlloc > & operator=(const B *const c)
Assignment operator for strings, ASCII and Unicode.
Definition: irrString.h:363
GLsizei GLsizei GLchar * source
string< T, TAlloc > & removeChars(const string< T, TAlloc > &characters)
Removes characters from a string.
Definition: irrString.h:1238
#define _IRR_DEBUG_BREAK_IF(_CONDITION_)
define a break macro for debugging.
Definition: irrTypes.h:185
string< c8 > stringc
Typedef for character strings.
Definition: irrString.h:1458
string< T, TAlloc > & remove(const string< T, TAlloc > &toRemove)
Removes a string from the string.
Definition: irrString.h:1205
bool equalsn(const T *const str, u32 n) const
compares the first n characters of the strings
Definition: irrString.h:617
string< T, TAlloc > & replace(T toReplace, T replaceWith)
Replaces all characters of a special type with another one.
Definition: irrString.h:1063
string()
Default constructor.
Definition: irrString.h:101
GLuint index
string(const string< B, A > &other)
Constructor from other string types.
Definition: irrString.h:118
string< T, TAlloc > & append(const T *const other, u32 length=0xffffffff)
Appends a char string to this string.
Definition: irrString.h:651
bool operator<(const string< T, TAlloc > &other) const
Is smaller comparator.
Definition: irrString.h:472
string< T > subString(u32 begin, s32 length, bool make_lower=false) const
Returns a substring.
Definition: irrString.h:948
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.h:737
#define snprintf_irr
Definition: irrTypes.h:149
Self reallocating template array (like stl vector) with additional features.
Definition: irrArray.h:22
GLdouble s
Definition: SDL_opengl.h:2063
s32 findFirstChar(const T *const c, u32 count=1) const
finds first occurrence of a character of a list in string
Definition: irrString.h:791
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
string(const string< T, TAlloc > &other)
Constructor.
Definition: irrString.h:110
friend size_t multibyteToWString(string< wchar_t > &destination, const char *source, u32 sourceSize)
Internally used by the other multibyteToWString functions.
Definition: irrString.h:1487
GLenum array
bool equals_ignore_case(const string< T, TAlloc > &other) const
Compares the strings ignoring case.
Definition: irrString.h:553
bool lower_ignore_case(const string< T, TAlloc > &other) const
Compares the strings ignoring case.
Definition: irrString.h:583
bool equalsn(const string< T, TAlloc > &other, u32 n) const
compares the first n characters of the strings
Definition: irrString.h:600
string< T, TAlloc > & operator+=(T c)
Appends a character to this string.
Definition: irrString.h:981
s32 findNext(T c, u32 startPos) const
finds next occurrence of character in string
Definition: irrString.h:864
string< T, TAlloc > & append(const string< T, TAlloc > &other)
Appends a string to this string.
Definition: irrString.h:683
GLuint GLsizei GLsizei * length
string< T, TAlloc > & validate()
verify the existing string.
Definition: irrString.h:1338
const GLubyte * c
GLuint in
bool operator!=(const string< T, TAlloc > &other) const
Inequality operator.
Definition: irrString.h:493
string(const B *const c, u32 length)
Constructor for copying a string from a pointer with a given length.
Definition: irrString.h:295
string< T, TAlloc > operator+(const string< T, TAlloc > &other) const
Append operator for other strings.
Definition: irrString.h:409
const T clamp(const T &value, const T &low, const T &high)
clamps a value between low and high
Definition: irrMath.h:167
string< T, TAlloc > & erase(u32 index)
Erases a character from the string.
Definition: irrString.h:1326
string(int number)
Constructs a string from an int.
Definition: irrString.h:136
string< wchar_t > stringw
Typedef for wide character strings.
Definition: irrString.h:1461