|
IrrlichtEngine
|
00001 // Copyright (C) 2002-2011 Nikolaus Gebhardt 00002 // This file is part of the "Irrlicht Engine" and the "irrXML" project. 00003 // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h 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 // ansi 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 // ansi 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); // new T[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 // store if negative and make positive 00119 00120 bool negative = false; 00121 if (number < 0) 00122 { 00123 number *= -1; 00124 negative = true; 00125 } 00126 00127 // temporary buffer for 16 numbers 00128 00129 c8 tmpbuf[16]={0}; 00130 u32 idx = 15; 00131 00132 // special case '0' 00133 00134 if (!number) 00135 { 00136 tmpbuf[14] = '0'; 00137 *this = &tmpbuf[14]; 00138 return; 00139 } 00140 00141 // add numbers 00142 00143 while(number && idx) 00144 { 00145 --idx; 00146 tmpbuf[idx] = (c8)('0' + (number % 10)); 00147 number /= 10; 00148 } 00149 00150 // add sign 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 // temporary buffer for 16 numbers 00167 00168 c8 tmpbuf[16]={0}; 00169 u32 idx = 15; 00170 00171 // special case '0' 00172 00173 if (!number) 00174 { 00175 tmpbuf[14] = '0'; 00176 *this = &tmpbuf[14]; 00177 return; 00178 } 00179 00180 // add numbers 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 // store if negative and make positive 00198 00199 bool negative = false; 00200 if (number < 0) 00201 { 00202 number *= -1; 00203 negative = true; 00204 } 00205 00206 // temporary buffer for 16 numbers 00207 00208 c8 tmpbuf[16]={0}; 00209 u32 idx = 15; 00210 00211 // special case '0' 00212 00213 if (!number) 00214 { 00215 tmpbuf[14] = '0'; 00216 *this = &tmpbuf[14]; 00217 return; 00218 } 00219 00220 // add numbers 00221 00222 while(number && idx) 00223 { 00224 --idx; 00225 tmpbuf[idx] = (c8)('0' + (number % 10)); 00226 number /= 10; 00227 } 00228 00229 // add sign 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 // temporary buffer for 16 numbers 00246 00247 c8 tmpbuf[16]={0}; 00248 u32 idx = 15; 00249 00250 // special case '0' 00251 00252 if (!number) 00253 { 00254 tmpbuf[14] = '0'; 00255 *this = &tmpbuf[14]; 00256 return; 00257 } 00258 00259 // add numbers 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 // correctly init the string to an empty one 00280 *this=""; 00281 return; 00282 } 00283 00284 allocated = used = length+1; 00285 array = allocator.allocate(used); // new T[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); // delete [] 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); // delete [] array; 00320 allocated = used; 00321 array = allocator.allocate(used); //new T[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); //new T[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 // we'll keep the old string for a while, because the new 00367 // string could be a part of the current string. 00368 T* oldArray = array; 00369 00370 used = len; 00371 if (used>allocated) 00372 { 00373 allocated = used; 00374 array = allocator.allocate(used); //new T[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); // delete [] 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) // bad index 00412 return array[index]; 00413 } 00414 00415 00417 const T& operator [](const u32 index) const 00418 { 00419 _IRR_DEBUG_BREAK_IF(index>=used) // bad index 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; i<used; ++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; i<used; ++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 // if one (or both) of the strings was smaller then they 00577 // are only equal if they have the same length 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 // if one (or both) of the strings was smaller then they 00596 // are only equal if they have the same length 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 // ensure proper termination 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; ++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; ++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; ++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) - 1 : start, 0, (s32)(used) - 1 ); 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=used-1; 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 // if start after string 00894 // or no proper substring length 00895 if ((length <= 0) || (begin>=size())) 00896 return string<T>(""); 00897 // clamp length to maximal value 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; ++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 // Determine the delta. The algorithm will change depending on the delta. 01030 s32 delta = replace_size - other_size; 01031 01032 // A character for character replace. The string will not shrink or grow. 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 // We are going to be removing some characters. The string will shrink. 01046 if (delta < 0) 01047 { 01048 u32 i = 0; 01049 for (u32 pos = 0; pos < used; ++i, ++pos) 01050 { 01051 // Is this potentially a match? 01052 if (array[pos] == *other) 01053 { 01054 // Check to see if we have a match. 01055 u32 j; 01056 for (j = 0; j < other_size; ++j) 01057 { 01058 if (array[pos + j] != other[j]) 01059 break; 01060 } 01061 01062 // If we have a match, replace characters. 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 // No match found, just copy characters. 01074 array[i] = array[pos]; 01075 } 01076 array[i-1] = 0; 01077 used = i; 01078 01079 return *this; 01080 } 01081 01082 // We are going to be adding characters, so the string size will increase. 01083 // Count the number of times toReplace exists in the string so we can allocate the new size. 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 // Re-allocate the string now, if needed. 01093 u32 len = delta * find_count; 01094 if (used + len > allocated) 01095 reallocate(used + len); 01096 01097 // Don't take the string terminator into account. 01098 --used; 01099 01100 // Start replacing. 01101 pos = 0; 01102 while ((pos = find(other, pos)) != -1) 01103 { 01104 T* start = array + pos + other_size - 1; 01105 T* ptr = array + used; 01106 T* end = array + used + delta; 01107 01108 // Shift characters to make room for the string. 01109 while (ptr != start) 01110 { 01111 *end = *ptr; 01112 --ptr; 01113 --end; 01114 } 01115 01116 // Add the new string now. 01117 for (u32 i = 0; i < replace_size; ++i) 01118 array[pos + i] = replace[i]; 01119 01120 pos += replace_size; 01121 used += delta; 01122 } 01123 01124 // Terminate the string and return ourself. 01125 array[used] = 0; 01126 ++used; 01127 return *this; 01128 } 01129 01130 01132 01133 string<T,TAlloc>& remove(T c) 01134 { 01135 u32 pos = 0; 01136 u32 found = 0; 01137 for (u32 i=0; i<used; ++i) 01138 { 01139 if (array[i] == c) 01140 { 01141 ++found; 01142 continue; 01143 } 01144 01145 array[pos++] = array[i]; 01146 } 01147 used -= found; 01148 array[used-1] = 0; 01149 return *this; 01150 } 01151 01152 01154 01155 string<T,TAlloc>& remove(const string<T,TAlloc>& toRemove) 01156 { 01157 u32 size = toRemove.size(); 01158 if ( size == 0 ) 01159 return *this; 01160 u32 pos = 0; 01161 u32 found = 0; 01162 for (u32 i=0; i<used; ++i) 01163 { 01164 u32 j = 0; 01165 while (j < size) 01166 { 01167 if (array[i + j] != toRemove[j]) 01168 break; 01169 ++j; 01170 } 01171 if (j == size) 01172 { 01173 found += size; 01174 i += size - 1; 01175 continue; 01176 } 01177 01178 array[pos++] = array[i]; 01179 } 01180 used -= found; 01181 array[used-1] = 0; 01182 return *this; 01183 } 01184 01185 01187 01188 string<T,TAlloc>& removeChars(const string<T,TAlloc> & characters) 01189 { 01190 if (characters.size() == 0) 01191 return *this; 01192 01193 u32 pos = 0; 01194 u32 found = 0; 01195 for (u32 i=0; i<used; ++i) 01196 { 01197 // Don't use characters.findFirst as it finds the \0, 01198 // causing used to become incorrect. 01199 bool docontinue = false; 01200 for (u32 j=0; j<characters.size(); ++j) 01201 { 01202 if (characters[j] == array[i]) 01203 { 01204 ++found; 01205 docontinue = true; 01206 break; 01207 } 01208 } 01209 if (docontinue) 01210 continue; 01211 01212 array[pos++] = array[i]; 01213 } 01214 used -= found; 01215 array[used-1] = 0; 01216 01217 return *this; 01218 } 01219 01220 01222 01224 string<T,TAlloc>& trim(const string<T,TAlloc> & whitespace = " \t\n\r") 01225 { 01226 // find start and end of the substring without the specified characters 01227 const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used); 01228 if (begin == -1) 01229 return (*this=""); 01230 01231 const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used); 01232 01233 return (*this = subString(begin, (end +1) - begin)); 01234 } 01235 01236 01238 01241 string<T,TAlloc>& erase(u32 index) 01242 { 01243 _IRR_DEBUG_BREAK_IF(index>=used) // access violation 01244 01245 for (u32 i=index+1; i<used; ++i) 01246 array[i-1] = array[i]; 01247 01248 --used; 01249 return *this; 01250 } 01251 01253 string<T,TAlloc>& validate() 01254 { 01255 // terminate on existing null 01256 for (u32 i=0; i<allocated; ++i) 01257 { 01258 if (array[i] == 0) 01259 { 01260 used = i + 1; 01261 return *this; 01262 } 01263 } 01264 01265 // terminate 01266 if ( allocated > 0 ) 01267 { 01268 used = allocated; 01269 array[used-1] = 0; 01270 } 01271 else 01272 { 01273 used = 0; 01274 } 01275 01276 return *this; 01277 } 01278 01280 T lastChar() const 01281 { 01282 return used > 1 ? array[used-2] : 0; 01283 } 01284 01286 01303 template<class container> 01304 u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const 01305 { 01306 if (!c) 01307 return 0; 01308 01309 const u32 oldSize=ret.size(); 01310 u32 lastpos = 0; 01311 bool lastWasSeparator = false; 01312 for (u32 i=0; i<used; ++i) 01313 { 01314 bool foundSeparator = false; 01315 for (u32 j=0; j<count; ++j) 01316 { 01317 if (array[i] == c[j]) 01318 { 01319 if ((!ignoreEmptyTokens || i - lastpos != 0) && 01320 !lastWasSeparator) 01321 ret.push_back(string<T,TAlloc>(&array[lastpos], i - lastpos)); 01322 foundSeparator = true; 01323 lastpos = (keepSeparators ? i : i + 1); 01324 break; 01325 } 01326 } 01327 lastWasSeparator = foundSeparator; 01328 } 01329 if ((used - 1) > lastpos) 01330 ret.push_back(string<T,TAlloc>(&array[lastpos], (used - 1) - lastpos)); 01331 return ret.size()-oldSize; 01332 } 01333 01334 private: 01335 01337 void reallocate(u32 new_size) 01338 { 01339 T* old_array = array; 01340 01341 array = allocator.allocate(new_size); //new T[new_size]; 01342 allocated = new_size; 01343 01344 u32 amount = used < new_size ? used : new_size; 01345 for (u32 i=0; i<amount; ++i) 01346 array[i] = old_array[i]; 01347 01348 if (allocated < used) 01349 used = allocated; 01350 01351 allocator.deallocate(old_array); // delete [] old_array; 01352 } 01353 01354 //--- member variables 01355 01356 T* array; 01357 u32 allocated; 01358 u32 used; 01359 TAlloc allocator; 01360 }; 01361 01362 01364 typedef string<c8> stringc; 01365 01367 typedef string<wchar_t> stringw; 01368 01369 01370 } // end namespace core 01371 } // end namespace irr 01372 01373 #endif 01374