00001
00002
00003
00004
00005 #ifndef __IRR_STRING_H_INCLUDED__
00006 #define __IRR_STRING_H_INCLUDED__
00007
00008 #include "irrTypes.h"
00009 #include "irrAllocator.h"
00010 #include "irrMath.h"
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <stdlib.h>
00014
00015 namespace irr
00016 {
00017 namespace core
00018 {
00019
00021
00032 enum eLocaleID
00033 {
00034 IRR_LOCALE_ANSI = 0,
00035 IRR_LOCALE_GERMAN = 1
00036 };
00037
00038 static eLocaleID locale_current = IRR_LOCALE_ANSI;
00039 static inline void locale_set ( eLocaleID id )
00040 {
00041 locale_current = id;
00042 }
00043
00045 static inline u32 locale_lower ( u32 x )
00046 {
00047 switch ( locale_current )
00048 {
00049 case IRR_LOCALE_GERMAN:
00050 case IRR_LOCALE_ANSI:
00051 break;
00052 }
00053
00054 return x >= 'A' && x <= 'Z' ? x + 0x20 : x;
00055 }
00056
00058 static inline u32 locale_upper ( u32 x )
00059 {
00060 switch ( locale_current )
00061 {
00062 case IRR_LOCALE_GERMAN:
00063 case IRR_LOCALE_ANSI:
00064 break;
00065 }
00066
00067
00068 return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x;
00069 }
00070
00071
00072 template <typename T, typename TAlloc = irrAllocator<T> >
00073 class string
00074 {
00075 public:
00076
00077 typedef T char_type;
00078
00080 string()
00081 : array(0), allocated(1), used(1)
00082 {
00083 array = allocator.allocate(1);
00084 array[0] = 0;
00085 }
00086
00087
00089 string(const string<T,TAlloc>& other)
00090 : array(0), allocated(0), used(0)
00091 {
00092 *this = other;
00093 }
00094
00096 template <class B, class A>
00097 string(const string<B, A>& other)
00098 : array(0), allocated(0), used(0)
00099 {
00100 *this = other;
00101 }
00102
00103
00105 explicit string(const double number)
00106 : array(0), allocated(0), used(0)
00107 {
00108 c8 tmpbuf[255];
00109 snprintf(tmpbuf, 255, "%0.6f", number);
00110 *this = tmpbuf;
00111 }
00112
00113
00115 explicit string(int number)
00116 : array(0), allocated(0), used(0)
00117 {
00118
00119
00120 bool negative = false;
00121 if (number < 0)
00122 {
00123 number *= -1;
00124 negative = true;
00125 }
00126
00127
00128
00129 c8 tmpbuf[16]={0};
00130 u32 idx = 15;
00131
00132
00133
00134 if (!number)
00135 {
00136 tmpbuf[14] = '0';
00137 *this = &tmpbuf[14];
00138 return;
00139 }
00140
00141
00142
00143 while(number && idx)
00144 {
00145 --idx;
00146 tmpbuf[idx] = (c8)('0' + (number % 10));
00147 number /= 10;
00148 }
00149
00150
00151
00152 if (negative)
00153 {
00154 --idx;
00155 tmpbuf[idx] = '-';
00156 }
00157
00158 *this = &tmpbuf[idx];
00159 }
00160
00161
00163 explicit string(unsigned int number)
00164 : array(0), allocated(0), used(0)
00165 {
00166
00167
00168 c8 tmpbuf[16]={0};
00169 u32 idx = 15;
00170
00171
00172
00173 if (!number)
00174 {
00175 tmpbuf[14] = '0';
00176 *this = &tmpbuf[14];
00177 return;
00178 }
00179
00180
00181
00182 while(number && idx)
00183 {
00184 --idx;
00185 tmpbuf[idx] = (c8)('0' + (number % 10));
00186 number /= 10;
00187 }
00188
00189 *this = &tmpbuf[idx];
00190 }
00191
00192
00194 explicit string(long number)
00195 : array(0), allocated(0), used(0)
00196 {
00197
00198
00199 bool negative = false;
00200 if (number < 0)
00201 {
00202 number *= -1;
00203 negative = true;
00204 }
00205
00206
00207
00208 c8 tmpbuf[16]={0};
00209 u32 idx = 15;
00210
00211
00212
00213 if (!number)
00214 {
00215 tmpbuf[14] = '0';
00216 *this = &tmpbuf[14];
00217 return;
00218 }
00219
00220
00221
00222 while(number && idx)
00223 {
00224 --idx;
00225 tmpbuf[idx] = (c8)('0' + (number % 10));
00226 number /= 10;
00227 }
00228
00229
00230
00231 if (negative)
00232 {
00233 --idx;
00234 tmpbuf[idx] = '-';
00235 }
00236
00237 *this = &tmpbuf[idx];
00238 }
00239
00240
00242 explicit string(unsigned long number)
00243 : array(0), allocated(0), used(0)
00244 {
00245
00246
00247 c8 tmpbuf[16]={0};
00248 u32 idx = 15;
00249
00250
00251
00252 if (!number)
00253 {
00254 tmpbuf[14] = '0';
00255 *this = &tmpbuf[14];
00256 return;
00257 }
00258
00259
00260
00261 while(number && idx)
00262 {
00263 --idx;
00264 tmpbuf[idx] = (c8)('0' + (number % 10));
00265 number /= 10;
00266 }
00267
00268 *this = &tmpbuf[idx];
00269 }
00270
00271
00273 template <class B>
00274 string(const B* const c, u32 length)
00275 : array(0), allocated(0), used(0)
00276 {
00277 if (!c)
00278 {
00279
00280 *this="";
00281 return;
00282 }
00283
00284 allocated = used = length+1;
00285 array = allocator.allocate(used);
00286
00287 for (u32 l = 0; l<length; ++l)
00288 array[l] = (T)c[l];
00289
00290 array[length] = 0;
00291 }
00292
00293
00295 template <class B>
00296 string(const B* const c)
00297 : array(0), allocated(0), used(0)
00298 {
00299 *this = c;
00300 }
00301
00302
00304 ~string()
00305 {
00306 allocator.deallocate(array);
00307 }
00308
00309
00311 string<T,TAlloc>& operator=(const string<T,TAlloc>& other)
00312 {
00313 if (this == &other)
00314 return *this;
00315
00316 used = other.size()+1;
00317 if (used>allocated)
00318 {
00319 allocator.deallocate(array);
00320 allocated = used;
00321 array = allocator.allocate(used);
00322 }
00323
00324 const T* p = other.c_str();
00325 for (u32 i=0; i<used; ++i, ++p)
00326 array[i] = *p;
00327
00328 return *this;
00329 }
00330
00332 template <class B, class A>
00333 string<T,TAlloc>& operator=(const string<B,A>& other)
00334 {
00335 *this = other.c_str();
00336 return *this;
00337 }
00338
00339
00341 template <class B>
00342 string<T,TAlloc>& operator=(const B* const c)
00343 {
00344 if (!c)
00345 {
00346 if (!array)
00347 {
00348 array = allocator.allocate(1);
00349 allocated = 1;
00350 }
00351 used = 1;
00352 array[0] = 0x0;
00353 return *this;
00354 }
00355
00356 if ((void*)c == (void*)array)
00357 return *this;
00358
00359 u32 len = 0;
00360 const B* p = c;
00361 do
00362 {
00363 ++len;
00364 } while(*p++);
00365
00366
00367
00368 T* oldArray = array;
00369
00370 used = len;
00371 if (used>allocated)
00372 {
00373 allocated = used;
00374 array = allocator.allocate(used);
00375 }
00376
00377 for (u32 l = 0; l<len; ++l)
00378 array[l] = (T)c[l];
00379
00380 if (oldArray != array)
00381 allocator.deallocate(oldArray);
00382
00383 return *this;
00384 }
00385
00386
00388 string<T,TAlloc> operator+(const string<T,TAlloc>& other) const
00389 {
00390 string<T,TAlloc> str(*this);
00391 str.append(other);
00392
00393 return str;
00394 }
00395
00396
00398 template <class B>
00399 string<T,TAlloc> operator+(const B* const c) const
00400 {
00401 string<T,TAlloc> str(*this);
00402 str.append(c);
00403
00404 return str;
00405 }
00406
00407
00409 T& operator [](const u32 index)
00410 {
00411 _IRR_DEBUG_BREAK_IF(index>=used)
00412 return array[index];
00413 }
00414
00415
00417 const T& operator [](const u32 index) const
00418 {
00419 _IRR_DEBUG_BREAK_IF(index>=used)
00420 return array[index];
00421 }
00422
00423
00425 bool operator==(const T* const str) const
00426 {
00427 if (!str)
00428 return false;
00429
00430 u32 i;
00431 for (i=0; array[i] && str[i]; ++i)
00432 if (array[i] != str[i])
00433 return false;
00434
00435 return (!array[i] && !str[i]);
00436 }
00437
00438
00440 bool operator==(const string<T,TAlloc>& other) const
00441 {
00442 for (u32 i=0; array[i] && other.array[i]; ++i)
00443 if (array[i] != other.array[i])
00444 return false;
00445
00446 return used == other.used;
00447 }
00448
00449
00451 bool operator<(const string<T,TAlloc>& other) const
00452 {
00453 for (u32 i=0; array[i] && other.array[i]; ++i)
00454 {
00455 const s32 diff = array[i] - other.array[i];
00456 if (diff)
00457 return (diff < 0);
00458 }
00459
00460 return (used < other.used);
00461 }
00462
00463
00465 bool operator!=(const T* const str) const
00466 {
00467 return !(*this == str);
00468 }
00469
00470
00472 bool operator!=(const string<T,TAlloc>& other) const
00473 {
00474 return !(*this == other);
00475 }
00476
00477
00479
00481 u32 size() const
00482 {
00483 return used-1;
00484 }
00485
00488 bool empty() const
00489 {
00490 return (size() == 0);
00491 }
00492
00494
00495 const T* c_str() const
00496 {
00497 return array;
00498 }
00499
00500
00502 string<T,TAlloc>& make_lower()
00503 {
00504 for (u32 i=0; array[i]; ++i)
00505 array[i] = locale_lower ( array[i] );
00506 return *this;
00507 }
00508
00509
00511 string<T,TAlloc>& make_upper()
00512 {
00513 for (u32 i=0; array[i]; ++i)
00514 array[i] = locale_upper ( array[i] );
00515 return *this;
00516 }
00517
00518
00520
00522 bool equals_ignore_case(const string<T,TAlloc>& other) const
00523 {
00524 for(u32 i=0; array[i] && other[i]; ++i)
00525 if (locale_lower( array[i]) != locale_lower(other[i]))
00526 return false;
00527
00528 return used == other.used;
00529 }
00530
00532
00535 bool equals_substring_ignore_case(const string<T,TAlloc>&other, const s32 sourcePos = 0 ) const
00536 {
00537 if ( (u32) sourcePos >= used )
00538 return false;
00539
00540 u32 i;
00541 for( i=0; array[sourcePos + i] && other[i]; ++i)
00542 if (locale_lower( array[sourcePos + i]) != locale_lower(other[i]))
00543 return false;
00544
00545 return array[sourcePos + i] == 0 && other[i] == 0;
00546 }
00547
00548
00550
00552 bool lower_ignore_case(const string<T,TAlloc>& other) const
00553 {
00554 for(u32 i=0; array[i] && other.array[i]; ++i)
00555 {
00556 s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] );
00557 if ( diff )
00558 return diff < 0;
00559 }
00560
00561 return used < other.used;
00562 }
00563
00564
00566
00569 bool equalsn(const string<T,TAlloc>& other, u32 n) const
00570 {
00571 u32 i;
00572 for(i=0; array[i] && other[i] && i < n; ++i)
00573 if (array[i] != other[i])
00574 return false;
00575
00576
00577
00578 return (i == n) || (used == other.used);
00579 }
00580
00581
00583
00586 bool equalsn(const T* const str, u32 n) const
00587 {
00588 if (!str)
00589 return false;
00590 u32 i;
00591 for(i=0; array[i] && str[i] && i < n; ++i)
00592 if (array[i] != str[i])
00593 return false;
00594
00595
00596
00597 return (i == n) || (array[i] == 0 && str[i] == 0);
00598 }
00599
00600
00602
00603 string<T,TAlloc>& append(T character)
00604 {
00605 if (used + 1 > allocated)
00606 reallocate(used + 1);
00607
00608 ++used;
00609
00610 array[used-2] = character;
00611 array[used-1] = 0;
00612
00613 return *this;
00614 }
00615
00616
00618
00620 string<T,TAlloc>& append(const T* const other, u32 length=0xffffffff)
00621 {
00622 if (!other)
00623 return *this;
00624
00625 u32 len = 0;
00626 const T* p = other;
00627 while(*p)
00628 {
00629 ++len;
00630 ++p;
00631 }
00632 if (len > length)
00633 len = length;
00634
00635 if (used + len > allocated)
00636 reallocate(used + len);
00637
00638 --used;
00639 ++len;
00640
00641 for (u32 l=0; l<len; ++l)
00642 array[l+used] = *(other+l);
00643
00644 used += len;
00645
00646 return *this;
00647 }
00648
00649
00651
00652 string<T,TAlloc>& append(const string<T,TAlloc>& other)
00653 {
00654 if (other.size() == 0)
00655 return *this;
00656
00657 --used;
00658 u32 len = other.size()+1;
00659
00660 if (used + len > allocated)
00661 reallocate(used + len);
00662
00663 for (u32 l=0; l<len; ++l)
00664 array[used+l] = other[l];
00665
00666 used += len;
00667
00668 return *this;
00669 }
00670
00671
00673
00675 string<T,TAlloc>& append(const string<T,TAlloc>& other, u32 length)
00676 {
00677 if (other.size() == 0)
00678 return *this;
00679
00680 if (other.size() < length)
00681 {
00682 append(other);
00683 return *this;
00684 }
00685
00686 if (used + length > allocated)
00687 reallocate(used + length);
00688
00689 --used;
00690
00691 for (u32 l=0; l<length; ++l)
00692 array[l+used] = other[l];
00693 used += length;
00694
00695
00696 array[used]=0;
00697 ++used;
00698
00699 return *this;
00700 }
00701
00702
00704
00705 void reserve(u32 count)
00706 {
00707 if (count < allocated)
00708 return;
00709
00710 reallocate(count);
00711 }
00712
00713
00715
00718 s32 findFirst(T c) const
00719 {
00720 for (u32 i=0; i<used-1; ++i)
00721 if (array[i] == c)
00722 return i;
00723
00724 return -1;
00725 }
00726
00728
00734 s32 findFirstChar(const T* const c, u32 count=1) const
00735 {
00736 if (!c || !count)
00737 return -1;
00738
00739 for (u32 i=0; i<used-1; ++i)
00740 for (u32 j=0; j<count; ++j)
00741 if (array[i] == c[j])
00742 return i;
00743
00744 return -1;
00745 }
00746
00747
00749
00755 template <class B>
00756 s32 findFirstCharNotInList(const B* const c, u32 count=1) const
00757 {
00758 if (!c || !count)
00759 return -1;
00760
00761 for (u32 i=0; i<used-1; ++i)
00762 {
00763 u32 j;
00764 for (j=0; j<count; ++j)
00765 if (array[i] == c[j])
00766 break;
00767
00768 if (j==count)
00769 return i;
00770 }
00771
00772 return -1;
00773 }
00774
00776
00782 template <class B>
00783 s32 findLastCharNotInList(const B* const c, u32 count=1) const
00784 {
00785 if (!c || !count)
00786 return -1;
00787
00788 for (s32 i=(s32)(used-2); i>=0; --i)
00789 {
00790 u32 j;
00791 for (j=0; j<count; ++j)
00792 if (array[i] == c[j])
00793 break;
00794
00795 if (j==count)
00796 return i;
00797 }
00798
00799 return -1;
00800 }
00801
00803
00807 s32 findNext(T c, u32 startPos) const
00808 {
00809 for (u32 i=startPos; i<used-1; ++i)
00810 if (array[i] == c)
00811 return i;
00812
00813 return -1;
00814 }
00815
00816
00818
00822 s32 findLast(T c, s32 start = -1) const
00823 {
00824 start = core::clamp ( start < 0 ? (s32)(used) - 2 : start, 0, (s32)(used) - 2 );
00825 for (s32 i=start; i>=0; --i)
00826 if (array[i] == c)
00827 return i;
00828
00829 return -1;
00830 }
00831
00833
00839 s32 findLastChar(const T* const c, u32 count=1) const
00840 {
00841 if (!c || !count)
00842 return -1;
00843
00844 for (s32 i=(s32)used-2; i>=0; --i)
00845 for (u32 j=0; j<count; ++j)
00846 if (array[i] == c[j])
00847 return i;
00848
00849 return -1;
00850 }
00851
00852
00854
00858 template <class B>
00859 s32 find(const B* const str, const u32 start = 0) const
00860 {
00861 if (str && *str)
00862 {
00863 u32 len = 0;
00864
00865 while (str[len])
00866 ++len;
00867
00868 if (len > used-1)
00869 return -1;
00870
00871 for (u32 i=start; i<used-len; ++i)
00872 {
00873 u32 j=0;
00874
00875 while(str[j] && array[i+j] == str[j])
00876 ++j;
00877
00878 if (!str[j])
00879 return i;
00880 }
00881 }
00882
00883 return -1;
00884 }
00885
00886
00888
00891 string<T> subString(u32 begin, s32 length, bool make_lower = false ) const
00892 {
00893
00894
00895 if ((length <= 0) || (begin>=size()))
00896 return string<T>("");
00897
00898 if ((length+begin) > size())
00899 length = size()-begin;
00900
00901 string<T> o;
00902 o.reserve(length+1);
00903
00904 s32 i;
00905 if ( !make_lower )
00906 {
00907 for (i=0; i<length; ++i)
00908 o.array[i] = array[i+begin];
00909 }
00910 else
00911 {
00912 for (i=0; i<length; ++i)
00913 o.array[i] = locale_lower ( array[i+begin] );
00914 }
00915
00916 o.array[length] = 0;
00917 o.used = length + 1;
00918
00919 return o;
00920 }
00921
00922
00924
00925 string<T,TAlloc>& operator += (T c)
00926 {
00927 append(c);
00928 return *this;
00929 }
00930
00931
00933
00934 string<T,TAlloc>& operator += (const T* const c)
00935 {
00936 append(c);
00937 return *this;
00938 }
00939
00940
00942
00943 string<T,TAlloc>& operator += (const string<T,TAlloc>& other)
00944 {
00945 append(other);
00946 return *this;
00947 }
00948
00949
00951
00952 string<T,TAlloc>& operator += (const int i)
00953 {
00954 append(string<T,TAlloc>(i));
00955 return *this;
00956 }
00957
00958
00960
00961 string<T,TAlloc>& operator += (const unsigned int i)
00962 {
00963 append(string<T,TAlloc>(i));
00964 return *this;
00965 }
00966
00967
00969
00970 string<T,TAlloc>& operator += (const long i)
00971 {
00972 append(string<T,TAlloc>(i));
00973 return *this;
00974 }
00975
00976
00978
00979 string<T,TAlloc>& operator += (const unsigned long i)
00980 {
00981 append(string<T,TAlloc>(i));
00982 return *this;
00983 }
00984
00985
00987
00988 string<T,TAlloc>& operator += (const double i)
00989 {
00990 append(string<T,TAlloc>(i));
00991 return *this;
00992 }
00993
00994
00996
00997 string<T,TAlloc>& operator += (const float i)
00998 {
00999 append(string<T,TAlloc>(i));
01000 return *this;
01001 }
01002
01003
01005
01007 string<T,TAlloc>& replace(T toReplace, T replaceWith)
01008 {
01009 for (u32 i=0; i<used-1; ++i)
01010 if (array[i] == toReplace)
01011 array[i] = replaceWith;
01012 return *this;
01013 }
01014
01015
01017
01019 string<T,TAlloc>& replace(const string<T,TAlloc>& toReplace, const string<T,TAlloc>& replaceWith)
01020 {
01021 if (toReplace.size() == 0)
01022 return *this;
01023
01024 const T* other = toReplace.c_str();
01025 const T* replace = replaceWith.c_str();
01026 const u32 other_size = toReplace.size();
01027 const u32 replace_size = replaceWith.size();
01028
01029
01030 s32 delta = replace_size - other_size;
01031
01032
01033 if (delta == 0)
01034 {
01035 s32 pos = 0;
01036 while ((pos = find(other, pos)) != -1)
01037 {
01038 for (u32 i = 0; i < replace_size; ++i)
01039 array[pos + i] = replace[i];
01040 ++pos;
01041 }
01042 return *this;
01043 }
01044
01045
01046 if (delta < 0)
01047 {
01048 u32 i = 0;
01049 for (u32 pos = 0; pos < used; ++i, ++pos)
01050 {
01051
01052 if (array[pos] == *other)
01053 {
01054
01055 u32 j;
01056 for (j = 0; j < other_size; ++j)
01057 {
01058 if (array[pos + j] != other[j])
01059 break;
01060 }
01061
01062
01063 if (j == other_size)
01064 {
01065 for (j = 0; j < replace_size; ++j)
01066 array[i + j] = replace[j];
01067 i += replace_size - 1;
01068 pos += other_size - 1;
01069 continue;
01070 }
01071 }
01072
01073
01074 array[i] = array[pos];
01075 }
01076 array[i-1] = 0;
01077 used = i;
01078
01079 return *this;
01080 }
01081
01082
01083
01084 u32 find_count = 0;
01085 s32 pos = 0;
01086 while ((pos = find(other, pos)) != -1)
01087 {
01088 ++find_count;
01089 ++pos;
01090 }
01091
01092
01093 u32 len = delta * find_count;
01094 if (used + len > allocated)
01095 reallocate(used + len);
01096
01097
01098 pos = 0;
01099 while ((pos = find(other, pos)) != -1)
01100 {
01101 T* start = array + pos + other_size - 1;
01102 T* ptr = array + used - 1;
01103 T* end = array + delta + used -1;
01104
01105
01106 while (ptr != start)
01107 {
01108 *end = *ptr;
01109 --ptr;
01110 --end;
01111 }
01112
01113
01114 for (u32 i = 0; i < replace_size; ++i)
01115 array[pos + i] = replace[i];
01116
01117 pos += replace_size;
01118 used += delta;
01119 }
01120
01121 return *this;
01122 }
01123
01124
01126
01127 string<T,TAlloc>& remove(T c)
01128 {
01129 u32 pos = 0;
01130 u32 found = 0;
01131 for (u32 i=0; i<used-1; ++i)
01132 {
01133 if (array[i] == c)
01134 {
01135 ++found;
01136 continue;
01137 }
01138
01139 array[pos++] = array[i];
01140 }
01141 used -= found;
01142 array[used-1] = 0;
01143 return *this;
01144 }
01145
01146
01148
01149 string<T,TAlloc>& remove(const string<T,TAlloc>& toRemove)
01150 {
01151 u32 size = toRemove.size();
01152 if ( size == 0 )
01153 return *this;
01154 u32 pos = 0;
01155 u32 found = 0;
01156 for (u32 i=0; i<used-1; ++i)
01157 {
01158 u32 j = 0;
01159 while (j < size)
01160 {
01161 if (array[i + j] != toRemove[j])
01162 break;
01163 ++j;
01164 }
01165 if (j == size)
01166 {
01167 found += size;
01168 i += size - 1;
01169 continue;
01170 }
01171
01172 array[pos++] = array[i];
01173 }
01174 used -= found;
01175 array[used-1] = 0;
01176 return *this;
01177 }
01178
01179
01181
01182 string<T,TAlloc>& removeChars(const string<T,TAlloc> & characters)
01183 {
01184 if (characters.size() == 0)
01185 return *this;
01186
01187 u32 pos = 0;
01188 u32 found = 0;
01189 for (u32 i=0; i<used-1; ++i)
01190 {
01191
01192
01193 bool docontinue = false;
01194 for (u32 j=0; j<characters.size(); ++j)
01195 {
01196 if (characters[j] == array[i])
01197 {
01198 ++found;
01199 docontinue = true;
01200 break;
01201 }
01202 }
01203 if (docontinue)
01204 continue;
01205
01206 array[pos++] = array[i];
01207 }
01208 used -= found;
01209 array[used-1] = 0;
01210
01211 return *this;
01212 }
01213
01214
01216
01218 string<T,TAlloc>& trim(const string<T,TAlloc> & whitespace = " \t\n\r")
01219 {
01220
01221 const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used);
01222 if (begin == -1)
01223 return (*this="");
01224
01225 const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used);
01226
01227 return (*this = subString(begin, (end +1) - begin));
01228 }
01229
01230
01232
01235 string<T,TAlloc>& erase(u32 index)
01236 {
01237 _IRR_DEBUG_BREAK_IF(index>=used)
01238
01239 for (u32 i=index+1; i<used; ++i)
01240 array[i-1] = array[i];
01241
01242 --used;
01243 return *this;
01244 }
01245
01247 string<T,TAlloc>& validate()
01248 {
01249
01250 for (u32 i=0; i<allocated; ++i)
01251 {
01252 if (array[i] == 0)
01253 {
01254 used = i + 1;
01255 return *this;
01256 }
01257 }
01258
01259
01260 if ( allocated > 0 )
01261 {
01262 used = allocated;
01263 array[used-1] = 0;
01264 }
01265 else
01266 {
01267 used = 0;
01268 }
01269
01270 return *this;
01271 }
01272
01274 T lastChar() const
01275 {
01276 return used > 1 ? array[used-2] : 0;
01277 }
01278
01280
01297 template<class container>
01298 u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
01299 {
01300 if (!c)
01301 return 0;
01302
01303 const u32 oldSize=ret.size();
01304 u32 lastpos = 0;
01305 bool lastWasSeparator = false;
01306 for (u32 i=0; i<used; ++i)
01307 {
01308 bool foundSeparator = false;
01309 for (u32 j=0; j<count; ++j)
01310 {
01311 if (array[i] == c[j])
01312 {
01313 if ((!ignoreEmptyTokens || i - lastpos != 0) &&
01314 !lastWasSeparator)
01315 ret.push_back(string<T,TAlloc>(&array[lastpos], i - lastpos));
01316 foundSeparator = true;
01317 lastpos = (keepSeparators ? i : i + 1);
01318 break;
01319 }
01320 }
01321 lastWasSeparator = foundSeparator;
01322 }
01323 if ((used - 1) > lastpos)
01324 ret.push_back(string<T,TAlloc>(&array[lastpos], (used - 1) - lastpos));
01325 return ret.size()-oldSize;
01326 }
01327
01328 private:
01329
01331 void reallocate(u32 new_size)
01332 {
01333 T* old_array = array;
01334
01335 array = allocator.allocate(new_size);
01336 allocated = new_size;
01337
01338 u32 amount = used < new_size ? used : new_size;
01339 for (u32 i=0; i<amount; ++i)
01340 array[i] = old_array[i];
01341
01342 if (allocated < used)
01343 used = allocated;
01344
01345 allocator.deallocate(old_array);
01346 }
01347
01348
01349
01350 T* array;
01351 u32 allocated;
01352 u32 used;
01353 TAlloc allocator;
01354 };
01355
01356
01358 typedef string<c8> stringc;
01359
01361 typedef string<wchar_t> stringw;
01362
01363
01364 }
01365 }
01366
01367 #endif
01368