Crazy Eddies GUI System
0.7.6
|
00001 /*********************************************************************** 00002 filename: CEGUIString.h 00003 created: 26/2/2004 00004 author: Paul D Turner 00005 00006 purpose: Defines string class used within the GUI system. 00007 *************************************************************************/ 00008 /*************************************************************************** 00009 * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team 00010 * 00011 * Permission is hereby granted, free of charge, to any person obtaining 00012 * a copy of this software and associated documentation files (the 00013 * "Software"), to deal in the Software without restriction, including 00014 * without limitation the rights to use, copy, modify, merge, publish, 00015 * distribute, sublicense, and/or sell copies of the Software, and to 00016 * permit persons to whom the Software is furnished to do so, subject to 00017 * the following conditions: 00018 * 00019 * The above copyright notice and this permission notice shall be 00020 * included in all copies or substantial portions of the Software. 00021 * 00022 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00023 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00024 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00025 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 00026 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00027 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00028 * OTHER DEALINGS IN THE SOFTWARE. 00029 ***************************************************************************/ 00030 #ifndef _CEGUIString_h_ 00031 #define _CEGUIString_h_ 00032 00033 #include "CEGUIBase.h" 00034 #include <string.h> 00035 #include <stdexcept> 00036 #include <cstddef> 00037 00038 // Start of CEGUI namespace section 00039 namespace CEGUI 00040 { 00041 #define STR_QUICKBUFF_SIZE 32 00042 /************************************************************************* 00043 Basic Types 00044 *************************************************************************/ 00045 typedef uint8 utf8; 00046 //typedef uint16 utf16; // removed typedef to prevent usage, as utf16 is not supported (yet) 00047 typedef uint32 utf32; 00048 00057 class CEGUIEXPORT String 00058 { 00059 public: 00060 /************************************************************************* 00061 Integral Types 00062 *************************************************************************/ 00063 typedef utf32 value_type; 00064 typedef size_t size_type; 00065 typedef std::ptrdiff_t difference_type; 00066 typedef utf32& reference; 00067 typedef const utf32& const_reference; 00068 typedef utf32* pointer; 00069 typedef const utf32* const_pointer; 00070 00071 static const size_type npos; 00072 00073 private: 00074 /************************************************************************* 00075 Implementation data 00076 *************************************************************************/ 00077 size_type d_cplength; 00078 size_type d_reserve; 00079 00080 mutable utf8* d_encodedbuff; 00081 mutable size_type d_encodeddatlen; 00082 mutable size_type d_encodedbufflen; 00083 00084 utf32 d_quickbuff[STR_QUICKBUFF_SIZE]; 00085 utf32* d_buffer; 00086 00087 public: 00088 /************************************************************************* 00089 Iterator Classes 00090 *************************************************************************/ 00092 class iterator : public std::iterator<std::random_access_iterator_tag, utf32> 00093 { 00094 public: 00095 iterator() : d_ptr(0) {} 00096 explicit iterator(utf32* const ptr) : d_ptr(ptr) {} 00097 00098 utf32& operator*() const 00099 { 00100 return *d_ptr; 00101 } 00102 00103 utf32* operator->() const 00104 { 00105 return &**this; 00106 } 00107 00108 String::iterator& operator++() 00109 { 00110 ++d_ptr; 00111 return *this; 00112 } 00113 00114 String::iterator operator++(int) 00115 { 00116 String::iterator temp = *this; 00117 ++*this; 00118 return temp; 00119 } 00120 00121 String::iterator& operator--() 00122 { 00123 --d_ptr; 00124 return *this; 00125 } 00126 00127 String::iterator operator--(int) 00128 { 00129 String::iterator temp = *this; 00130 --*this; 00131 return temp; 00132 } 00133 00134 String::iterator& operator+=(difference_type offset) 00135 { 00136 d_ptr += offset; 00137 return *this; 00138 } 00139 00140 String::iterator operator+(difference_type offset) const 00141 { 00142 String::iterator temp = *this; 00143 return temp += offset; 00144 } 00145 00146 String::iterator& operator-=(difference_type offset) 00147 { 00148 return *this += -offset; 00149 } 00150 00151 String::iterator operator-(difference_type offset) const 00152 { 00153 String::iterator temp = *this; 00154 return temp -= offset; 00155 } 00156 00157 utf32& operator[](difference_type offset) const 00158 { 00159 return *(*this + offset); 00160 } 00161 00162 friend difference_type operator-(const String::iterator& lhs, 00163 const String::iterator& rhs) 00164 { return lhs.d_ptr - rhs.d_ptr; } 00165 00166 friend String::iterator operator+(difference_type offset, const String::iterator& iter) 00167 { return iter + offset; } 00168 00169 friend bool operator==(const String::iterator& lhs, 00170 const String::iterator& rhs) 00171 { return lhs.d_ptr == rhs.d_ptr; } 00172 00173 friend bool operator!=(const String::iterator& lhs, 00174 const String::iterator& rhs) 00175 { return lhs.d_ptr != rhs.d_ptr; } 00176 00177 friend bool operator<(const String::iterator& lhs, 00178 const String::iterator& rhs) 00179 { return lhs.d_ptr < rhs.d_ptr; } 00180 00181 friend bool operator>(const String::iterator& lhs, 00182 const String::iterator& rhs) 00183 { return lhs.d_ptr > rhs.d_ptr; } 00184 00185 friend bool operator<=(const String::iterator& lhs, 00186 const String::iterator& rhs) 00187 { return lhs.d_ptr <= rhs.d_ptr; } 00188 00189 friend bool operator>=(const String::iterator& lhs, 00190 const String::iterator& rhs) 00191 { return lhs.d_ptr >= rhs.d_ptr; } 00192 00193 utf32* d_ptr; 00194 }; 00195 00197 class const_iterator : public std::iterator<std::random_access_iterator_tag, const utf32> 00198 { 00199 public: 00200 const_iterator() : d_ptr(0) {} 00201 explicit const_iterator(const utf32* const ptr) : d_ptr(ptr) {} 00202 const_iterator(const String::iterator& iter) : d_ptr(iter.d_ptr) {} 00203 00204 const utf32& operator*() const 00205 { 00206 return *d_ptr; 00207 } 00208 00209 const utf32* operator->() const 00210 { 00211 return &**this; 00212 } 00213 00214 String::const_iterator& operator++() 00215 { 00216 ++d_ptr; 00217 return *this; 00218 } 00219 00220 String::const_iterator operator++(int) 00221 { 00222 String::const_iterator temp = *this; 00223 ++*this; 00224 return temp; 00225 } 00226 00227 String::const_iterator& operator--() 00228 { 00229 --d_ptr; 00230 return *this; 00231 } 00232 00233 String::const_iterator operator--(int) 00234 { 00235 String::const_iterator temp = *this; 00236 --*this; 00237 return temp; 00238 } 00239 00240 String::const_iterator& operator+=(difference_type offset) 00241 { 00242 d_ptr += offset; 00243 return *this; 00244 } 00245 00246 String::const_iterator operator+(difference_type offset) const 00247 { 00248 String::const_iterator temp = *this; 00249 return temp += offset; 00250 } 00251 00252 String::const_iterator& operator-=(difference_type offset) 00253 { 00254 return *this += -offset; 00255 } 00256 00257 String::const_iterator operator-(difference_type offset) const 00258 { 00259 String::const_iterator temp = *this; 00260 return temp -= offset; 00261 } 00262 00263 const utf32& operator[](difference_type offset) const 00264 { 00265 return *(*this + offset); 00266 } 00267 00268 String::const_iterator& operator=(const String::iterator& iter) 00269 { 00270 d_ptr = iter.d_ptr; 00271 return *this; 00272 } 00273 00274 friend String::const_iterator operator+(difference_type offset, const String::const_iterator& iter) 00275 { return iter + offset; } 00276 00277 friend difference_type operator-(const String::const_iterator& lhs, 00278 const String::const_iterator& rhs) 00279 { return lhs.d_ptr - rhs.d_ptr; } 00280 00281 friend bool operator==(const String::const_iterator& lhs, 00282 const String::const_iterator& rhs) 00283 { return lhs.d_ptr == rhs.d_ptr; } 00284 00285 friend bool operator!=(const String::const_iterator& lhs, 00286 const String::const_iterator& rhs) 00287 { return lhs.d_ptr != rhs.d_ptr; } 00288 00289 friend bool operator<(const String::const_iterator& lhs, 00290 const String::const_iterator& rhs) 00291 { return lhs.d_ptr < rhs.d_ptr; } 00292 00293 friend bool operator>(const String::const_iterator& lhs, 00294 const String::const_iterator& rhs) 00295 { return lhs.d_ptr > rhs.d_ptr; } 00296 00297 friend bool operator<=(const String::const_iterator& lhs, 00298 const String::const_iterator& rhs) 00299 { return lhs.d_ptr <= rhs.d_ptr; } 00300 00301 friend bool operator>=(const String::const_iterator& lhs, 00302 const String::const_iterator& rhs) 00303 { return lhs.d_ptr >= rhs.d_ptr; } 00304 00305 const utf32* d_ptr; 00306 }; 00307 00312 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION))) 00313 typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator; 00314 #else 00315 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00316 #endif 00317 00322 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION))) 00323 typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator; 00324 #else 00325 typedef std::reverse_iterator<iterator> reverse_iterator; 00326 #endif 00327 00328 public: 00334 struct FastLessCompare 00335 { 00336 bool operator() (const String& a, const String& b) const 00337 { 00338 const size_t la = a.length(); 00339 const size_t lb = b.length(); 00340 if (la == lb) 00341 return (memcmp(a.ptr(), b.ptr(), la*sizeof(utf32)) < 0); 00342 return (la < lb); 00343 } 00344 }; 00345 00346 public: 00348 // Default Construction and Destructor 00350 00354 String(void) 00355 { 00356 init(); 00357 } 00358 00363 ~String(void); 00364 00366 // Construction via CEGUI::String 00368 00378 String(const String& str) 00379 { 00380 init(); 00381 assign(str); 00382 } 00383 00384 00401 String(const String& str, size_type str_idx, size_type str_num = npos) 00402 { 00403 init(); 00404 assign(str, str_idx, str_num); 00405 } 00406 00408 // Construction via std::string 00410 00426 String(const std::string& std_str) 00427 { 00428 init(); 00429 assign(std_str); 00430 } 00431 00454 String(const std::string& std_str, size_type str_idx, size_type str_num = npos) 00455 { 00456 init(); 00457 assign(std_str, str_idx, str_num); 00458 } 00459 00460 00462 // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid) 00464 00482 String(const utf8* utf8_str) 00483 { 00484 init(); 00485 assign(utf8_str); 00486 } 00487 00514 String(const utf8* utf8_str, size_type chars_len) 00515 { 00516 init(); 00517 assign(utf8_str, chars_len); 00518 } 00519 00521 // Construction via code-point (using a UTF-32 code unit) 00523 00538 String(size_type num, utf32 code_point) 00539 { 00540 init(); 00541 assign(num, code_point); 00542 } 00543 00545 // Construction via iterator 00547 // Create string with characters in the range [beg, end) 00561 String(const_iterator iter_beg, const_iterator iter_end) 00562 { 00563 init(); 00564 append(iter_beg, iter_end); 00565 } 00566 00567 00569 // Construction via c-string 00571 00583 String(const char* cstr) 00584 { 00585 init(); 00586 assign(cstr); 00587 } 00588 00604 String(const char* chars, size_type chars_len) 00605 { 00606 init(); 00607 assign(chars, chars_len); 00608 } 00609 00610 00612 // Size operations 00614 00621 size_type size(void) const 00622 { 00623 return d_cplength; 00624 } 00625 00633 size_type length(void) const 00634 { 00635 return d_cplength; 00636 } 00637 00645 bool empty(void) const 00646 { 00647 return (d_cplength == 0); 00648 } 00649 00659 static size_type max_size(void) 00660 { 00661 return (((size_type)-1) / sizeof(utf32)); 00662 } 00663 00665 // Capacity Operations 00667 // return the number of code points the string could hold without re-allocation 00668 // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!) 00677 size_type capacity(void) const 00678 { 00679 return d_reserve - 1; 00680 } 00681 00682 // reserve internal memory for at-least 'num' code-points (characters). if num is 0, request is shrink-to-fit. 00697 void reserve(size_type num = 0) 00698 { 00699 if (num == 0) 00700 trim(); 00701 else 00702 grow(num); 00703 } 00704 00706 // Comparisons 00708 00723 int compare(const String& str) const 00724 { 00725 return compare(0, d_cplength, str); 00726 } 00727 00757 int compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const 00758 { 00759 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 00760 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00761 00762 if ((len == npos) || (idx + len > d_cplength)) 00763 len = d_cplength - idx; 00764 00765 if ((str_len == npos) || (str_idx + str_len > str.d_cplength)) 00766 str_len = str.d_cplength - str_idx; 00767 00768 int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len); 00769 00770 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1; 00771 } 00772 00773 00793 int compare(const std::string& std_str) const 00794 { 00795 return compare(0, d_cplength, std_str); 00796 } 00797 00798 00832 int compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const 00833 { 00834 if (d_cplength < idx) 00835 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00836 00837 if (std_str.size() < str_idx) 00838 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 00839 00840 if ((len == npos) || (idx + len > d_cplength)) 00841 len = d_cplength - idx; 00842 00843 if ((str_len == npos) || (str_idx + str_len > std_str.size())) 00844 str_len = (size_type)std_str.size() - str_idx; 00845 00846 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len); 00847 00848 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1; 00849 } 00850 00851 00873 int compare(const utf8* utf8_str) const 00874 { 00875 return compare(0, d_cplength, utf8_str, encoded_size(utf8_str)); 00876 } 00877 00878 00908 int compare(size_type idx, size_type len, const utf8* utf8_str) const 00909 { 00910 return compare(idx, len, utf8_str, encoded_size(utf8_str)); 00911 } 00912 00946 int compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const 00947 { 00948 if (d_cplength < idx) 00949 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00950 00951 if (str_cplen == npos) 00952 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 00953 00954 if ((len == npos) || (idx + len > d_cplength)) 00955 len = d_cplength - idx; 00956 00957 int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen); 00958 00959 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1; 00960 } 00961 00962 00978 int compare(const char* cstr) const 00979 { 00980 return compare(0, d_cplength, cstr, strlen(cstr)); 00981 } 00982 00983 01007 int compare(size_type idx, size_type len, const char* cstr) const 01008 { 01009 return compare(idx, len, cstr, strlen(cstr)); 01010 } 01011 01012 01040 int compare(size_type idx, size_type len, const char* chars, size_type chars_len) const 01041 { 01042 if (d_cplength < idx) 01043 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01044 01045 if (chars_len == npos) 01046 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 01047 01048 if ((len == npos) || (idx + len > d_cplength)) 01049 len = d_cplength - idx; 01050 01051 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len); 01052 01053 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1; 01054 } 01055 01056 01058 // Character access 01060 01074 reference operator[](size_type idx) 01075 { 01076 return (ptr()[idx]); 01077 } 01078 01093 value_type operator[](size_type idx) const 01094 { 01095 return ptr()[idx]; 01096 } 01097 01110 reference at(size_type idx) 01111 { 01112 if (d_cplength <= idx) 01113 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01114 01115 return ptr()[idx]; 01116 } 01117 01130 const_reference at(size_type idx) const 01131 { 01132 if (d_cplength <= idx) 01133 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01134 01135 return ptr()[idx]; 01136 } 01137 01138 01140 // C-Strings and arrays 01142 01155 const char* c_str(void) const 01156 { 01157 return (const char*)build_utf8_buff(); 01158 } 01159 01173 const utf8* data(void) const 01174 { 01175 return build_utf8_buff(); 01176 } 01177 01182 utf32* ptr(void) 01183 { 01184 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff; 01185 } 01186 01191 const utf32* ptr(void) const 01192 { 01193 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff; 01194 } 01195 01196 // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data 01197 // return number of utf8 code units placed into the buffer 01218 size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const 01219 { 01220 if (d_cplength < idx) 01221 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01222 01223 if (len == npos) 01224 len = d_cplength; 01225 01226 return encode(&ptr()[idx], buf, npos, len); 01227 } 01228 01230 // UTF8 Encoding length information 01232 // return the number of bytes required to hold 'num' code-points, starting at code-point 'idx', of the the string when encoded as utf8 data. 01248 size_type utf8_stream_len(size_type num = npos, size_type idx = 0) const 01249 { 01250 using namespace std; 01251 01252 if (d_cplength < idx) 01253 CEGUI_THROW(out_of_range("Index was out of range for CEGUI::String object")); 01254 01255 size_type maxlen = d_cplength - idx; 01256 01257 return encoded_size(&ptr()[idx], ceguimin(num, maxlen)); 01258 } 01259 01261 // Assignment Functions 01263 01273 String& operator=(const String& str) 01274 { 01275 return assign(str); 01276 } 01277 01296 String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos) 01297 { 01298 if (str.d_cplength < str_idx) 01299 CEGUI_THROW(std::out_of_range("Index was out of range for CEGUI::String object")); 01300 01301 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 01302 str_num = str.d_cplength - str_idx; 01303 01304 grow(str_num); 01305 setlen(str_num); 01306 memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32)); 01307 01308 return *this; 01309 } 01310 01327 String& operator=(const std::string& std_str) 01328 { 01329 return assign(std_str); 01330 } 01331 01355 String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos) 01356 { 01357 if (std_str.size() < str_idx) 01358 CEGUI_THROW(std::out_of_range("Index was out of range for std::string object")); 01359 01360 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 01361 str_num = (size_type)std_str.size() - str_idx; 01362 01363 grow(str_num); 01364 setlen(str_num); 01365 01366 while(str_num--) 01367 { 01368 ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx])); 01369 } 01370 01371 return *this; 01372 } 01373 01392 String& operator=(const utf8* utf8_str) 01393 { 01394 return assign(utf8_str, utf_length(utf8_str)); 01395 } 01396 01415 String& assign(const utf8* utf8_str) 01416 { 01417 return assign(utf8_str, utf_length(utf8_str)); 01418 } 01419 01441 String& assign(const utf8* utf8_str, size_type str_num) 01442 { 01443 if (str_num == npos) 01444 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 01445 01446 size_type enc_sze = encoded_size(utf8_str, str_num); 01447 01448 grow(enc_sze); 01449 encode(utf8_str, ptr(), d_reserve, str_num); 01450 setlen(enc_sze); 01451 return *this; 01452 } 01453 01464 String& operator=(utf32 code_point) 01465 { 01466 return assign(1, code_point); 01467 } 01468 01484 String& assign(size_type num, utf32 code_point) 01485 { 01486 if (num == npos) 01487 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 01488 01489 grow(num); 01490 setlen(num); 01491 utf32* p = ptr(); 01492 01493 while(num--) 01494 *p++ = code_point; 01495 01496 return *this; 01497 } 01498 01499 01512 String& operator=(const char* cstr) 01513 { 01514 return assign(cstr, strlen(cstr)); 01515 } 01516 01517 01530 String& assign(const char* cstr) 01531 { 01532 return assign(cstr, strlen(cstr)); 01533 } 01534 01535 01551 String& assign(const char* chars, size_type chars_len) 01552 { 01553 grow(chars_len); 01554 utf32* pt = ptr(); 01555 01556 for (size_type i = 0; i < chars_len; ++i) 01557 { 01558 *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++)); 01559 } 01560 01561 setlen(chars_len); 01562 return *this; 01563 } 01564 01565 01576 void swap(String& str) 01577 { 01578 size_type temp_len = d_cplength; 01579 d_cplength = str.d_cplength; 01580 str.d_cplength = temp_len; 01581 01582 size_type temp_res = d_reserve; 01583 d_reserve = str.d_reserve; 01584 str.d_reserve = temp_res; 01585 01586 utf32* temp_buf = d_buffer; 01587 d_buffer = str.d_buffer; 01588 str.d_buffer = temp_buf; 01589 01590 // see if we need to swap 'quick buffer' data 01591 if (temp_res <= STR_QUICKBUFF_SIZE) 01592 { 01593 utf32 temp_qbf[STR_QUICKBUFF_SIZE]; 01594 01595 memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32)); 01596 memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32)); 01597 memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32)); 01598 } 01599 01600 } 01601 01603 // Appending Functions 01605 01617 String& operator+=(const String& str) 01618 { 01619 return append(str); 01620 } 01621 01641 String& append(const String& str, size_type str_idx = 0, size_type str_num = npos) 01642 { 01643 if (str.d_cplength < str_idx) 01644 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01645 01646 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 01647 str_num = str.d_cplength - str_idx; 01648 01649 grow(d_cplength + str_num); 01650 memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32)); 01651 setlen(d_cplength + str_num); 01652 return *this; 01653 } 01654 01655 01672 String& operator+=(const std::string& std_str) 01673 { 01674 return append(std_str); 01675 } 01676 01700 String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos) 01701 { 01702 if (std_str.size() < str_idx) 01703 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 01704 01705 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 01706 str_num = (size_type)std_str.size() - str_idx; 01707 01708 size_type newsze = d_cplength + str_num; 01709 01710 grow(newsze); 01711 utf32* pt = &ptr()[newsze-1]; 01712 01713 while(str_num--) 01714 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num])); 01715 01716 setlen(newsze); 01717 return *this; 01718 } 01719 01720 01739 String& operator+=(const utf8* utf8_str) 01740 { 01741 return append(utf8_str, utf_length(utf8_str)); 01742 } 01743 01762 String& append(const utf8* utf8_str) 01763 { 01764 return append(utf8_str, utf_length(utf8_str)); 01765 } 01766 01767 01789 String& append(const utf8* utf8_str, size_type len) 01790 { 01791 if (len == npos) 01792 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 01793 01794 size_type encsz = encoded_size(utf8_str, len); 01795 size_type newsz = d_cplength + encsz; 01796 01797 grow(newsz); 01798 encode(utf8_str, &ptr()[d_cplength], encsz, len); 01799 setlen(newsz); 01800 01801 return *this; 01802 } 01803 01804 01817 String& operator+=(utf32 code_point) 01818 { 01819 return append(1, code_point); 01820 } 01821 01837 String& append(size_type num, utf32 code_point) 01838 { 01839 if (num == npos) 01840 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 01841 01842 size_type newsz = d_cplength + num; 01843 grow(newsz); 01844 01845 utf32* p = &ptr()[d_cplength]; 01846 01847 while(num--) 01848 *p++ = code_point; 01849 01850 setlen(newsz); 01851 01852 return *this; 01853 } 01854 01867 void push_back(utf32 code_point) 01868 { 01869 append(1, code_point); 01870 } 01871 01887 String& append(const_iterator iter_beg, const_iterator iter_end) 01888 { 01889 return replace(end(), end(), iter_beg, iter_end); 01890 } 01891 01892 01905 String& operator+=(const char* cstr) 01906 { 01907 return append(cstr, strlen(cstr)); 01908 } 01909 01910 01923 String& append(const char* cstr) 01924 { 01925 return append(cstr, strlen(cstr)); 01926 } 01927 01928 01944 String& append(const char* chars, size_type chars_len) 01945 { 01946 if (chars_len == npos) 01947 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 01948 01949 size_type newsz = d_cplength + chars_len; 01950 01951 grow(newsz); 01952 01953 utf32* pt = &ptr()[newsz-1]; 01954 01955 while(chars_len--) 01956 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 01957 01958 setlen(newsz); 01959 01960 return *this; 01961 } 01962 01963 01965 // Insertion Functions 01967 01983 String& insert(size_type idx, const String& str) 01984 { 01985 return insert(idx, str, 0, npos); 01986 } 01987 02010 String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num) 02011 { 02012 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 02013 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02014 02015 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 02016 str_num = str.d_cplength - str_idx; 02017 02018 size_type newsz = d_cplength + str_num; 02019 grow(newsz); 02020 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02021 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32)); 02022 setlen(newsz); 02023 02024 return *this; 02025 } 02026 02047 String& insert(size_type idx, const std::string& std_str) 02048 { 02049 return insert(idx, std_str, 0, npos); 02050 } 02051 02078 String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num) 02079 { 02080 if (d_cplength < idx) 02081 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02082 02083 if (std_str.size() < str_idx) 02084 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 02085 02086 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 02087 str_num = (size_type)std_str.size() - str_idx; 02088 02089 size_type newsz = d_cplength + str_num; 02090 grow(newsz); 02091 02092 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02093 02094 utf32* pt = &ptr()[idx + str_num - 1]; 02095 02096 while(str_num--) 02097 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num])); 02098 02099 setlen(newsz); 02100 02101 return *this; 02102 } 02103 02126 String& insert(size_type idx, const utf8* utf8_str) 02127 { 02128 return insert(idx, utf8_str, utf_length(utf8_str)); 02129 } 02130 02156 String& insert(size_type idx, const utf8* utf8_str, size_type len) 02157 { 02158 if (d_cplength < idx) 02159 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02160 02161 if (len == npos) 02162 CEGUI_THROW(std::length_error("Length of utf8 encoded string can not be 'npos'")); 02163 02164 size_type encsz = encoded_size(utf8_str, len); 02165 size_type newsz = d_cplength + encsz; 02166 02167 grow(newsz); 02168 memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02169 encode(utf8_str, &ptr()[idx], encsz, len); 02170 setlen(newsz); 02171 02172 return *this; 02173 } 02174 02194 String& insert(size_type idx, size_type num, utf32 code_point) 02195 { 02196 if (d_cplength < idx) 02197 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02198 02199 if (num == npos) 02200 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 02201 02202 size_type newsz = d_cplength + num; 02203 grow(newsz); 02204 02205 memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02206 02207 utf32* pt = &ptr()[idx + num - 1]; 02208 02209 while(num--) 02210 *pt-- = code_point; 02211 02212 setlen(newsz); 02213 02214 return *this; 02215 } 02216 02235 void insert(iterator pos, size_type num, utf32 code_point) 02236 { 02237 insert(safe_iter_dif(pos, begin()), num, code_point); 02238 } 02239 02255 iterator insert(iterator pos, utf32 code_point) 02256 { 02257 insert(pos, 1, code_point); 02258 return pos; 02259 } 02260 02279 void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end) 02280 { 02281 replace(iter_pos, iter_pos, iter_beg, iter_end); 02282 } 02283 02284 02301 String& insert(size_type idx, const char* cstr) 02302 { 02303 return insert(idx, cstr, strlen(cstr)); 02304 } 02305 02306 02326 String& insert(size_type idx, const char* chars, size_type chars_len) 02327 { 02328 if (d_cplength < idx) 02329 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02330 02331 if (chars_len == npos) 02332 CEGUI_THROW(std::length_error("Length of char array can not be 'npos'")); 02333 02334 size_type newsz = d_cplength + chars_len; 02335 02336 grow(newsz); 02337 memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02338 02339 utf32* pt = &ptr()[idx + chars_len - 1]; 02340 02341 while(chars_len--) 02342 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 02343 02344 setlen(newsz); 02345 02346 return *this; 02347 } 02348 02349 02351 // Erasing characters 02353 02360 void clear(void) 02361 { 02362 setlen(0); 02363 trim(); 02364 } 02365 02373 String& erase(void) 02374 { 02375 clear(); 02376 return *this; 02377 } 02378 02391 String& erase(size_type idx) 02392 { 02393 return erase(idx, 1); 02394 } 02395 02411 String& erase(size_type idx, size_type len) 02412 { 02413 // cover the no-op case. 02414 if (len == 0) 02415 return *this; 02416 02417 if (d_cplength <= idx) 02418 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02419 02420 if (len == npos) 02421 len = d_cplength - idx; 02422 02423 size_type newsz = d_cplength - len; 02424 02425 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32)); 02426 setlen(newsz); 02427 return *this; 02428 } 02429 02440 String& erase(iterator pos) 02441 { 02442 return erase(safe_iter_dif(pos, begin()), 1); 02443 } 02444 02458 String& erase(iterator iter_beg, iterator iter_end) 02459 { 02460 return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg)); 02461 } 02462 02464 // Resizing 02466 02478 void resize(size_type num) 02479 { 02480 resize(num, utf32()); 02481 } 02482 02498 void resize(size_type num, utf32 code_point) 02499 { 02500 if (num < d_cplength) 02501 { 02502 setlen(num); 02503 } 02504 else 02505 { 02506 append(num - d_cplength, code_point); 02507 } 02508 02509 } 02510 02512 // Replacing Characters 02514 02533 String& replace(size_type idx, size_type len, const String& str) 02534 { 02535 return replace(idx, len, str, 0, npos); 02536 } 02537 02559 String& replace(iterator iter_beg, iterator iter_end, const String& str) 02560 { 02561 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos); 02562 } 02563 02589 String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num) 02590 { 02591 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 02592 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02593 02594 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos)) 02595 str_num = str.d_cplength - str_idx; 02596 02597 if (((len + idx) > d_cplength) || (len == npos)) 02598 len = d_cplength - idx; 02599 02600 size_type newsz = d_cplength + str_num - len; 02601 02602 grow(newsz); 02603 02604 if ((idx + len) < d_cplength) 02605 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02606 02607 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32)); 02608 setlen(newsz); 02609 02610 return *this; 02611 } 02612 02613 02637 String& replace(size_type idx, size_type len, const std::string& std_str) 02638 { 02639 return replace(idx, len, std_str, 0, npos); 02640 } 02641 02667 String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str) 02668 { 02669 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos); 02670 } 02671 02701 String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num) 02702 { 02703 if (d_cplength < idx) 02704 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02705 02706 if (std_str.size() < str_idx) 02707 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 02708 02709 if (((str_idx + str_num) > std_str.size()) || (str_num == npos)) 02710 str_num = (size_type)std_str.size() - str_idx; 02711 02712 if (((len + idx) > d_cplength) || (len == npos)) 02713 len = d_cplength - idx; 02714 02715 size_type newsz = d_cplength + str_num - len; 02716 02717 grow(newsz); 02718 02719 if ((idx + len) < d_cplength) 02720 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02721 02722 utf32* pt = &ptr()[idx + str_num - 1]; 02723 02724 while (str_num--) 02725 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num])); 02726 02727 setlen(newsz); 02728 02729 return *this; 02730 } 02731 02732 02758 String& replace(size_type idx, size_type len, const utf8* utf8_str) 02759 { 02760 return replace(idx, len, utf8_str, utf_length(utf8_str)); 02761 } 02762 02790 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str) 02791 { 02792 return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str)); 02793 } 02794 02823 String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len) 02824 { 02825 if (d_cplength < idx) 02826 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02827 02828 if (str_len == npos) 02829 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 02830 02831 if (((len + idx) > d_cplength) || (len == npos)) 02832 len = d_cplength - idx; 02833 02834 size_type encsz = encoded_size(utf8_str, str_len); 02835 size_type newsz = d_cplength + encsz - len; 02836 02837 grow(newsz); 02838 02839 if ((idx + len) < d_cplength) 02840 memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02841 02842 encode(utf8_str, &ptr()[idx], encsz, str_len); 02843 02844 setlen(newsz); 02845 return *this; 02846 } 02847 02878 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len) 02879 { 02880 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len); 02881 } 02882 02905 String& replace(size_type idx, size_type len, size_type num, utf32 code_point) 02906 { 02907 if (d_cplength < idx) 02908 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02909 02910 if (num == npos) 02911 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 02912 02913 if (((len + idx) > d_cplength) || (len == npos)) 02914 len = d_cplength - idx; 02915 02916 size_type newsz = d_cplength + num - len; 02917 02918 grow(newsz); 02919 02920 if ((idx + len) < d_cplength) 02921 memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02922 02923 utf32* pt = &ptr()[idx + num - 1]; 02924 02925 while (num--) 02926 *pt-- = code_point; 02927 02928 setlen(newsz); 02929 02930 return *this; 02931 } 02932 02957 String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point) 02958 { 02959 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point); 02960 } 02961 02962 02987 String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd) 02988 { 02989 if (iter_newBeg == iter_newEnd) 02990 { 02991 erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg)); 02992 } 02993 else 02994 { 02995 size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg); 02996 size_type idx = safe_iter_dif(iter_beg, begin()); 02997 size_type len = safe_iter_dif(iter_end, iter_beg); 02998 02999 if ((len + idx) > d_cplength) 03000 len = d_cplength - idx; 03001 03002 size_type newsz = d_cplength + str_len - len; 03003 03004 grow(newsz); 03005 03006 if ((idx + len) < d_cplength) 03007 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 03008 03009 memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32)); 03010 setlen(newsz); 03011 } 03012 03013 return *this; 03014 } 03015 03016 03036 String& replace(size_type idx, size_type len, const char* cstr) 03037 { 03038 return replace(idx, len, cstr, strlen(cstr)); 03039 } 03040 03041 03063 String& replace(iterator iter_beg, iterator iter_end, const char* cstr) 03064 { 03065 return replace(iter_beg, iter_end, cstr, strlen(cstr)); 03066 } 03067 03068 03091 String& replace(size_type idx, size_type len, const char* chars, size_type chars_len) 03092 { 03093 if (d_cplength < idx) 03094 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 03095 03096 if (chars_len == npos) 03097 CEGUI_THROW(std::length_error("Length for the char array can not be 'npos'")); 03098 03099 if (((len + idx) > d_cplength) || (len == npos)) 03100 len = d_cplength - idx; 03101 03102 size_type newsz = d_cplength + chars_len - len; 03103 03104 grow(newsz); 03105 03106 if ((idx + len) < d_cplength) 03107 memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 03108 03109 utf32* pt = &ptr()[idx + chars_len - 1]; 03110 03111 while (chars_len--) 03112 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 03113 03114 setlen(newsz); 03115 return *this; 03116 } 03117 03118 03143 String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len) 03144 { 03145 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len); 03146 } 03147 03148 03150 // Find a code point 03152 03166 size_type find(utf32 code_point, size_type idx = 0) const 03167 { 03168 if (idx < d_cplength) 03169 { 03170 const utf32* pt = &ptr()[idx]; 03171 03172 while (idx < d_cplength) 03173 { 03174 if (*pt++ == code_point) 03175 return idx; 03176 03177 ++idx; 03178 } 03179 03180 } 03181 03182 return npos; 03183 } 03184 03199 size_type rfind(utf32 code_point, size_type idx = npos) const 03200 { 03201 if (idx >= d_cplength) 03202 idx = d_cplength - 1; 03203 03204 if (d_cplength > 0) 03205 { 03206 const utf32* pt = &ptr()[idx]; 03207 03208 do 03209 { 03210 if (*pt-- == code_point) 03211 return idx; 03212 03213 } while (idx-- != 0); 03214 03215 } 03216 03217 return npos; 03218 } 03219 03221 // Find a substring 03223 03237 size_type find(const String& str, size_type idx = 0) const 03238 { 03239 if ((str.d_cplength == 0) && (idx < d_cplength)) 03240 return idx; 03241 03242 if (idx < d_cplength) 03243 { 03244 // loop while search string could fit in to search area 03245 while (d_cplength - idx >= str.d_cplength) 03246 { 03247 if (0 == compare(idx, str.d_cplength, str)) 03248 return idx; 03249 03250 ++idx; 03251 } 03252 03253 } 03254 03255 return npos; 03256 } 03257 03272 size_type rfind(const String& str, size_type idx = npos) const 03273 { 03274 if (str.d_cplength == 0) 03275 return (idx < d_cplength) ? idx : d_cplength; 03276 03277 if (str.d_cplength <= d_cplength) 03278 { 03279 if (idx > (d_cplength - str.d_cplength)) 03280 idx = d_cplength - str.d_cplength; 03281 03282 do 03283 { 03284 if (0 == compare(idx, str.d_cplength, str)) 03285 return idx; 03286 03287 } while (idx-- != 0); 03288 03289 } 03290 03291 return npos; 03292 } 03293 03312 size_type find(const std::string& std_str, size_type idx = 0) const 03313 { 03314 std::string::size_type sze = std_str.size(); 03315 03316 if ((sze == 0) && (idx < d_cplength)) 03317 return idx; 03318 03319 if (idx < d_cplength) 03320 { 03321 // loop while search string could fit in to search area 03322 while (d_cplength - idx >= sze) 03323 { 03324 if (0 == compare(idx, (size_type)sze, std_str)) 03325 return idx; 03326 03327 ++idx; 03328 } 03329 03330 } 03331 03332 return npos; 03333 } 03334 03353 size_type rfind(const std::string& std_str, size_type idx = npos) const 03354 { 03355 std::string::size_type sze = std_str.size(); 03356 03357 if (sze == 0) 03358 return (idx < d_cplength) ? idx : d_cplength; 03359 03360 if (sze <= d_cplength) 03361 { 03362 if (idx > (d_cplength - sze)) 03363 idx = d_cplength - sze; 03364 03365 do 03366 { 03367 if (0 == compare(idx, (size_type)sze, std_str)) 03368 return idx; 03369 03370 } while (idx-- != 0); 03371 03372 } 03373 03374 return npos; 03375 } 03376 03399 size_type find(const utf8* utf8_str, size_type idx = 0) const 03400 { 03401 return find(utf8_str, idx, utf_length(utf8_str)); 03402 } 03403 03426 size_type rfind(const utf8* utf8_str, size_type idx = npos) const 03427 { 03428 return rfind(utf8_str, idx, utf_length(utf8_str)); 03429 } 03430 03456 size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const 03457 { 03458 if (str_len == npos) 03459 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03460 03461 size_type sze = encoded_size(utf8_str, str_len); 03462 03463 if ((sze == 0) && (idx < d_cplength)) 03464 return idx; 03465 03466 if (idx < d_cplength) 03467 { 03468 // loop while search string could fit in to search area 03469 while (d_cplength - idx >= sze) 03470 { 03471 if (0 == compare(idx, sze, utf8_str, sze)) 03472 return idx; 03473 03474 ++idx; 03475 } 03476 03477 } 03478 03479 return npos; 03480 } 03481 03507 size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const 03508 { 03509 if (str_len == npos) 03510 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03511 03512 size_type sze = encoded_size(utf8_str, str_len); 03513 03514 if (sze == 0) 03515 return (idx < d_cplength) ? idx : d_cplength; 03516 03517 if (sze <= d_cplength) 03518 { 03519 if (idx > (d_cplength - sze)) 03520 idx = d_cplength - sze; 03521 03522 do 03523 { 03524 if (0 == compare(idx, sze, utf8_str, sze)) 03525 return idx; 03526 03527 } while (idx-- != 0); 03528 03529 } 03530 03531 return npos; 03532 } 03533 03534 03551 size_type find(const char* cstr, size_type idx = 0) const 03552 { 03553 return find(cstr, idx, strlen(cstr)); 03554 } 03555 03556 03573 size_type rfind(const char* cstr, size_type idx = npos) const 03574 { 03575 return rfind(cstr, idx, strlen(cstr)); 03576 } 03577 03578 03598 size_type find(const char* chars, size_type idx, size_type chars_len) const 03599 { 03600 if (chars_len == npos) 03601 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 03602 03603 if ((chars_len == 0) && (idx < d_cplength)) 03604 return idx; 03605 03606 if (idx < d_cplength) 03607 { 03608 // loop while search string could fit in to search area 03609 while (d_cplength - idx >= chars_len) 03610 { 03611 if (0 == compare(idx, chars_len, chars, chars_len)) 03612 return idx; 03613 03614 ++idx; 03615 } 03616 03617 } 03618 03619 return npos; 03620 } 03621 03622 03642 size_type rfind(const char* chars, size_type idx, size_type chars_len) const 03643 { 03644 if (chars_len == npos) 03645 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 03646 03647 if (chars_len == 0) 03648 return (idx < d_cplength) ? idx : d_cplength; 03649 03650 if (chars_len <= d_cplength) 03651 { 03652 if (idx > (d_cplength - chars_len)) 03653 idx = d_cplength - chars_len; 03654 03655 do 03656 { 03657 if (0 == compare(idx, chars_len, chars, chars_len)) 03658 return idx; 03659 03660 } while (idx-- != 0); 03661 03662 } 03663 03664 return npos; 03665 } 03666 03667 03669 // Find first of different code-points 03671 03685 size_type find_first_of(const String& str, size_type idx = 0) const 03686 { 03687 if (idx < d_cplength) 03688 { 03689 const utf32* pt = &ptr()[idx]; 03690 03691 do 03692 { 03693 if (npos != str.find(*pt++)) 03694 return idx; 03695 03696 } while (++idx != d_cplength); 03697 03698 } 03699 03700 return npos; 03701 } 03702 03717 size_type find_first_not_of(const String& str, size_type idx = 0) const 03718 { 03719 if (idx < d_cplength) 03720 { 03721 const utf32* pt = &ptr()[idx]; 03722 03723 do 03724 { 03725 if (npos == str.find(*pt++)) 03726 return idx; 03727 03728 } while (++idx != d_cplength); 03729 03730 } 03731 03732 return npos; 03733 } 03734 03735 03754 size_type find_first_of(const std::string& std_str, size_type idx = 0) const 03755 { 03756 if (idx < d_cplength) 03757 { 03758 const utf32* pt = &ptr()[idx]; 03759 03760 do 03761 { 03762 if (npos != find_codepoint(std_str, *pt++)) 03763 return idx; 03764 03765 } while (++idx != d_cplength); 03766 03767 } 03768 03769 return npos; 03770 } 03771 03790 size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const 03791 { 03792 if (idx < d_cplength) 03793 { 03794 const utf32* pt = &ptr()[idx]; 03795 03796 do 03797 { 03798 if (npos == find_codepoint(std_str, *pt++)) 03799 return idx; 03800 03801 } while (++idx != d_cplength); 03802 03803 } 03804 03805 return npos; 03806 } 03807 03808 03831 size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const 03832 { 03833 return find_first_of(utf8_str, idx, utf_length(utf8_str)); 03834 } 03835 03858 size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const 03859 { 03860 return find_first_not_of(utf8_str, idx, utf_length(utf8_str)); 03861 } 03862 03888 size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const 03889 { 03890 if (str_len == npos) 03891 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03892 03893 if (idx < d_cplength) 03894 { 03895 size_type encsze = encoded_size(utf8_str, str_len); 03896 03897 const utf32* pt = &ptr()[idx]; 03898 03899 do 03900 { 03901 if (npos != find_codepoint(utf8_str, encsze, *pt++)) 03902 return idx; 03903 03904 } while (++idx != d_cplength); 03905 03906 } 03907 03908 return npos; 03909 } 03910 03936 size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const 03937 { 03938 if (str_len == npos) 03939 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03940 03941 if (idx < d_cplength) 03942 { 03943 size_type encsze = encoded_size(utf8_str, str_len); 03944 03945 const utf32* pt = &ptr()[idx]; 03946 03947 do 03948 { 03949 if (npos == find_codepoint(utf8_str, encsze, *pt++)) 03950 return idx; 03951 03952 } while (++idx != d_cplength); 03953 03954 } 03955 03956 return npos; 03957 } 03958 03959 03974 size_type find_first_of(utf32 code_point, size_type idx = 0) const 03975 { 03976 return find(code_point, idx); 03977 } 03978 03995 size_type find_first_not_of(utf32 code_point, size_type idx = 0) const 03996 { 03997 if (idx < d_cplength) 03998 { 03999 do 04000 { 04001 if ((*this)[idx] != code_point) 04002 return idx; 04003 04004 } while(idx++ < d_cplength); 04005 04006 } 04007 04008 return npos; 04009 } 04010 04011 04028 size_type find_first_of(const char* cstr, size_type idx = 0) const 04029 { 04030 return find_first_of(cstr, idx, strlen(cstr)); 04031 } 04032 04033 04050 size_type find_first_not_of(const char* cstr, size_type idx = 0) const 04051 { 04052 return find_first_not_of(cstr, idx, strlen(cstr)); 04053 } 04054 04055 04075 size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const 04076 { 04077 if (chars_len == npos) 04078 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04079 04080 if (idx < d_cplength) 04081 { 04082 const utf32* pt = &ptr()[idx]; 04083 04084 do 04085 { 04086 if (npos != find_codepoint(chars, chars_len, *pt++)) 04087 return idx; 04088 04089 } while (++idx != d_cplength); 04090 04091 } 04092 04093 return npos; 04094 } 04095 04096 04116 size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const 04117 { 04118 if (chars_len == npos) 04119 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04120 04121 if (idx < d_cplength) 04122 { 04123 const utf32* pt = &ptr()[idx]; 04124 04125 do 04126 { 04127 if (npos == find_codepoint(chars, chars_len, *pt++)) 04128 return idx; 04129 04130 } while (++idx != d_cplength); 04131 04132 } 04133 04134 return npos; 04135 } 04136 04137 04139 // Find last of different code-points 04141 04155 size_type find_last_of(const String& str, size_type idx = npos) const 04156 { 04157 if (d_cplength > 0) 04158 { 04159 if (idx >= d_cplength) 04160 idx = d_cplength - 1; 04161 04162 const utf32* pt = &ptr()[idx]; 04163 04164 do 04165 { 04166 if (npos != str.find(*pt--)) 04167 return idx; 04168 04169 } while (idx-- != 0); 04170 04171 } 04172 04173 return npos; 04174 } 04175 04190 size_type find_last_not_of(const String& str, size_type idx = npos) const 04191 { 04192 if (d_cplength > 0) 04193 { 04194 if (idx >= d_cplength) 04195 idx = d_cplength - 1; 04196 04197 const utf32* pt = &ptr()[idx]; 04198 04199 do 04200 { 04201 if (npos == str.find(*pt--)) 04202 return idx; 04203 04204 } while (idx-- != 0); 04205 04206 } 04207 04208 return npos; 04209 } 04210 04211 04230 size_type find_last_of(const std::string& std_str, size_type idx = npos) const 04231 { 04232 if (d_cplength > 0) 04233 { 04234 if (idx >= d_cplength) 04235 idx = d_cplength - 1; 04236 04237 const utf32* pt = &ptr()[idx]; 04238 04239 do 04240 { 04241 if (npos != find_codepoint(std_str, *pt--)) 04242 return idx; 04243 04244 } while (idx-- != 0); 04245 04246 } 04247 04248 return npos; 04249 } 04250 04269 size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const 04270 { 04271 if (d_cplength > 0) 04272 { 04273 if (idx >= d_cplength) 04274 idx = d_cplength - 1; 04275 04276 const utf32* pt = &ptr()[idx]; 04277 04278 do 04279 { 04280 if (npos == find_codepoint(std_str, *pt--)) 04281 return idx; 04282 04283 } while (idx-- != 0); 04284 04285 } 04286 04287 return npos; 04288 } 04289 04290 04313 size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const 04314 { 04315 return find_last_of(utf8_str, idx, utf_length(utf8_str)); 04316 } 04317 04340 size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const 04341 { 04342 return find_last_not_of(utf8_str, idx, utf_length(utf8_str)); 04343 } 04344 04370 size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const 04371 { 04372 if (str_len == npos) 04373 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 04374 04375 if (d_cplength > 0) 04376 { 04377 if (idx >= d_cplength) 04378 idx = d_cplength - 1; 04379 04380 size_type encsze = encoded_size(utf8_str, str_len); 04381 04382 const utf32* pt = &ptr()[idx]; 04383 04384 do 04385 { 04386 if (npos != find_codepoint(utf8_str, encsze, *pt--)) 04387 return idx; 04388 04389 } while (idx-- != 0); 04390 04391 } 04392 04393 return npos; 04394 } 04395 04421 size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const 04422 { 04423 if (str_len == npos) 04424 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 04425 04426 if (d_cplength > 0) 04427 { 04428 if (idx >= d_cplength) 04429 idx = d_cplength - 1; 04430 04431 size_type encsze = encoded_size(utf8_str, str_len); 04432 04433 const utf32* pt = &ptr()[idx]; 04434 04435 do 04436 { 04437 if (npos == find_codepoint(utf8_str, encsze, *pt--)) 04438 return idx; 04439 04440 } while (idx-- != 0); 04441 04442 } 04443 04444 return npos; 04445 } 04446 04447 04462 size_type find_last_of(utf32 code_point, size_type idx = npos) const 04463 { 04464 return rfind(code_point, idx); 04465 } 04466 04481 size_type find_last_not_of(utf32 code_point, size_type idx = npos) const 04482 { 04483 if (d_cplength > 0) 04484 { 04485 if (idx >= d_cplength) 04486 idx = d_cplength - 1; 04487 04488 do 04489 { 04490 if ((*this)[idx] != code_point) 04491 return idx; 04492 04493 } while(idx-- != 0); 04494 04495 } 04496 04497 return npos; 04498 } 04499 04500 04517 size_type find_last_of(const char* cstr, size_type idx = npos) const 04518 { 04519 return find_last_of(cstr, idx, strlen(cstr)); 04520 } 04521 04522 04539 size_type find_last_not_of(const char* cstr, size_type idx = npos) const 04540 { 04541 return find_last_not_of(cstr, idx, strlen(cstr)); 04542 } 04543 04544 04564 size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const 04565 { 04566 if (chars_len == npos) 04567 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04568 04569 if (d_cplength > 0) 04570 { 04571 if (idx >= d_cplength) 04572 idx = d_cplength - 1; 04573 04574 const utf32* pt = &ptr()[idx]; 04575 04576 do 04577 { 04578 if (npos != find_codepoint(chars, chars_len, *pt--)) 04579 return idx; 04580 04581 } while (idx-- != 0); 04582 04583 } 04584 04585 return npos; 04586 } 04587 04588 04608 size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const 04609 { 04610 if (chars_len == npos) 04611 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04612 04613 if (d_cplength > 0) 04614 { 04615 if (idx >= d_cplength) 04616 idx = d_cplength - 1; 04617 04618 const utf32* pt = &ptr()[idx]; 04619 04620 do 04621 { 04622 if (npos == find_codepoint(chars, chars_len, *pt--)) 04623 return idx; 04624 04625 } while (idx-- != 0); 04626 04627 } 04628 04629 return npos; 04630 } 04631 04632 04634 // Substring 04636 04651 String substr(size_type idx = 0, size_type len = npos) const 04652 { 04653 if (d_cplength < idx) 04654 CEGUI_THROW(std::out_of_range("Index is out of range for this CEGUI::String")); 04655 04656 return String(*this, idx, len); 04657 } 04658 04660 // Iterator creation 04662 04669 iterator begin(void) 04670 { 04671 return iterator(ptr()); 04672 } 04673 04681 const_iterator begin(void) const 04682 { 04683 return const_iterator(ptr()); 04684 } 04685 04693 iterator end(void) 04694 { 04695 return iterator(&ptr()[d_cplength]); 04696 } 04697 04705 const_iterator end(void) const 04706 { 04707 return const_iterator(&ptr()[d_cplength]); 04708 } 04709 04717 reverse_iterator rbegin(void) 04718 { 04719 return reverse_iterator(end()); 04720 } 04721 04729 const_reverse_iterator rbegin(void) const 04730 { 04731 return const_reverse_iterator(end()); 04732 } 04733 04741 reverse_iterator rend(void) 04742 { 04743 return reverse_iterator(begin()); 04744 } 04745 04753 const_reverse_iterator rend(void) const 04754 { 04755 return const_reverse_iterator(begin()); 04756 } 04757 04758 private: 04759 /************************************************************************* 04760 Implementation Functions 04761 *************************************************************************/ 04762 // string management 04763 04764 // change size of allocated buffer so it is at least 'new_size'. 04765 // May or may not cause re-allocation and copy of buffer if size is larger 04766 // will never re-allocate to make size smaller. (see trim()) 04767 bool grow(size_type new_size); 04768 04769 // perform re-allocation to remove wasted space. 04770 void trim(void); 04771 04772 // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first). 04773 void setlen(size_type len) 04774 { 04775 d_cplength = len; 04776 ptr()[len] = (utf32)(0); 04777 } 04778 04779 // initialise string object 04780 void init(void) 04781 { 04782 d_reserve = STR_QUICKBUFF_SIZE; 04783 d_encodedbuff = 0; 04784 d_encodedbufflen = 0; 04785 d_encodeddatlen = 0; 04786 d_buffer = 0; 04787 setlen(0); 04788 } 04789 04790 // return true if the given pointer is inside the string data 04791 bool inside(utf32* inptr) 04792 { 04793 if (inptr < ptr() || ptr() + d_cplength <= inptr) 04794 return false; 04795 else 04796 return true; 04797 } 04798 04799 // compute distance between two iterators, returning a 'safe' value 04800 size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const 04801 { 04802 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2); 04803 } 04804 04805 // encoding functions 04806 // for all: 04807 // src_len is in code units, or 0 for null terminated string. 04808 // dest_len is in code units. 04809 // returns number of code units put into dest buffer. 04810 size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const 04811 { 04812 // count length for null terminated source... 04813 if (src_len == 0) 04814 { 04815 src_len = utf_length(src); 04816 } 04817 04818 size_type destCapacity = dest_len; 04819 04820 // while there is data in the source buffer, 04821 for (uint idx = 0; idx < src_len; ++idx) 04822 { 04823 utf32 cp = src[idx]; 04824 04825 // check there is enough destination buffer to receive this encoded unit (exit loop & return if not) 04826 if (destCapacity < encoded_size(cp)) 04827 { 04828 break; 04829 } 04830 04831 if (cp < 0x80) 04832 { 04833 *dest++ = (utf8)cp; 04834 --destCapacity; 04835 } 04836 else if (cp < 0x0800) 04837 { 04838 *dest++ = (utf8)((cp >> 6) | 0xC0); 04839 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04840 destCapacity -= 2; 04841 } 04842 else if (cp < 0x10000) 04843 { 04844 *dest++ = (utf8)((cp >> 12) | 0xE0); 04845 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80); 04846 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04847 destCapacity -= 3; 04848 } 04849 else 04850 { 04851 *dest++ = (utf8)((cp >> 18) | 0xF0); 04852 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80); 04853 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80); 04854 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04855 destCapacity -= 4; 04856 } 04857 04858 } 04859 04860 return dest_len - destCapacity; 04861 } 04862 04863 size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const 04864 { 04865 // count length for null terminated source... 04866 if (src_len == 0) 04867 { 04868 src_len = utf_length(src); 04869 } 04870 04871 size_type destCapacity = dest_len; 04872 04873 // while there is data in the source buffer, and space in the dest buffer 04874 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));) 04875 { 04876 utf32 cp; 04877 utf8 cu = src[idx++]; 04878 04879 if (cu < 0x80) 04880 { 04881 cp = (utf32)(cu); 04882 } 04883 else if (cu < 0xE0) 04884 { 04885 cp = ((cu & 0x1F) << 6); 04886 cp |= (src[idx++] & 0x3F); 04887 } 04888 else if (cu < 0xF0) 04889 { 04890 cp = ((cu & 0x0F) << 12); 04891 cp |= ((src[idx++] & 0x3F) << 6); 04892 cp |= (src[idx++] & 0x3F); 04893 } 04894 else 04895 { 04896 cp = ((cu & 0x07) << 18); 04897 cp |= ((src[idx++] & 0x3F) << 12); 04898 cp |= ((src[idx++] & 0x3F) << 6); 04899 cp |= (src[idx++] & 0x3F); 04900 } 04901 04902 *dest++ = cp; 04903 --destCapacity; 04904 } 04905 04906 return dest_len - destCapacity; 04907 } 04908 04909 // return the number of utf8 code units required to encode the given utf32 code point 04910 size_type encoded_size(utf32 code_point) const 04911 { 04912 if (code_point < 0x80) 04913 return 1; 04914 else if (code_point < 0x0800) 04915 return 2; 04916 else if (code_point < 0x10000) 04917 return 3; 04918 else 04919 return 4; 04920 } 04921 04922 // return number of code units required to re-encode given null-terminated utf32 data as utf8. return does not include terminating null. 04923 size_type encoded_size(const utf32* buf) const 04924 { 04925 return encoded_size(buf, utf_length(buf)); 04926 } 04927 04928 // return number of code units required to re-encode given utf32 data as utf8. len is number of code units in 'buf'. 04929 size_type encoded_size(const utf32* buf, size_type len) const 04930 { 04931 size_type count = 0; 04932 04933 while (len--) 04934 { 04935 count += encoded_size(*buf++); 04936 } 04937 04938 return count; 04939 } 04940 04941 // return number of utf32 code units required to re-encode given utf8 data as utf32. return does not include terminating null. 04942 size_type encoded_size(const utf8* buf) const 04943 { 04944 return encoded_size(buf, utf_length(buf)); 04945 } 04946 04947 // return number of utf32 code units required to re-encode given utf8 data as utf32. len is number of code units in 'buf'. 04948 size_type encoded_size(const utf8* buf, size_type len) const 04949 { 04950 utf8 tcp; 04951 size_type count = 0; 04952 04953 while (len--) 04954 { 04955 tcp = *buf++; 04956 ++count; 04957 size_type size = 0; 04958 04959 if (tcp < 0x80) 04960 { 04961 } 04962 else if (tcp < 0xE0) 04963 { 04964 size = 1; 04965 ++buf; 04966 } 04967 else if (tcp < 0xF0) 04968 { 04969 size = 2; 04970 buf += 2; 04971 } 04972 else 04973 { 04974 size = 3; 04975 buf += 3; 04976 } 04977 04978 if (len >= size) 04979 len -= size; 04980 else 04981 break; 04982 } 04983 04984 return count; 04985 } 04986 04987 // return number of code units in a null terminated string 04988 size_type utf_length(const utf8* utf8_str) const 04989 { 04990 size_type cnt = 0; 04991 while (*utf8_str++) 04992 cnt++; 04993 04994 return cnt; 04995 } 04996 04997 // return number of code units in a null terminated string 04998 size_type utf_length(const utf32* utf32_str) const 04999 { 05000 size_type cnt = 0; 05001 while (*utf32_str++) 05002 cnt++; 05003 05004 return cnt; 05005 } 05006 05007 // build an internal buffer with the string encoded as utf8 (remains valid until string is modified). 05008 utf8* build_utf8_buff(void) const; 05009 05010 // compare two utf32 buffers 05011 int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const 05012 { 05013 if (!cp_count) 05014 return 0; 05015 05016 while ((--cp_count) && (*buf1 == *buf2)) 05017 buf1++, buf2++; 05018 05019 return *buf1 - *buf2; 05020 } 05021 05022 // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF) 05023 int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const 05024 { 05025 if (!cp_count) 05026 return 0; 05027 05028 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2)))) 05029 buf1++, buf2++; 05030 05031 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2)); 05032 } 05033 05034 // compare utf32 buffer with encoded utf8 data 05035 int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const 05036 { 05037 if (!cp_count) 05038 return 0; 05039 05040 utf32 cp; 05041 utf8 cu; 05042 05043 do 05044 { 05045 cu = *buf2++; 05046 05047 if (cu < 0x80) 05048 { 05049 cp = (utf32)(cu); 05050 } 05051 else if (cu < 0xE0) 05052 { 05053 cp = ((cu & 0x1F) << 6); 05054 cp |= (*buf2++ & 0x3F); 05055 } 05056 else if (cu < 0xF0) 05057 { 05058 cp = ((cu & 0x0F) << 12); 05059 cp |= ((*buf2++ & 0x3F) << 6); 05060 cp |= (*buf2++ & 0x3F); 05061 } 05062 else 05063 { 05064 cp = ((cu & 0x07) << 18); 05065 cp |= ((*buf2++ & 0x3F) << 12); 05066 cp |= ((*buf2++ & 0x3F) << 6); 05067 cp |= (*buf2++ & 0x3F); 05068 } 05069 05070 } while ((*buf1++ == cp) && (--cp_count)); 05071 05072 return (*--buf1) - cp; 05073 } 05074 05075 // return index of first occurrence of 'code_point' in std::string 'str', or npos if none 05076 size_type find_codepoint(const std::string& str, utf32 code_point) const 05077 { 05078 size_type idx = 0, sze = (size_type)str.size(); 05079 05080 while (idx != sze) 05081 { 05082 if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx]))) 05083 return idx; 05084 05085 ++idx; 05086 } 05087 05088 return npos; 05089 } 05090 05091 // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none. len is in code points. 05092 size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const 05093 { 05094 size_type idx = 0; 05095 05096 utf32 cp; 05097 utf8 cu; 05098 05099 while (idx != len) { 05100 cu = *str++; 05101 05102 if (cu < 0x80) 05103 { 05104 cp = (utf32)(cu); 05105 } 05106 else if (cu < 0xE0) 05107 { 05108 cp = ((cu & 0x1F) << 6); 05109 cp |= (*str++ & 0x3F); 05110 } 05111 else if (cu < 0xF0) 05112 { 05113 cp = ((cu & 0x0F) << 12); 05114 cp |= ((*str++ & 0x3F) << 6); 05115 cp |= (*str++ & 0x3F); 05116 } 05117 else 05118 { 05119 cp = ((cu & 0x07) << 18); 05120 cp |= ((*str++ & 0x3F) << 12); 05121 cp |= ((*str++ & 0x3F) << 6); 05122 cp |= (*str++ & 0x3F); 05123 } 05124 05125 if (code_point == cp) 05126 return idx; 05127 05128 ++idx; 05129 } 05130 05131 return npos; 05132 } 05133 05134 05135 // return index of first occurrence of 'code_point' in char array 'chars', or npos if none 05136 size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const 05137 { 05138 for (size_type idx = 0; idx != chars_len; ++idx) 05139 { 05140 if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx]))) 05141 return idx; 05142 } 05143 05144 return npos; 05145 } 05146 05147 }; 05148 05149 05151 // Comparison operators 05153 05157 bool CEGUIEXPORT operator==(const String& str1, const String& str2); 05158 05163 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str); 05164 05169 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str); 05170 05175 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str); 05176 05181 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str); 05182 05187 bool CEGUIEXPORT operator!=(const String& str1, const String& str2); 05188 05193 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str); 05194 05199 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str); 05200 05205 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str); 05206 05211 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str); 05212 05217 bool CEGUIEXPORT operator<(const String& str1, const String& str2); 05218 05223 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str); 05224 05229 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str); 05230 05235 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str); 05236 05241 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str); 05242 05247 bool CEGUIEXPORT operator>(const String& str1, const String& str2); 05248 05253 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str); 05254 05259 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str); 05260 05265 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str); 05266 05271 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str); 05272 05277 bool CEGUIEXPORT operator<=(const String& str1, const String& str2); 05278 05283 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str); 05284 05289 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str); 05290 05295 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str); 05296 05301 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str); 05302 05307 bool CEGUIEXPORT operator>=(const String& str1, const String& str2); 05308 05313 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str); 05314 05319 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str); 05320 05325 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str); 05326 05331 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str); 05332 05337 bool CEGUIEXPORT operator==(const String& str, const char* c_str); 05338 05343 bool CEGUIEXPORT operator==(const char* c_str, const String& str); 05344 05349 bool CEGUIEXPORT operator!=(const String& str, const char* c_str); 05350 05355 bool CEGUIEXPORT operator!=(const char* c_str, const String& str); 05356 05361 bool CEGUIEXPORT operator<(const String& str, const char* c_str); 05362 05367 bool CEGUIEXPORT operator<(const char* c_str, const String& str); 05368 05373 bool CEGUIEXPORT operator>(const String& str, const char* c_str); 05374 05379 bool CEGUIEXPORT operator>(const char* c_str, const String& str); 05380 05385 bool CEGUIEXPORT operator<=(const String& str, const char* c_str); 05386 05391 bool CEGUIEXPORT operator<=(const char* c_str, const String& str); 05392 05397 bool CEGUIEXPORT operator>=(const String& str, const char* c_str); 05398 05403 bool CEGUIEXPORT operator>=(const char* c_str, const String& str); 05404 05406 // Concatenation operator functions 05408 05423 String CEGUIEXPORT operator+(const String& str1, const String& str2); 05424 05440 String CEGUIEXPORT operator+(const String& str, const std::string& std_str); 05441 05457 String CEGUIEXPORT operator+(const std::string& std_str, const String& str); 05458 05474 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str); 05475 05491 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str); 05492 05508 String CEGUIEXPORT operator+(const String& str, utf32 code_point); 05509 05525 String CEGUIEXPORT operator+(utf32 code_point, const String& str); 05526 05542 String CEGUIEXPORT operator+(const String& str, const char* c_str); 05543 05559 String CEGUIEXPORT operator+(const char* c_str, const String& str); 05560 05561 05563 // Output (stream) functions 05565 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str); 05566 05567 05569 // Modifying operations 05571 05584 void CEGUIEXPORT swap(String& str1, String& str2); 05585 05586 05587 } // End of CEGUI namespace section 05588 05589 05590 #endif // end of guard _CEGUIString_h_