Crazy Eddies GUI System 0.7.5
|
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> 00035 #include <string.h> 00036 #include <stdexcept> 00037 #include <cstddef> 00038 00039 // Start of CEGUI namespace section 00040 namespace CEGUI 00041 { 00042 #define STR_QUICKBUFF_SIZE 32 00043 /************************************************************************* 00044 Basic Types 00045 *************************************************************************/ 00046 typedef uint8 utf8; 00047 //typedef uint16 utf16; // removed typedef to prevent usage, as utf16 is not supported (yet) 00048 typedef uint32 utf32; 00049 00058 class CEGUIEXPORT String 00059 { 00060 public: 00061 /************************************************************************* 00062 Integral Types 00063 *************************************************************************/ 00064 typedef utf32 value_type; 00065 typedef size_t size_type; 00066 typedef ptrdiff_t difference_type; 00067 typedef utf32& reference; 00068 typedef const utf32& const_reference; 00069 typedef utf32* pointer; 00070 typedef const utf32* const_pointer; 00071 00072 static const size_type npos; 00073 00074 private: 00075 /************************************************************************* 00076 Implementation data 00077 *************************************************************************/ 00078 size_type d_cplength; 00079 size_type d_reserve; 00080 00081 mutable utf8* d_encodedbuff; 00082 mutable size_type d_encodeddatlen; 00083 mutable size_type d_encodedbufflen; 00084 00085 utf32 d_quickbuff[STR_QUICKBUFF_SIZE]; 00086 utf32* d_buffer; 00087 00088 public: 00089 /************************************************************************* 00090 Iterator Classes 00091 *************************************************************************/ 00093 class iterator : public std::iterator<std::random_access_iterator_tag, utf32> 00094 { 00095 public: 00096 iterator() : d_ptr(0) {} 00097 explicit iterator(utf32* const ptr) : d_ptr(ptr) {} 00098 00099 utf32& operator*() const 00100 { 00101 return *d_ptr; 00102 } 00103 00104 utf32* operator->() const 00105 { 00106 return &**this; 00107 } 00108 00109 String::iterator& operator++() 00110 { 00111 ++d_ptr; 00112 return *this; 00113 } 00114 00115 String::iterator operator++(int) 00116 { 00117 String::iterator temp = *this; 00118 ++*this; 00119 return temp; 00120 } 00121 00122 String::iterator& operator--() 00123 { 00124 --d_ptr; 00125 return *this; 00126 } 00127 00128 String::iterator operator--(int) 00129 { 00130 String::iterator temp = *this; 00131 --*this; 00132 return temp; 00133 } 00134 00135 String::iterator& operator+=(difference_type offset) 00136 { 00137 d_ptr += offset; 00138 return *this; 00139 } 00140 00141 String::iterator operator+(difference_type offset) const 00142 { 00143 String::iterator temp = *this; 00144 return temp += offset; 00145 } 00146 00147 String::iterator& operator-=(difference_type offset) 00148 { 00149 return *this += -offset; 00150 } 00151 00152 String::iterator operator-(difference_type offset) const 00153 { 00154 String::iterator temp = *this; 00155 return temp -= offset; 00156 } 00157 00158 utf32& operator[](difference_type offset) const 00159 { 00160 return *(*this + offset); 00161 } 00162 00163 friend difference_type operator-(const String::iterator& lhs, 00164 const String::iterator& rhs) 00165 { return lhs.d_ptr - rhs.d_ptr; } 00166 00167 friend String::iterator operator+(difference_type offset, const String::iterator& iter) 00168 { return iter + offset; } 00169 00170 friend bool operator==(const String::iterator& lhs, 00171 const String::iterator& rhs) 00172 { return lhs.d_ptr == rhs.d_ptr; } 00173 00174 friend bool operator!=(const String::iterator& lhs, 00175 const String::iterator& rhs) 00176 { return lhs.d_ptr != rhs.d_ptr; } 00177 00178 friend bool operator<(const String::iterator& lhs, 00179 const String::iterator& rhs) 00180 { return lhs.d_ptr < rhs.d_ptr; } 00181 00182 friend bool operator>(const String::iterator& lhs, 00183 const String::iterator& rhs) 00184 { return lhs.d_ptr > rhs.d_ptr; } 00185 00186 friend bool operator<=(const String::iterator& lhs, 00187 const String::iterator& rhs) 00188 { return lhs.d_ptr <= rhs.d_ptr; } 00189 00190 friend bool operator>=(const String::iterator& lhs, 00191 const String::iterator& rhs) 00192 { return lhs.d_ptr >= rhs.d_ptr; } 00193 00194 utf32* d_ptr; 00195 }; 00196 00198 class const_iterator : public std::iterator<std::random_access_iterator_tag, const utf32> 00199 { 00200 public: 00201 const_iterator() : d_ptr(0) {} 00202 explicit const_iterator(const utf32* const ptr) : d_ptr(ptr) {} 00203 const_iterator(const String::iterator& iter) : d_ptr(iter.d_ptr) {} 00204 00205 const utf32& operator*() const 00206 { 00207 return *d_ptr; 00208 } 00209 00210 const utf32* operator->() const 00211 { 00212 return &**this; 00213 } 00214 00215 String::const_iterator& operator++() 00216 { 00217 ++d_ptr; 00218 return *this; 00219 } 00220 00221 String::const_iterator operator++(int) 00222 { 00223 String::const_iterator temp = *this; 00224 ++*this; 00225 return temp; 00226 } 00227 00228 String::const_iterator& operator--() 00229 { 00230 --d_ptr; 00231 return *this; 00232 } 00233 00234 String::const_iterator operator--(int) 00235 { 00236 String::const_iterator temp = *this; 00237 --*this; 00238 return temp; 00239 } 00240 00241 String::const_iterator& operator+=(difference_type offset) 00242 { 00243 d_ptr += offset; 00244 return *this; 00245 } 00246 00247 String::const_iterator operator+(difference_type offset) const 00248 { 00249 String::const_iterator temp = *this; 00250 return temp += offset; 00251 } 00252 00253 String::const_iterator& operator-=(difference_type offset) 00254 { 00255 return *this += -offset; 00256 } 00257 00258 String::const_iterator operator-(difference_type offset) const 00259 { 00260 String::const_iterator temp = *this; 00261 return temp -= offset; 00262 } 00263 00264 const utf32& operator[](difference_type offset) const 00265 { 00266 return *(*this + offset); 00267 } 00268 00269 String::const_iterator& operator=(const String::iterator& iter) 00270 { 00271 d_ptr = iter.d_ptr; 00272 return *this; 00273 } 00274 00275 friend String::const_iterator operator+(difference_type offset, const String::const_iterator& iter) 00276 { return iter + offset; } 00277 00278 friend difference_type operator-(const String::const_iterator& lhs, 00279 const String::const_iterator& rhs) 00280 { return lhs.d_ptr - rhs.d_ptr; } 00281 00282 friend bool operator==(const String::const_iterator& lhs, 00283 const String::const_iterator& rhs) 00284 { return lhs.d_ptr == rhs.d_ptr; } 00285 00286 friend bool operator!=(const String::const_iterator& lhs, 00287 const String::const_iterator& rhs) 00288 { return lhs.d_ptr != rhs.d_ptr; } 00289 00290 friend bool operator<(const String::const_iterator& lhs, 00291 const String::const_iterator& rhs) 00292 { return lhs.d_ptr < rhs.d_ptr; } 00293 00294 friend bool operator>(const String::const_iterator& lhs, 00295 const String::const_iterator& rhs) 00296 { return lhs.d_ptr > rhs.d_ptr; } 00297 00298 friend bool operator<=(const String::const_iterator& lhs, 00299 const String::const_iterator& rhs) 00300 { return lhs.d_ptr <= rhs.d_ptr; } 00301 00302 friend bool operator>=(const String::const_iterator& lhs, 00303 const String::const_iterator& rhs) 00304 { return lhs.d_ptr >= rhs.d_ptr; } 00305 00306 const utf32* d_ptr; 00307 }; 00308 00313 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION))) 00314 typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator; 00315 #else 00316 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00317 #endif 00318 00323 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION))) 00324 typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator; 00325 #else 00326 typedef std::reverse_iterator<iterator> reverse_iterator; 00327 #endif 00328 00329 public: 00335 struct FastLessCompare 00336 { 00337 bool operator() (const String& a, const String& b) const 00338 { 00339 const size_t la = a.length(); 00340 const size_t lb = b.length(); 00341 if (la == lb) 00342 return (memcmp(a.ptr(), b.ptr(), la*sizeof(utf32)) < 0); 00343 return (la < lb); 00344 } 00345 }; 00346 00347 public: 00349 // Default Construction and Destructor 00351 00355 String(void) 00356 { 00357 init(); 00358 } 00359 00364 ~String(void); 00365 00367 // Construction via CEGUI::String 00369 00379 String(const String& str) 00380 { 00381 init(); 00382 assign(str); 00383 } 00384 00385 00402 String(const String& str, size_type str_idx, size_type str_num = npos) 00403 { 00404 init(); 00405 assign(str, str_idx, str_num); 00406 } 00407 00409 // Construction via std::string 00411 00427 String(const std::string& std_str) 00428 { 00429 init(); 00430 assign(std_str); 00431 } 00432 00455 String(const std::string& std_str, size_type str_idx, size_type str_num = npos) 00456 { 00457 init(); 00458 assign(std_str, str_idx, str_num); 00459 } 00460 00461 00463 // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid) 00465 00483 String(const utf8* utf8_str) 00484 { 00485 init(); 00486 assign(utf8_str); 00487 } 00488 00515 String(const utf8* utf8_str, size_type chars_len) 00516 { 00517 init(); 00518 assign(utf8_str, chars_len); 00519 } 00520 00522 // Construction via code-point (using a UTF-32 code unit) 00524 00539 String(size_type num, utf32 code_point) 00540 { 00541 init(); 00542 assign(num, code_point); 00543 } 00544 00546 // Construction via iterator 00548 // Create string with characters in the range [beg, end) 00562 String(const_iterator iter_beg, const_iterator iter_end) 00563 { 00564 init(); 00565 append(iter_beg, iter_end); 00566 } 00567 00568 00570 // Construction via c-string 00572 00584 String(const char* cstr) 00585 { 00586 init(); 00587 assign(cstr); 00588 } 00589 00605 String(const char* chars, size_type chars_len) 00606 { 00607 init(); 00608 assign(chars, chars_len); 00609 } 00610 00611 00613 // Size operations 00615 00622 size_type size(void) const 00623 { 00624 return d_cplength; 00625 } 00626 00634 size_type length(void) const 00635 { 00636 return d_cplength; 00637 } 00638 00646 bool empty(void) const 00647 { 00648 return (d_cplength == 0); 00649 } 00650 00660 static size_type max_size(void) 00661 { 00662 return (((size_type)-1) / sizeof(utf32)); 00663 } 00664 00666 // Capacity Operations 00668 // return the number of code points the string could hold without re-allocation 00669 // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!) 00678 size_type capacity(void) const 00679 { 00680 return d_reserve - 1; 00681 } 00682 00683 // reserve internal memory for at-least 'num' code-points (characters). if num is 0, request is shrink-to-fit. 00698 void reserve(size_type num = 0) 00699 { 00700 if (num == 0) 00701 trim(); 00702 else 00703 grow(num); 00704 } 00705 00707 // Comparisons 00709 00724 int compare(const String& str) const 00725 { 00726 return compare(0, d_cplength, str); 00727 } 00728 00758 int compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const 00759 { 00760 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 00761 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00762 00763 if ((len == npos) || (idx + len > d_cplength)) 00764 len = d_cplength - idx; 00765 00766 if ((str_len == npos) || (str_idx + str_len > str.d_cplength)) 00767 str_len = str.d_cplength - str_idx; 00768 00769 int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len); 00770 00771 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1; 00772 } 00773 00774 00794 int compare(const std::string& std_str) const 00795 { 00796 return compare(0, d_cplength, std_str); 00797 } 00798 00799 00833 int compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const 00834 { 00835 if (d_cplength < idx) 00836 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00837 00838 if (std_str.size() < str_idx) 00839 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 00840 00841 if ((len == npos) || (idx + len > d_cplength)) 00842 len = d_cplength - idx; 00843 00844 if ((str_len == npos) || (str_idx + str_len > std_str.size())) 00845 str_len = (size_type)std_str.size() - str_idx; 00846 00847 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len); 00848 00849 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1; 00850 } 00851 00852 00874 int compare(const utf8* utf8_str) const 00875 { 00876 return compare(0, d_cplength, utf8_str, encoded_size(utf8_str)); 00877 } 00878 00879 00909 int compare(size_type idx, size_type len, const utf8* utf8_str) const 00910 { 00911 return compare(idx, len, utf8_str, encoded_size(utf8_str)); 00912 } 00913 00947 int compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const 00948 { 00949 if (d_cplength < idx) 00950 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00951 00952 if (str_cplen == npos) 00953 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 00954 00955 if ((len == npos) || (idx + len > d_cplength)) 00956 len = d_cplength - idx; 00957 00958 int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen); 00959 00960 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1; 00961 } 00962 00963 00979 int compare(const char* cstr) const 00980 { 00981 return compare(0, d_cplength, cstr, strlen(cstr)); 00982 } 00983 00984 01008 int compare(size_type idx, size_type len, const char* cstr) const 01009 { 01010 return compare(idx, len, cstr, strlen(cstr)); 01011 } 01012 01013 01041 int compare(size_type idx, size_type len, const char* chars, size_type chars_len) const 01042 { 01043 if (d_cplength < idx) 01044 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01045 01046 if (chars_len == npos) 01047 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 01048 01049 if ((len == npos) || (idx + len > d_cplength)) 01050 len = d_cplength - idx; 01051 01052 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len); 01053 01054 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1; 01055 } 01056 01057 01059 // Character access 01061 01075 reference operator[](size_type idx) 01076 { 01077 return (ptr()[idx]); 01078 } 01079 01094 value_type operator[](size_type idx) const 01095 { 01096 return ptr()[idx]; 01097 } 01098 01111 reference at(size_type idx) 01112 { 01113 if (d_cplength <= idx) 01114 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01115 01116 return ptr()[idx]; 01117 } 01118 01131 const_reference at(size_type idx) const 01132 { 01133 if (d_cplength <= idx) 01134 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01135 01136 return ptr()[idx]; 01137 } 01138 01139 01141 // C-Strings and arrays 01143 01156 const char* c_str(void) const 01157 { 01158 return (const char*)build_utf8_buff(); 01159 } 01160 01174 const utf8* data(void) const 01175 { 01176 return build_utf8_buff(); 01177 } 01178 01183 utf32* ptr(void) 01184 { 01185 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff; 01186 } 01187 01192 const utf32* ptr(void) const 01193 { 01194 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff; 01195 } 01196 01197 // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data 01198 // return number of utf8 code units placed into the buffer 01219 size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const 01220 { 01221 if (d_cplength < idx) 01222 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01223 01224 if (len == npos) 01225 len = d_cplength; 01226 01227 return encode(&ptr()[idx], buf, npos, len); 01228 } 01229 01231 // UTF8 Encoding length information 01233 // 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. 01249 size_type utf8_stream_len(size_type num = npos, size_type idx = 0) const 01250 { 01251 using namespace std; 01252 01253 if (d_cplength < idx) 01254 CEGUI_THROW(out_of_range("Index was out of range for CEGUI::String object")); 01255 01256 size_type maxlen = d_cplength - idx; 01257 01258 return encoded_size(&ptr()[idx], ceguimin(num, maxlen)); 01259 } 01260 01262 // Assignment Functions 01264 01274 String& operator=(const String& str) 01275 { 01276 return assign(str); 01277 } 01278 01297 String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos) 01298 { 01299 if (str.d_cplength < str_idx) 01300 CEGUI_THROW(std::out_of_range("Index was out of range for CEGUI::String object")); 01301 01302 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 01303 str_num = str.d_cplength - str_idx; 01304 01305 grow(str_num); 01306 setlen(str_num); 01307 memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32)); 01308 01309 return *this; 01310 } 01311 01328 String& operator=(const std::string& std_str) 01329 { 01330 return assign(std_str); 01331 } 01332 01356 String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos) 01357 { 01358 if (std_str.size() < str_idx) 01359 CEGUI_THROW(std::out_of_range("Index was out of range for std::string object")); 01360 01361 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 01362 str_num = (size_type)std_str.size() - str_idx; 01363 01364 grow(str_num); 01365 setlen(str_num); 01366 01367 while(str_num--) 01368 { 01369 ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx])); 01370 } 01371 01372 return *this; 01373 } 01374 01393 String& operator=(const utf8* utf8_str) 01394 { 01395 return assign(utf8_str, utf_length(utf8_str)); 01396 } 01397 01416 String& assign(const utf8* utf8_str) 01417 { 01418 return assign(utf8_str, utf_length(utf8_str)); 01419 } 01420 01442 String& assign(const utf8* utf8_str, size_type str_num) 01443 { 01444 if (str_num == npos) 01445 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 01446 01447 size_type enc_sze = encoded_size(utf8_str, str_num); 01448 01449 grow(enc_sze); 01450 encode(utf8_str, ptr(), d_reserve, str_num); 01451 setlen(enc_sze); 01452 return *this; 01453 } 01454 01465 String& operator=(utf32 code_point) 01466 { 01467 return assign(1, code_point); 01468 } 01469 01485 String& assign(size_type num, utf32 code_point) 01486 { 01487 if (num == npos) 01488 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 01489 01490 grow(num); 01491 setlen(num); 01492 utf32* p = ptr(); 01493 01494 while(num--) 01495 *p++ = code_point; 01496 01497 return *this; 01498 } 01499 01500 01513 String& operator=(const char* cstr) 01514 { 01515 return assign(cstr, strlen(cstr)); 01516 } 01517 01518 01531 String& assign(const char* cstr) 01532 { 01533 return assign(cstr, strlen(cstr)); 01534 } 01535 01536 01552 String& assign(const char* chars, size_type chars_len) 01553 { 01554 grow(chars_len); 01555 utf32* pt = ptr(); 01556 01557 for (size_type i = 0; i < chars_len; ++i) 01558 { 01559 *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++)); 01560 } 01561 01562 setlen(chars_len); 01563 return *this; 01564 } 01565 01566 01577 void swap(String& str) 01578 { 01579 size_type temp_len = d_cplength; 01580 d_cplength = str.d_cplength; 01581 str.d_cplength = temp_len; 01582 01583 size_type temp_res = d_reserve; 01584 d_reserve = str.d_reserve; 01585 str.d_reserve = temp_res; 01586 01587 utf32* temp_buf = d_buffer; 01588 d_buffer = str.d_buffer; 01589 str.d_buffer = temp_buf; 01590 01591 // see if we need to swap 'quick buffer' data 01592 if (temp_res <= STR_QUICKBUFF_SIZE) 01593 { 01594 utf32 temp_qbf[STR_QUICKBUFF_SIZE]; 01595 01596 memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32)); 01597 memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32)); 01598 memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32)); 01599 } 01600 01601 } 01602 01604 // Appending Functions 01606 01618 String& operator+=(const String& str) 01619 { 01620 return append(str); 01621 } 01622 01642 String& append(const String& str, size_type str_idx = 0, size_type str_num = npos) 01643 { 01644 if (str.d_cplength < str_idx) 01645 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01646 01647 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 01648 str_num = str.d_cplength - str_idx; 01649 01650 grow(d_cplength + str_num); 01651 memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32)); 01652 setlen(d_cplength + str_num); 01653 return *this; 01654 } 01655 01656 01673 String& operator+=(const std::string& std_str) 01674 { 01675 return append(std_str); 01676 } 01677 01701 String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos) 01702 { 01703 if (std_str.size() < str_idx) 01704 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 01705 01706 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 01707 str_num = (size_type)std_str.size() - str_idx; 01708 01709 size_type newsze = d_cplength + str_num; 01710 01711 grow(newsze); 01712 utf32* pt = &ptr()[newsze-1]; 01713 01714 while(str_num--) 01715 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num])); 01716 01717 setlen(newsze); 01718 return *this; 01719 } 01720 01721 01740 String& operator+=(const utf8* utf8_str) 01741 { 01742 return append(utf8_str, utf_length(utf8_str)); 01743 } 01744 01763 String& append(const utf8* utf8_str) 01764 { 01765 return append(utf8_str, utf_length(utf8_str)); 01766 } 01767 01768 01790 String& append(const utf8* utf8_str, size_type len) 01791 { 01792 if (len == npos) 01793 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 01794 01795 size_type encsz = encoded_size(utf8_str, len); 01796 size_type newsz = d_cplength + encsz; 01797 01798 grow(newsz); 01799 encode(utf8_str, &ptr()[d_cplength], encsz, len); 01800 setlen(newsz); 01801 01802 return *this; 01803 } 01804 01805 01818 String& operator+=(utf32 code_point) 01819 { 01820 return append(1, code_point); 01821 } 01822 01838 String& append(size_type num, utf32 code_point) 01839 { 01840 if (num == npos) 01841 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 01842 01843 size_type newsz = d_cplength + num; 01844 grow(newsz); 01845 01846 utf32* p = &ptr()[d_cplength]; 01847 01848 while(num--) 01849 *p++ = code_point; 01850 01851 setlen(newsz); 01852 01853 return *this; 01854 } 01855 01868 void push_back(utf32 code_point) 01869 { 01870 append(1, code_point); 01871 } 01872 01888 String& append(const_iterator iter_beg, const_iterator iter_end) 01889 { 01890 return replace(end(), end(), iter_beg, iter_end); 01891 } 01892 01893 01906 String& operator+=(const char* cstr) 01907 { 01908 return append(cstr, strlen(cstr)); 01909 } 01910 01911 01924 String& append(const char* cstr) 01925 { 01926 return append(cstr, strlen(cstr)); 01927 } 01928 01929 01945 String& append(const char* chars, size_type chars_len) 01946 { 01947 if (chars_len == npos) 01948 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 01949 01950 size_type newsz = d_cplength + chars_len; 01951 01952 grow(newsz); 01953 01954 utf32* pt = &ptr()[newsz-1]; 01955 01956 while(chars_len--) 01957 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 01958 01959 setlen(newsz); 01960 01961 return *this; 01962 } 01963 01964 01966 // Insertion Functions 01968 01984 String& insert(size_type idx, const String& str) 01985 { 01986 return insert(idx, str, 0, npos); 01987 } 01988 02011 String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num) 02012 { 02013 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 02014 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02015 02016 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 02017 str_num = str.d_cplength - str_idx; 02018 02019 size_type newsz = d_cplength + str_num; 02020 grow(newsz); 02021 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02022 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32)); 02023 setlen(newsz); 02024 02025 return *this; 02026 } 02027 02048 String& insert(size_type idx, const std::string& std_str) 02049 { 02050 return insert(idx, std_str, 0, npos); 02051 } 02052 02079 String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num) 02080 { 02081 if (d_cplength < idx) 02082 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02083 02084 if (std_str.size() < str_idx) 02085 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 02086 02087 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 02088 str_num = (size_type)std_str.size() - str_idx; 02089 02090 size_type newsz = d_cplength + str_num; 02091 grow(newsz); 02092 02093 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02094 02095 utf32* pt = &ptr()[idx + str_num - 1]; 02096 02097 while(str_num--) 02098 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num])); 02099 02100 setlen(newsz); 02101 02102 return *this; 02103 } 02104 02127 String& insert(size_type idx, const utf8* utf8_str) 02128 { 02129 return insert(idx, utf8_str, utf_length(utf8_str)); 02130 } 02131 02157 String& insert(size_type idx, const utf8* utf8_str, size_type len) 02158 { 02159 if (d_cplength < idx) 02160 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02161 02162 if (len == npos) 02163 CEGUI_THROW(std::length_error("Length of utf8 encoded string can not be 'npos'")); 02164 02165 size_type encsz = encoded_size(utf8_str, len); 02166 size_type newsz = d_cplength + encsz; 02167 02168 grow(newsz); 02169 memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02170 encode(utf8_str, &ptr()[idx], encsz, len); 02171 setlen(newsz); 02172 02173 return *this; 02174 } 02175 02195 String& insert(size_type idx, size_type num, utf32 code_point) 02196 { 02197 if (d_cplength < idx) 02198 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02199 02200 if (num == npos) 02201 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 02202 02203 size_type newsz = d_cplength + num; 02204 grow(newsz); 02205 02206 memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02207 02208 utf32* pt = &ptr()[idx + num - 1]; 02209 02210 while(num--) 02211 *pt-- = code_point; 02212 02213 setlen(newsz); 02214 02215 return *this; 02216 } 02217 02236 void insert(iterator pos, size_type num, utf32 code_point) 02237 { 02238 insert(safe_iter_dif(pos, begin()), num, code_point); 02239 } 02240 02256 iterator insert(iterator pos, utf32 code_point) 02257 { 02258 insert(pos, 1, code_point); 02259 return pos; 02260 } 02261 02280 void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end) 02281 { 02282 replace(iter_pos, iter_pos, iter_beg, iter_end); 02283 } 02284 02285 02302 String& insert(size_type idx, const char* cstr) 02303 { 02304 return insert(idx, cstr, strlen(cstr)); 02305 } 02306 02307 02327 String& insert(size_type idx, const char* chars, size_type chars_len) 02328 { 02329 if (d_cplength < idx) 02330 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02331 02332 if (chars_len == npos) 02333 CEGUI_THROW(std::length_error("Length of char array can not be 'npos'")); 02334 02335 size_type newsz = d_cplength + chars_len; 02336 02337 grow(newsz); 02338 memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02339 02340 utf32* pt = &ptr()[idx + chars_len - 1]; 02341 02342 while(chars_len--) 02343 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 02344 02345 setlen(newsz); 02346 02347 return *this; 02348 } 02349 02350 02352 // Erasing characters 02354 02361 void clear(void) 02362 { 02363 setlen(0); 02364 trim(); 02365 } 02366 02374 String& erase(void) 02375 { 02376 clear(); 02377 return *this; 02378 } 02379 02392 String& erase(size_type idx) 02393 { 02394 return erase(idx, 1); 02395 } 02396 02412 String& erase(size_type idx, size_type len) 02413 { 02414 // cover the no-op case. 02415 if (len == 0) 02416 return *this; 02417 02418 if (d_cplength <= idx) 02419 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02420 02421 if (len == npos) 02422 len = d_cplength - idx; 02423 02424 size_type newsz = d_cplength - len; 02425 02426 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32)); 02427 setlen(newsz); 02428 return *this; 02429 } 02430 02441 String& erase(iterator pos) 02442 { 02443 return erase(safe_iter_dif(pos, begin()), 1); 02444 } 02445 02459 String& erase(iterator iter_beg, iterator iter_end) 02460 { 02461 return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg)); 02462 } 02463 02465 // Resizing 02467 02479 void resize(size_type num) 02480 { 02481 resize(num, utf32()); 02482 } 02483 02499 void resize(size_type num, utf32 code_point) 02500 { 02501 if (num < d_cplength) 02502 { 02503 setlen(num); 02504 } 02505 else 02506 { 02507 append(num - d_cplength, code_point); 02508 } 02509 02510 } 02511 02513 // Replacing Characters 02515 02534 String& replace(size_type idx, size_type len, const String& str) 02535 { 02536 return replace(idx, len, str, 0, npos); 02537 } 02538 02560 String& replace(iterator iter_beg, iterator iter_end, const String& str) 02561 { 02562 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos); 02563 } 02564 02590 String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num) 02591 { 02592 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 02593 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02594 02595 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos)) 02596 str_num = str.d_cplength - str_idx; 02597 02598 if (((len + idx) > d_cplength) || (len == npos)) 02599 len = d_cplength - idx; 02600 02601 size_type newsz = d_cplength + str_num - len; 02602 02603 grow(newsz); 02604 02605 if ((idx + len) < d_cplength) 02606 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02607 02608 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32)); 02609 setlen(newsz); 02610 02611 return *this; 02612 } 02613 02614 02638 String& replace(size_type idx, size_type len, const std::string& std_str) 02639 { 02640 return replace(idx, len, std_str, 0, npos); 02641 } 02642 02668 String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str) 02669 { 02670 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos); 02671 } 02672 02702 String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num) 02703 { 02704 if (d_cplength < idx) 02705 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02706 02707 if (std_str.size() < str_idx) 02708 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 02709 02710 if (((str_idx + str_num) > std_str.size()) || (str_num == npos)) 02711 str_num = (size_type)std_str.size() - str_idx; 02712 02713 if (((len + idx) > d_cplength) || (len == npos)) 02714 len = d_cplength - idx; 02715 02716 size_type newsz = d_cplength + str_num - len; 02717 02718 grow(newsz); 02719 02720 if ((idx + len) < d_cplength) 02721 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02722 02723 utf32* pt = &ptr()[idx + str_num - 1]; 02724 02725 while (str_num--) 02726 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num])); 02727 02728 setlen(newsz); 02729 02730 return *this; 02731 } 02732 02733 02759 String& replace(size_type idx, size_type len, const utf8* utf8_str) 02760 { 02761 return replace(idx, len, utf8_str, utf_length(utf8_str)); 02762 } 02763 02791 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str) 02792 { 02793 return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str)); 02794 } 02795 02824 String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len) 02825 { 02826 if (d_cplength < idx) 02827 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02828 02829 if (str_len == npos) 02830 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 02831 02832 if (((len + idx) > d_cplength) || (len == npos)) 02833 len = d_cplength - idx; 02834 02835 size_type encsz = encoded_size(utf8_str, str_len); 02836 size_type newsz = d_cplength + encsz - len; 02837 02838 grow(newsz); 02839 02840 if ((idx + len) < d_cplength) 02841 memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02842 02843 encode(utf8_str, &ptr()[idx], encsz, str_len); 02844 02845 setlen(newsz); 02846 return *this; 02847 } 02848 02879 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len) 02880 { 02881 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len); 02882 } 02883 02906 String& replace(size_type idx, size_type len, size_type num, utf32 code_point) 02907 { 02908 if (d_cplength < idx) 02909 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02910 02911 if (num == npos) 02912 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 02913 02914 if (((len + idx) > d_cplength) || (len == npos)) 02915 len = d_cplength - idx; 02916 02917 size_type newsz = d_cplength + num - len; 02918 02919 grow(newsz); 02920 02921 if ((idx + len) < d_cplength) 02922 memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02923 02924 utf32* pt = &ptr()[idx + num - 1]; 02925 02926 while (num--) 02927 *pt-- = code_point; 02928 02929 setlen(newsz); 02930 02931 return *this; 02932 } 02933 02958 String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point) 02959 { 02960 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point); 02961 } 02962 02963 02988 String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd) 02989 { 02990 if (iter_newBeg == iter_newEnd) 02991 { 02992 erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg)); 02993 } 02994 else 02995 { 02996 size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg); 02997 size_type idx = safe_iter_dif(iter_beg, begin()); 02998 size_type len = safe_iter_dif(iter_end, iter_beg); 02999 03000 if ((len + idx) > d_cplength) 03001 len = d_cplength - idx; 03002 03003 size_type newsz = d_cplength + str_len - len; 03004 03005 grow(newsz); 03006 03007 if ((idx + len) < d_cplength) 03008 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 03009 03010 memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32)); 03011 setlen(newsz); 03012 } 03013 03014 return *this; 03015 } 03016 03017 03037 String& replace(size_type idx, size_type len, const char* cstr) 03038 { 03039 return replace(idx, len, cstr, strlen(cstr)); 03040 } 03041 03042 03064 String& replace(iterator iter_beg, iterator iter_end, const char* cstr) 03065 { 03066 return replace(iter_beg, iter_end, cstr, strlen(cstr)); 03067 } 03068 03069 03092 String& replace(size_type idx, size_type len, const char* chars, size_type chars_len) 03093 { 03094 if (d_cplength < idx) 03095 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 03096 03097 if (chars_len == npos) 03098 CEGUI_THROW(std::length_error("Length for the char array can not be 'npos'")); 03099 03100 if (((len + idx) > d_cplength) || (len == npos)) 03101 len = d_cplength - idx; 03102 03103 size_type newsz = d_cplength + chars_len - len; 03104 03105 grow(newsz); 03106 03107 if ((idx + len) < d_cplength) 03108 memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 03109 03110 utf32* pt = &ptr()[idx + chars_len - 1]; 03111 03112 while (chars_len--) 03113 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 03114 03115 setlen(newsz); 03116 return *this; 03117 } 03118 03119 03144 String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len) 03145 { 03146 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len); 03147 } 03148 03149 03151 // Find a code point 03153 03167 size_type find(utf32 code_point, size_type idx = 0) const 03168 { 03169 if (idx < d_cplength) 03170 { 03171 const utf32* pt = &ptr()[idx]; 03172 03173 while (idx < d_cplength) 03174 { 03175 if (*pt++ == code_point) 03176 return idx; 03177 03178 ++idx; 03179 } 03180 03181 } 03182 03183 return npos; 03184 } 03185 03200 size_type rfind(utf32 code_point, size_type idx = npos) const 03201 { 03202 if (idx >= d_cplength) 03203 idx = d_cplength - 1; 03204 03205 if (d_cplength > 0) 03206 { 03207 const utf32* pt = &ptr()[idx]; 03208 03209 do 03210 { 03211 if (*pt-- == code_point) 03212 return idx; 03213 03214 } while (idx-- != 0); 03215 03216 } 03217 03218 return npos; 03219 } 03220 03222 // Find a substring 03224 03238 size_type find(const String& str, size_type idx = 0) const 03239 { 03240 if ((str.d_cplength == 0) && (idx < d_cplength)) 03241 return idx; 03242 03243 if (idx < d_cplength) 03244 { 03245 // loop while search string could fit in to search area 03246 while (d_cplength - idx >= str.d_cplength) 03247 { 03248 if (0 == compare(idx, str.d_cplength, str)) 03249 return idx; 03250 03251 ++idx; 03252 } 03253 03254 } 03255 03256 return npos; 03257 } 03258 03273 size_type rfind(const String& str, size_type idx = npos) const 03274 { 03275 if (str.d_cplength == 0) 03276 return (idx < d_cplength) ? idx : d_cplength; 03277 03278 if (str.d_cplength <= d_cplength) 03279 { 03280 if (idx > (d_cplength - str.d_cplength)) 03281 idx = d_cplength - str.d_cplength; 03282 03283 do 03284 { 03285 if (0 == compare(idx, str.d_cplength, str)) 03286 return idx; 03287 03288 } while (idx-- != 0); 03289 03290 } 03291 03292 return npos; 03293 } 03294 03313 size_type find(const std::string& std_str, size_type idx = 0) const 03314 { 03315 std::string::size_type sze = std_str.size(); 03316 03317 if ((sze == 0) && (idx < d_cplength)) 03318 return idx; 03319 03320 if (idx < d_cplength) 03321 { 03322 // loop while search string could fit in to search area 03323 while (d_cplength - idx >= sze) 03324 { 03325 if (0 == compare(idx, (size_type)sze, std_str)) 03326 return idx; 03327 03328 ++idx; 03329 } 03330 03331 } 03332 03333 return npos; 03334 } 03335 03354 size_type rfind(const std::string& std_str, size_type idx = npos) const 03355 { 03356 std::string::size_type sze = std_str.size(); 03357 03358 if (sze == 0) 03359 return (idx < d_cplength) ? idx : d_cplength; 03360 03361 if (sze <= d_cplength) 03362 { 03363 if (idx > (d_cplength - sze)) 03364 idx = d_cplength - sze; 03365 03366 do 03367 { 03368 if (0 == compare(idx, (size_type)sze, std_str)) 03369 return idx; 03370 03371 } while (idx-- != 0); 03372 03373 } 03374 03375 return npos; 03376 } 03377 03400 size_type find(const utf8* utf8_str, size_type idx = 0) const 03401 { 03402 return find(utf8_str, idx, utf_length(utf8_str)); 03403 } 03404 03427 size_type rfind(const utf8* utf8_str, size_type idx = npos) const 03428 { 03429 return rfind(utf8_str, idx, utf_length(utf8_str)); 03430 } 03431 03457 size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const 03458 { 03459 if (str_len == npos) 03460 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03461 03462 size_type sze = encoded_size(utf8_str, str_len); 03463 03464 if ((sze == 0) && (idx < d_cplength)) 03465 return idx; 03466 03467 if (idx < d_cplength) 03468 { 03469 // loop while search string could fit in to search area 03470 while (d_cplength - idx >= sze) 03471 { 03472 if (0 == compare(idx, sze, utf8_str, sze)) 03473 return idx; 03474 03475 ++idx; 03476 } 03477 03478 } 03479 03480 return npos; 03481 } 03482 03508 size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const 03509 { 03510 if (str_len == npos) 03511 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03512 03513 size_type sze = encoded_size(utf8_str, str_len); 03514 03515 if (sze == 0) 03516 return (idx < d_cplength) ? idx : d_cplength; 03517 03518 if (sze <= d_cplength) 03519 { 03520 if (idx > (d_cplength - sze)) 03521 idx = d_cplength - sze; 03522 03523 do 03524 { 03525 if (0 == compare(idx, sze, utf8_str, sze)) 03526 return idx; 03527 03528 } while (idx-- != 0); 03529 03530 } 03531 03532 return npos; 03533 } 03534 03535 03552 size_type find(const char* cstr, size_type idx = 0) const 03553 { 03554 return find(cstr, idx, strlen(cstr)); 03555 } 03556 03557 03574 size_type rfind(const char* cstr, size_type idx = npos) const 03575 { 03576 return rfind(cstr, idx, strlen(cstr)); 03577 } 03578 03579 03599 size_type find(const char* chars, size_type idx, size_type chars_len) const 03600 { 03601 if (chars_len == npos) 03602 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 03603 03604 if ((chars_len == 0) && (idx < d_cplength)) 03605 return idx; 03606 03607 if (idx < d_cplength) 03608 { 03609 // loop while search string could fit in to search area 03610 while (d_cplength - idx >= chars_len) 03611 { 03612 if (0 == compare(idx, chars_len, chars, chars_len)) 03613 return idx; 03614 03615 ++idx; 03616 } 03617 03618 } 03619 03620 return npos; 03621 } 03622 03623 03643 size_type rfind(const char* chars, size_type idx, size_type chars_len) const 03644 { 03645 if (chars_len == npos) 03646 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 03647 03648 if (chars_len == 0) 03649 return (idx < d_cplength) ? idx : d_cplength; 03650 03651 if (chars_len <= d_cplength) 03652 { 03653 if (idx > (d_cplength - chars_len)) 03654 idx = d_cplength - chars_len; 03655 03656 do 03657 { 03658 if (0 == compare(idx, chars_len, chars, chars_len)) 03659 return idx; 03660 03661 } while (idx-- != 0); 03662 03663 } 03664 03665 return npos; 03666 } 03667 03668 03670 // Find first of different code-points 03672 03686 size_type find_first_of(const String& str, size_type idx = 0) const 03687 { 03688 if (idx < d_cplength) 03689 { 03690 const utf32* pt = &ptr()[idx]; 03691 03692 do 03693 { 03694 if (npos != str.find(*pt++)) 03695 return idx; 03696 03697 } while (++idx != d_cplength); 03698 03699 } 03700 03701 return npos; 03702 } 03703 03718 size_type find_first_not_of(const String& str, size_type idx = 0) const 03719 { 03720 if (idx < d_cplength) 03721 { 03722 const utf32* pt = &ptr()[idx]; 03723 03724 do 03725 { 03726 if (npos == str.find(*pt++)) 03727 return idx; 03728 03729 } while (++idx != d_cplength); 03730 03731 } 03732 03733 return npos; 03734 } 03735 03736 03755 size_type find_first_of(const std::string& std_str, size_type idx = 0) const 03756 { 03757 if (idx < d_cplength) 03758 { 03759 const utf32* pt = &ptr()[idx]; 03760 03761 do 03762 { 03763 if (npos != find_codepoint(std_str, *pt++)) 03764 return idx; 03765 03766 } while (++idx != d_cplength); 03767 03768 } 03769 03770 return npos; 03771 } 03772 03791 size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const 03792 { 03793 if (idx < d_cplength) 03794 { 03795 const utf32* pt = &ptr()[idx]; 03796 03797 do 03798 { 03799 if (npos == find_codepoint(std_str, *pt++)) 03800 return idx; 03801 03802 } while (++idx != d_cplength); 03803 03804 } 03805 03806 return npos; 03807 } 03808 03809 03832 size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const 03833 { 03834 return find_first_of(utf8_str, idx, utf_length(utf8_str)); 03835 } 03836 03859 size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const 03860 { 03861 return find_first_not_of(utf8_str, idx, utf_length(utf8_str)); 03862 } 03863 03889 size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const 03890 { 03891 if (str_len == npos) 03892 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03893 03894 if (idx < d_cplength) 03895 { 03896 size_type encsze = encoded_size(utf8_str, str_len); 03897 03898 const utf32* pt = &ptr()[idx]; 03899 03900 do 03901 { 03902 if (npos != find_codepoint(utf8_str, encsze, *pt++)) 03903 return idx; 03904 03905 } while (++idx != d_cplength); 03906 03907 } 03908 03909 return npos; 03910 } 03911 03937 size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const 03938 { 03939 if (str_len == npos) 03940 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03941 03942 if (idx < d_cplength) 03943 { 03944 size_type encsze = encoded_size(utf8_str, str_len); 03945 03946 const utf32* pt = &ptr()[idx]; 03947 03948 do 03949 { 03950 if (npos == find_codepoint(utf8_str, encsze, *pt++)) 03951 return idx; 03952 03953 } while (++idx != d_cplength); 03954 03955 } 03956 03957 return npos; 03958 } 03959 03960 03975 size_type find_first_of(utf32 code_point, size_type idx = 0) const 03976 { 03977 return find(code_point, idx); 03978 } 03979 03996 size_type find_first_not_of(utf32 code_point, size_type idx = 0) const 03997 { 03998 if (idx < d_cplength) 03999 { 04000 do 04001 { 04002 if ((*this)[idx] != code_point) 04003 return idx; 04004 04005 } while(idx++ < d_cplength); 04006 04007 } 04008 04009 return npos; 04010 } 04011 04012 04029 size_type find_first_of(const char* cstr, size_type idx = 0) const 04030 { 04031 return find_first_of(cstr, idx, strlen(cstr)); 04032 } 04033 04034 04051 size_type find_first_not_of(const char* cstr, size_type idx = 0) const 04052 { 04053 return find_first_not_of(cstr, idx, strlen(cstr)); 04054 } 04055 04056 04076 size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const 04077 { 04078 if (chars_len == npos) 04079 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04080 04081 if (idx < d_cplength) 04082 { 04083 const utf32* pt = &ptr()[idx]; 04084 04085 do 04086 { 04087 if (npos != find_codepoint(chars, chars_len, *pt++)) 04088 return idx; 04089 04090 } while (++idx != d_cplength); 04091 04092 } 04093 04094 return npos; 04095 } 04096 04097 04117 size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const 04118 { 04119 if (chars_len == npos) 04120 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04121 04122 if (idx < d_cplength) 04123 { 04124 const utf32* pt = &ptr()[idx]; 04125 04126 do 04127 { 04128 if (npos == find_codepoint(chars, chars_len, *pt++)) 04129 return idx; 04130 04131 } while (++idx != d_cplength); 04132 04133 } 04134 04135 return npos; 04136 } 04137 04138 04140 // Find last of different code-points 04142 04156 size_type find_last_of(const String& str, size_type idx = npos) const 04157 { 04158 if (d_cplength > 0) 04159 { 04160 if (idx >= d_cplength) 04161 idx = d_cplength - 1; 04162 04163 const utf32* pt = &ptr()[idx]; 04164 04165 do 04166 { 04167 if (npos != str.find(*pt--)) 04168 return idx; 04169 04170 } while (idx-- != 0); 04171 04172 } 04173 04174 return npos; 04175 } 04176 04191 size_type find_last_not_of(const String& str, size_type idx = npos) const 04192 { 04193 if (d_cplength > 0) 04194 { 04195 if (idx >= d_cplength) 04196 idx = d_cplength - 1; 04197 04198 const utf32* pt = &ptr()[idx]; 04199 04200 do 04201 { 04202 if (npos == str.find(*pt--)) 04203 return idx; 04204 04205 } while (idx-- != 0); 04206 04207 } 04208 04209 return npos; 04210 } 04211 04212 04231 size_type find_last_of(const std::string& std_str, size_type idx = npos) const 04232 { 04233 if (d_cplength > 0) 04234 { 04235 if (idx >= d_cplength) 04236 idx = d_cplength - 1; 04237 04238 const utf32* pt = &ptr()[idx]; 04239 04240 do 04241 { 04242 if (npos != find_codepoint(std_str, *pt--)) 04243 return idx; 04244 04245 } while (idx-- != 0); 04246 04247 } 04248 04249 return npos; 04250 } 04251 04270 size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const 04271 { 04272 if (d_cplength > 0) 04273 { 04274 if (idx >= d_cplength) 04275 idx = d_cplength - 1; 04276 04277 const utf32* pt = &ptr()[idx]; 04278 04279 do 04280 { 04281 if (npos == find_codepoint(std_str, *pt--)) 04282 return idx; 04283 04284 } while (idx-- != 0); 04285 04286 } 04287 04288 return npos; 04289 } 04290 04291 04314 size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const 04315 { 04316 return find_last_of(utf8_str, idx, utf_length(utf8_str)); 04317 } 04318 04341 size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const 04342 { 04343 return find_last_not_of(utf8_str, idx, utf_length(utf8_str)); 04344 } 04345 04371 size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const 04372 { 04373 if (str_len == npos) 04374 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 04375 04376 if (d_cplength > 0) 04377 { 04378 if (idx >= d_cplength) 04379 idx = d_cplength - 1; 04380 04381 size_type encsze = encoded_size(utf8_str, str_len); 04382 04383 const utf32* pt = &ptr()[idx]; 04384 04385 do 04386 { 04387 if (npos != find_codepoint(utf8_str, encsze, *pt--)) 04388 return idx; 04389 04390 } while (idx-- != 0); 04391 04392 } 04393 04394 return npos; 04395 } 04396 04422 size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const 04423 { 04424 if (str_len == npos) 04425 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 04426 04427 if (d_cplength > 0) 04428 { 04429 if (idx >= d_cplength) 04430 idx = d_cplength - 1; 04431 04432 size_type encsze = encoded_size(utf8_str, str_len); 04433 04434 const utf32* pt = &ptr()[idx]; 04435 04436 do 04437 { 04438 if (npos == find_codepoint(utf8_str, encsze, *pt--)) 04439 return idx; 04440 04441 } while (idx-- != 0); 04442 04443 } 04444 04445 return npos; 04446 } 04447 04448 04463 size_type find_last_of(utf32 code_point, size_type idx = npos) const 04464 { 04465 return rfind(code_point, idx); 04466 } 04467 04482 size_type find_last_not_of(utf32 code_point, size_type idx = npos) const 04483 { 04484 if (d_cplength > 0) 04485 { 04486 if (idx >= d_cplength) 04487 idx = d_cplength - 1; 04488 04489 do 04490 { 04491 if ((*this)[idx] != code_point) 04492 return idx; 04493 04494 } while(idx-- != 0); 04495 04496 } 04497 04498 return npos; 04499 } 04500 04501 04518 size_type find_last_of(const char* cstr, size_type idx = npos) const 04519 { 04520 return find_last_of(cstr, idx, strlen(cstr)); 04521 } 04522 04523 04540 size_type find_last_not_of(const char* cstr, size_type idx = npos) const 04541 { 04542 return find_last_not_of(cstr, idx, strlen(cstr)); 04543 } 04544 04545 04565 size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const 04566 { 04567 if (chars_len == npos) 04568 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04569 04570 if (d_cplength > 0) 04571 { 04572 if (idx >= d_cplength) 04573 idx = d_cplength - 1; 04574 04575 const utf32* pt = &ptr()[idx]; 04576 04577 do 04578 { 04579 if (npos != find_codepoint(chars, chars_len, *pt--)) 04580 return idx; 04581 04582 } while (idx-- != 0); 04583 04584 } 04585 04586 return npos; 04587 } 04588 04589 04609 size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const 04610 { 04611 if (chars_len == npos) 04612 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04613 04614 if (d_cplength > 0) 04615 { 04616 if (idx >= d_cplength) 04617 idx = d_cplength - 1; 04618 04619 const utf32* pt = &ptr()[idx]; 04620 04621 do 04622 { 04623 if (npos == find_codepoint(chars, chars_len, *pt--)) 04624 return idx; 04625 04626 } while (idx-- != 0); 04627 04628 } 04629 04630 return npos; 04631 } 04632 04633 04635 // Substring 04637 04652 String substr(size_type idx = 0, size_type len = npos) const 04653 { 04654 if (d_cplength < idx) 04655 CEGUI_THROW(std::out_of_range("Index is out of range for this CEGUI::String")); 04656 04657 return String(*this, idx, len); 04658 } 04659 04661 // Iterator creation 04663 04670 iterator begin(void) 04671 { 04672 return iterator(ptr()); 04673 } 04674 04682 const_iterator begin(void) const 04683 { 04684 return const_iterator(ptr()); 04685 } 04686 04694 iterator end(void) 04695 { 04696 return iterator(&ptr()[d_cplength]); 04697 } 04698 04706 const_iterator end(void) const 04707 { 04708 return const_iterator(&ptr()[d_cplength]); 04709 } 04710 04718 reverse_iterator rbegin(void) 04719 { 04720 return reverse_iterator(end()); 04721 } 04722 04730 const_reverse_iterator rbegin(void) const 04731 { 04732 return const_reverse_iterator(end()); 04733 } 04734 04742 reverse_iterator rend(void) 04743 { 04744 return reverse_iterator(begin()); 04745 } 04746 04754 const_reverse_iterator rend(void) const 04755 { 04756 return const_reverse_iterator(begin()); 04757 } 04758 04759 private: 04760 /************************************************************************* 04761 Implementation Functions 04762 *************************************************************************/ 04763 // string management 04764 04765 // change size of allocated buffer so it is at least 'new_size'. 04766 // May or may not cause re-allocation and copy of buffer if size is larger 04767 // will never re-allocate to make size smaller. (see trim()) 04768 bool grow(size_type new_size); 04769 04770 // perform re-allocation to remove wasted space. 04771 void trim(void); 04772 04773 // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first). 04774 void setlen(size_type len) 04775 { 04776 d_cplength = len; 04777 ptr()[len] = (utf32)(0); 04778 } 04779 04780 // initialise string object 04781 void init(void) 04782 { 04783 d_reserve = STR_QUICKBUFF_SIZE; 04784 d_encodedbuff = 0; 04785 d_encodedbufflen = 0; 04786 d_encodeddatlen = 0; 04787 d_buffer = 0; 04788 setlen(0); 04789 } 04790 04791 // return true if the given pointer is inside the string data 04792 bool inside(utf32* inptr) 04793 { 04794 if (inptr < ptr() || ptr() + d_cplength <= inptr) 04795 return false; 04796 else 04797 return true; 04798 } 04799 04800 // compute distance between two iterators, returning a 'safe' value 04801 size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const 04802 { 04803 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2); 04804 } 04805 04806 // encoding functions 04807 // for all: 04808 // src_len is in code units, or 0 for null terminated string. 04809 // dest_len is in code units. 04810 // returns number of code units put into dest buffer. 04811 size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const 04812 { 04813 // count length for null terminated source... 04814 if (src_len == 0) 04815 { 04816 src_len = utf_length(src); 04817 } 04818 04819 size_type destCapacity = dest_len; 04820 04821 // while there is data in the source buffer, 04822 for (uint idx = 0; idx < src_len; ++idx) 04823 { 04824 utf32 cp = src[idx]; 04825 04826 // check there is enough destination buffer to receive this encoded unit (exit loop & return if not) 04827 if (destCapacity < encoded_size(cp)) 04828 { 04829 break; 04830 } 04831 04832 if (cp < 0x80) 04833 { 04834 *dest++ = (utf8)cp; 04835 --destCapacity; 04836 } 04837 else if (cp < 0x0800) 04838 { 04839 *dest++ = (utf8)((cp >> 6) | 0xC0); 04840 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04841 destCapacity -= 2; 04842 } 04843 else if (cp < 0x10000) 04844 { 04845 *dest++ = (utf8)((cp >> 12) | 0xE0); 04846 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80); 04847 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04848 destCapacity -= 3; 04849 } 04850 else 04851 { 04852 *dest++ = (utf8)((cp >> 18) | 0xF0); 04853 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80); 04854 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80); 04855 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04856 destCapacity -= 4; 04857 } 04858 04859 } 04860 04861 return dest_len - destCapacity; 04862 } 04863 04864 size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const 04865 { 04866 // count length for null terminated source... 04867 if (src_len == 0) 04868 { 04869 src_len = utf_length(src); 04870 } 04871 04872 size_type destCapacity = dest_len; 04873 04874 // while there is data in the source buffer, and space in the dest buffer 04875 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));) 04876 { 04877 utf32 cp; 04878 utf8 cu = src[idx++]; 04879 04880 if (cu < 0x80) 04881 { 04882 cp = (utf32)(cu); 04883 } 04884 else if (cu < 0xE0) 04885 { 04886 cp = ((cu & 0x1F) << 6); 04887 cp |= (src[idx++] & 0x3F); 04888 } 04889 else if (cu < 0xF0) 04890 { 04891 cp = ((cu & 0x0F) << 12); 04892 cp |= ((src[idx++] & 0x3F) << 6); 04893 cp |= (src[idx++] & 0x3F); 04894 } 04895 else 04896 { 04897 cp = ((cu & 0x07) << 18); 04898 cp |= ((src[idx++] & 0x3F) << 12); 04899 cp |= ((src[idx++] & 0x3F) << 6); 04900 cp |= (src[idx++] & 0x3F); 04901 } 04902 04903 *dest++ = cp; 04904 --destCapacity; 04905 } 04906 04907 return dest_len - destCapacity; 04908 } 04909 04910 // return the number of utf8 code units required to encode the given utf32 code point 04911 size_type encoded_size(utf32 code_point) const 04912 { 04913 if (code_point < 0x80) 04914 return 1; 04915 else if (code_point < 0x0800) 04916 return 2; 04917 else if (code_point < 0x10000) 04918 return 3; 04919 else 04920 return 4; 04921 } 04922 04923 // return number of code units required to re-encode given null-terminated utf32 data as utf8. return does not include terminating null. 04924 size_type encoded_size(const utf32* buf) const 04925 { 04926 return encoded_size(buf, utf_length(buf)); 04927 } 04928 04929 // return number of code units required to re-encode given utf32 data as utf8. len is number of code units in 'buf'. 04930 size_type encoded_size(const utf32* buf, size_type len) const 04931 { 04932 size_type count = 0; 04933 04934 while (len--) 04935 { 04936 count += encoded_size(*buf++); 04937 } 04938 04939 return count; 04940 } 04941 04942 // return number of utf32 code units required to re-encode given utf8 data as utf32. return does not include terminating null. 04943 size_type encoded_size(const utf8* buf) const 04944 { 04945 return encoded_size(buf, utf_length(buf)); 04946 } 04947 04948 // return number of utf32 code units required to re-encode given utf8 data as utf32. len is number of code units in 'buf'. 04949 size_type encoded_size(const utf8* buf, size_type len) const 04950 { 04951 utf8 tcp; 04952 size_type count = 0; 04953 04954 while (len--) 04955 { 04956 tcp = *buf++; 04957 ++count; 04958 size_type size = 0; 04959 04960 if (tcp < 0x80) 04961 { 04962 } 04963 else if (tcp < 0xE0) 04964 { 04965 size = 1; 04966 ++buf; 04967 } 04968 else if (tcp < 0xF0) 04969 { 04970 size = 2; 04971 buf += 2; 04972 } 04973 else 04974 { 04975 size = 3; 04976 buf += 3; 04977 } 04978 04979 if (len >= size) 04980 len -= size; 04981 else 04982 break; 04983 } 04984 04985 return count; 04986 } 04987 04988 // return number of code units in a null terminated string 04989 size_type utf_length(const utf8* utf8_str) const 04990 { 04991 size_type cnt = 0; 04992 while (*utf8_str++) 04993 cnt++; 04994 04995 return cnt; 04996 } 04997 04998 // return number of code units in a null terminated string 04999 size_type utf_length(const utf32* utf32_str) const 05000 { 05001 size_type cnt = 0; 05002 while (*utf32_str++) 05003 cnt++; 05004 05005 return cnt; 05006 } 05007 05008 // build an internal buffer with the string encoded as utf8 (remains valid until string is modified). 05009 utf8* build_utf8_buff(void) const; 05010 05011 // compare two utf32 buffers 05012 int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const 05013 { 05014 if (!cp_count) 05015 return 0; 05016 05017 while ((--cp_count) && (*buf1 == *buf2)) 05018 buf1++, buf2++; 05019 05020 return *buf1 - *buf2; 05021 } 05022 05023 // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF) 05024 int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const 05025 { 05026 if (!cp_count) 05027 return 0; 05028 05029 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2)))) 05030 buf1++, buf2++; 05031 05032 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2)); 05033 } 05034 05035 // compare utf32 buffer with encoded utf8 data 05036 int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const 05037 { 05038 if (!cp_count) 05039 return 0; 05040 05041 utf32 cp; 05042 utf8 cu; 05043 05044 do 05045 { 05046 cu = *buf2++; 05047 05048 if (cu < 0x80) 05049 { 05050 cp = (utf32)(cu); 05051 } 05052 else if (cu < 0xE0) 05053 { 05054 cp = ((cu & 0x1F) << 6); 05055 cp |= (*buf2++ & 0x3F); 05056 } 05057 else if (cu < 0xF0) 05058 { 05059 cp = ((cu & 0x0F) << 12); 05060 cp |= ((*buf2++ & 0x3F) << 6); 05061 cp |= (*buf2++ & 0x3F); 05062 } 05063 else 05064 { 05065 cp = ((cu & 0x07) << 18); 05066 cp |= ((*buf2++ & 0x3F) << 12); 05067 cp |= ((*buf2++ & 0x3F) << 6); 05068 cp |= (*buf2++ & 0x3F); 05069 } 05070 05071 } while ((*buf1++ == cp) && (--cp_count)); 05072 05073 return (*--buf1) - cp; 05074 } 05075 05076 // return index of first occurrence of 'code_point' in std::string 'str', or npos if none 05077 size_type find_codepoint(const std::string& str, utf32 code_point) const 05078 { 05079 size_type idx = 0, sze = (size_type)str.size(); 05080 05081 while (idx != sze) 05082 { 05083 if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx]))) 05084 return idx; 05085 05086 ++idx; 05087 } 05088 05089 return npos; 05090 } 05091 05092 // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none. len is in code points. 05093 size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const 05094 { 05095 size_type idx = 0; 05096 05097 utf32 cp; 05098 utf8 cu; 05099 05100 while (idx != len) { 05101 cu = *str++; 05102 05103 if (cu < 0x80) 05104 { 05105 cp = (utf32)(cu); 05106 } 05107 else if (cu < 0xE0) 05108 { 05109 cp = ((cu & 0x1F) << 6); 05110 cp |= (*str++ & 0x3F); 05111 } 05112 else if (cu < 0xF0) 05113 { 05114 cp = ((cu & 0x0F) << 12); 05115 cp |= ((*str++ & 0x3F) << 6); 05116 cp |= (*str++ & 0x3F); 05117 } 05118 else 05119 { 05120 cp = ((cu & 0x07) << 18); 05121 cp |= ((*str++ & 0x3F) << 12); 05122 cp |= ((*str++ & 0x3F) << 6); 05123 cp |= (*str++ & 0x3F); 05124 } 05125 05126 if (code_point == cp) 05127 return idx; 05128 05129 ++idx; 05130 } 05131 05132 return npos; 05133 } 05134 05135 05136 // return index of first occurrence of 'code_point' in char array 'chars', or npos if none 05137 size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const 05138 { 05139 for (size_type idx = 0; idx != chars_len; ++idx) 05140 { 05141 if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx]))) 05142 return idx; 05143 } 05144 05145 return npos; 05146 } 05147 05148 }; 05149 05150 05152 // Comparison operators 05154 05158 bool CEGUIEXPORT operator==(const String& str1, const String& str2); 05159 05164 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str); 05165 05170 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str); 05171 05176 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str); 05177 05182 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str); 05183 05188 bool CEGUIEXPORT operator!=(const String& str1, const String& str2); 05189 05194 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str); 05195 05200 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str); 05201 05206 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str); 05207 05212 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str); 05213 05218 bool CEGUIEXPORT operator<(const String& str1, const String& str2); 05219 05224 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str); 05225 05230 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str); 05231 05236 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str); 05237 05242 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str); 05243 05248 bool CEGUIEXPORT operator>(const String& str1, const String& str2); 05249 05254 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str); 05255 05260 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str); 05261 05266 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str); 05267 05272 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str); 05273 05278 bool CEGUIEXPORT operator<=(const String& str1, const String& str2); 05279 05284 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str); 05285 05290 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str); 05291 05296 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str); 05297 05302 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str); 05303 05308 bool CEGUIEXPORT operator>=(const String& str1, const String& str2); 05309 05314 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str); 05315 05320 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str); 05321 05326 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str); 05327 05332 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str); 05333 05338 bool CEGUIEXPORT operator==(const String& str, const char* c_str); 05339 05344 bool CEGUIEXPORT operator==(const char* c_str, const String& str); 05345 05350 bool CEGUIEXPORT operator!=(const String& str, const char* c_str); 05351 05356 bool CEGUIEXPORT operator!=(const char* c_str, const String& str); 05357 05362 bool CEGUIEXPORT operator<(const String& str, const char* c_str); 05363 05368 bool CEGUIEXPORT operator<(const char* c_str, const String& str); 05369 05374 bool CEGUIEXPORT operator>(const String& str, const char* c_str); 05375 05380 bool CEGUIEXPORT operator>(const char* c_str, const String& str); 05381 05386 bool CEGUIEXPORT operator<=(const String& str, const char* c_str); 05387 05392 bool CEGUIEXPORT operator<=(const char* c_str, const String& str); 05393 05398 bool CEGUIEXPORT operator>=(const String& str, const char* c_str); 05399 05404 bool CEGUIEXPORT operator>=(const char* c_str, const String& str); 05405 05407 // Concatenation operator functions 05409 05424 String CEGUIEXPORT operator+(const String& str1, const String& str2); 05425 05441 String CEGUIEXPORT operator+(const String& str, const std::string& std_str); 05442 05458 String CEGUIEXPORT operator+(const std::string& std_str, const String& str); 05459 05475 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str); 05476 05492 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str); 05493 05509 String CEGUIEXPORT operator+(const String& str, utf32 code_point); 05510 05526 String CEGUIEXPORT operator+(utf32 code_point, const String& str); 05527 05543 String CEGUIEXPORT operator+(const String& str, const char* c_str); 05544 05560 String CEGUIEXPORT operator+(const char* c_str, const String& str); 05561 05562 05564 // Output (stream) functions 05566 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str); 05567 05568 05570 // Modifying operations 05572 05585 void CEGUIEXPORT swap(String& str1, String& str2); 05586 05587 05588 } // End of CEGUI namespace section 05589 05590 05591 #endif // end of guard _CEGUIString_h_