Crazy Eddie's GUI System
0.8.4
|
00001 /*********************************************************************** 00002 created: 26/2/2004 00003 author: Paul D Turner 00004 00005 purpose: Defines string class used within the GUI system. 00006 *************************************************************************/ 00007 /*************************************************************************** 00008 * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team 00009 * 00010 * Permission is hereby granted, free of charge, to any person obtaining 00011 * a copy of this software and associated documentation files (the 00012 * "Software"), to deal in the Software without restriction, including 00013 * without limitation the rights to use, copy, modify, merge, publish, 00014 * distribute, sublicense, and/or sell copies of the Software, and to 00015 * permit persons to whom the Software is furnished to do so, subject to 00016 * the following conditions: 00017 * 00018 * The above copyright notice and this permission notice shall be 00019 * included in all copies or substantial portions of the Software. 00020 * 00021 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00022 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00023 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00024 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 00025 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00026 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00027 * OTHER DEALINGS IN THE SOFTWARE. 00028 ***************************************************************************/ 00029 #ifndef _String_h_ 00030 #define _String_h_ 00031 00032 #include "CEGUI/Base.h" 00033 #include <cstring> 00034 #include <stdexcept> 00035 #include <cstddef> 00036 00037 // Start of CEGUI namespace section 00038 namespace CEGUI 00039 { 00040 /************************************************************************* 00041 Basic Types 00042 *************************************************************************/ 00043 typedef uint8 utf8; 00044 //typedef uint16 utf16; // removed typedef to prevent usage, as utf16 is not supported (yet) 00045 typedef uint32 utf32; 00046 00047 #if CEGUI_STRING_CLASS == CEGUI_STRING_CLASS_UNICODE 00048 00050 typedef utf8 encoded_char; 00051 00052 #define CEGUI_STR_QUICKBUFF_SIZE 32 00053 00062 class CEGUIEXPORT String : 00063 public AllocatedObject<String> 00064 { 00065 public: 00066 /************************************************************************* 00067 Integral Types 00068 *************************************************************************/ 00069 typedef utf32 value_type; 00070 typedef size_t size_type; 00071 typedef std::ptrdiff_t difference_type; 00072 typedef utf32& reference; 00073 typedef const utf32& const_reference; 00074 typedef utf32* pointer; 00075 typedef const utf32* const_pointer; 00076 00077 static const size_type npos; 00078 00079 private: 00080 /************************************************************************* 00081 Implementation data 00082 *************************************************************************/ 00083 size_type d_cplength; 00084 size_type d_reserve; 00085 00086 mutable utf8* d_encodedbuff; 00087 mutable size_type d_encodeddatlen; 00088 mutable size_type d_encodedbufflen; 00089 00090 utf32 d_quickbuff[CEGUI_STR_QUICKBUFF_SIZE]; 00091 utf32* d_buffer; 00092 00093 public: 00094 /************************************************************************* 00095 Iterator Classes 00096 *************************************************************************/ 00098 class iterator : public std::iterator<std::random_access_iterator_tag, utf32> 00099 { 00100 public: 00101 iterator() : d_ptr(0) {} 00102 explicit iterator(utf32* const ptr) : d_ptr(ptr) {} 00103 00104 utf32& operator*() const 00105 { 00106 return *d_ptr; 00107 } 00108 00109 utf32* operator->() const 00110 { 00111 return &**this; 00112 } 00113 00114 String::iterator& operator++() 00115 { 00116 ++d_ptr; 00117 return *this; 00118 } 00119 00120 String::iterator operator++(int) 00121 { 00122 String::iterator temp = *this; 00123 ++*this; 00124 return temp; 00125 } 00126 00127 String::iterator& operator--() 00128 { 00129 --d_ptr; 00130 return *this; 00131 } 00132 00133 String::iterator operator--(int) 00134 { 00135 String::iterator temp = *this; 00136 --*this; 00137 return temp; 00138 } 00139 00140 String::iterator& operator+=(difference_type offset) 00141 { 00142 d_ptr += offset; 00143 return *this; 00144 } 00145 00146 String::iterator operator+(difference_type offset) const 00147 { 00148 String::iterator temp = *this; 00149 return temp += offset; 00150 } 00151 00152 String::iterator& operator-=(difference_type offset) 00153 { 00154 return *this += -offset; 00155 } 00156 00157 String::iterator operator-(difference_type offset) const 00158 { 00159 String::iterator temp = *this; 00160 return temp -= offset; 00161 } 00162 00163 utf32& operator[](difference_type offset) const 00164 { 00165 return *(*this + offset); 00166 } 00167 00168 friend difference_type operator-(const String::iterator& lhs, 00169 const String::iterator& rhs) 00170 { return lhs.d_ptr - rhs.d_ptr; } 00171 00172 friend String::iterator operator+(difference_type offset, const String::iterator& iter) 00173 { return iter + offset; } 00174 00175 friend bool operator==(const String::iterator& lhs, 00176 const String::iterator& rhs) 00177 { return lhs.d_ptr == rhs.d_ptr; } 00178 00179 friend bool operator!=(const String::iterator& lhs, 00180 const String::iterator& rhs) 00181 { return lhs.d_ptr != rhs.d_ptr; } 00182 00183 friend bool operator<(const String::iterator& lhs, 00184 const String::iterator& rhs) 00185 { return lhs.d_ptr < rhs.d_ptr; } 00186 00187 friend bool operator>(const String::iterator& lhs, 00188 const String::iterator& rhs) 00189 { return lhs.d_ptr > rhs.d_ptr; } 00190 00191 friend bool operator<=(const String::iterator& lhs, 00192 const String::iterator& rhs) 00193 { return lhs.d_ptr <= rhs.d_ptr; } 00194 00195 friend bool operator>=(const String::iterator& lhs, 00196 const String::iterator& rhs) 00197 { return lhs.d_ptr >= rhs.d_ptr; } 00198 00199 utf32* d_ptr; 00200 }; 00201 00203 class const_iterator : public std::iterator<std::random_access_iterator_tag, const utf32> 00204 { 00205 public: 00206 const_iterator() : d_ptr(0) {} 00207 explicit const_iterator(const utf32* const ptr) : d_ptr(ptr) {} 00208 const_iterator(const String::iterator& iter) : d_ptr(iter.d_ptr) {} 00209 00210 const utf32& operator*() const 00211 { 00212 return *d_ptr; 00213 } 00214 00215 const utf32* operator->() const 00216 { 00217 return &**this; 00218 } 00219 00220 String::const_iterator& operator++() 00221 { 00222 ++d_ptr; 00223 return *this; 00224 } 00225 00226 String::const_iterator operator++(int) 00227 { 00228 String::const_iterator temp = *this; 00229 ++*this; 00230 return temp; 00231 } 00232 00233 String::const_iterator& operator--() 00234 { 00235 --d_ptr; 00236 return *this; 00237 } 00238 00239 String::const_iterator operator--(int) 00240 { 00241 String::const_iterator temp = *this; 00242 --*this; 00243 return temp; 00244 } 00245 00246 String::const_iterator& operator+=(difference_type offset) 00247 { 00248 d_ptr += offset; 00249 return *this; 00250 } 00251 00252 String::const_iterator operator+(difference_type offset) const 00253 { 00254 String::const_iterator temp = *this; 00255 return temp += offset; 00256 } 00257 00258 String::const_iterator& operator-=(difference_type offset) 00259 { 00260 return *this += -offset; 00261 } 00262 00263 String::const_iterator operator-(difference_type offset) const 00264 { 00265 String::const_iterator temp = *this; 00266 return temp -= offset; 00267 } 00268 00269 const utf32& operator[](difference_type offset) const 00270 { 00271 return *(*this + offset); 00272 } 00273 00274 String::const_iterator& operator=(const String::iterator& iter) 00275 { 00276 d_ptr = iter.d_ptr; 00277 return *this; 00278 } 00279 00280 friend String::const_iterator operator+(difference_type offset, const String::const_iterator& iter) 00281 { return iter + offset; } 00282 00283 friend difference_type operator-(const String::const_iterator& lhs, 00284 const String::const_iterator& rhs) 00285 { return lhs.d_ptr - rhs.d_ptr; } 00286 00287 friend bool operator==(const String::const_iterator& lhs, 00288 const String::const_iterator& rhs) 00289 { return lhs.d_ptr == rhs.d_ptr; } 00290 00291 friend bool operator!=(const String::const_iterator& lhs, 00292 const String::const_iterator& rhs) 00293 { return lhs.d_ptr != rhs.d_ptr; } 00294 00295 friend bool operator<(const String::const_iterator& lhs, 00296 const String::const_iterator& rhs) 00297 { return lhs.d_ptr < rhs.d_ptr; } 00298 00299 friend bool operator>(const String::const_iterator& lhs, 00300 const String::const_iterator& rhs) 00301 { return lhs.d_ptr > rhs.d_ptr; } 00302 00303 friend bool operator<=(const String::const_iterator& lhs, 00304 const String::const_iterator& rhs) 00305 { return lhs.d_ptr <= rhs.d_ptr; } 00306 00307 friend bool operator>=(const String::const_iterator& lhs, 00308 const String::const_iterator& rhs) 00309 { return lhs.d_ptr >= rhs.d_ptr; } 00310 00311 const utf32* d_ptr; 00312 }; 00313 00318 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION))) 00319 typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator; 00320 #else 00321 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00322 #endif 00323 00328 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION))) 00329 typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator; 00330 #else 00331 typedef std::reverse_iterator<iterator> reverse_iterator; 00332 #endif 00333 00334 public: 00336 // Default Construction and Destructor 00338 00342 String(void) 00343 { 00344 init(); 00345 } 00346 00351 ~String(void); 00352 00354 // Construction via CEGUI::String 00356 00366 String(const String& str) 00367 { 00368 init(); 00369 assign(str); 00370 } 00371 00372 00389 String(const String& str, size_type str_idx, size_type str_num = npos) 00390 { 00391 init(); 00392 assign(str, str_idx, str_num); 00393 } 00394 00396 // Construction via std::string 00398 00414 String(const std::string& std_str) 00415 { 00416 init(); 00417 assign(std_str); 00418 } 00419 00442 String(const std::string& std_str, size_type str_idx, size_type str_num = npos) 00443 { 00444 init(); 00445 assign(std_str, str_idx, str_num); 00446 } 00447 00448 00450 // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid) 00452 00470 String(const utf8* utf8_str) 00471 { 00472 init(); 00473 assign(utf8_str); 00474 } 00475 00502 String(const utf8* utf8_str, size_type chars_len) 00503 { 00504 init(); 00505 assign(utf8_str, chars_len); 00506 } 00507 00509 // Construction via code-point (using a UTF-32 code unit) 00511 00526 String(size_type num, utf32 code_point) 00527 { 00528 init(); 00529 assign(num, code_point); 00530 } 00531 00533 // Construction via iterator 00535 // Create string with characters in the range [beg, end) 00549 String(const_iterator iter_beg, const_iterator iter_end) 00550 { 00551 init(); 00552 append(iter_beg, iter_end); 00553 } 00554 00555 00557 // Construction via c-string 00559 00571 String(const char* cstr) 00572 { 00573 init(); 00574 assign(cstr); 00575 } 00576 00592 String(const char* chars, size_type chars_len) 00593 { 00594 init(); 00595 assign(chars, chars_len); 00596 } 00597 00598 00600 // Size operations 00602 00609 size_type size(void) const 00610 { 00611 return d_cplength; 00612 } 00613 00621 size_type length(void) const 00622 { 00623 return d_cplength; 00624 } 00625 00633 bool empty(void) const 00634 { 00635 return (d_cplength == 0); 00636 } 00637 00647 size_type max_size(void) const 00648 { 00649 return (((size_type)-1) / sizeof(utf32)); 00650 } 00651 00653 // Capacity Operations 00655 // return the number of code points the string could hold without re-allocation 00656 // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!) 00665 size_type capacity(void) const 00666 { 00667 return d_reserve - 1; 00668 } 00669 00670 // reserve internal memory for at-least 'num' code-points (characters). if num is 0, request is shrink-to-fit. 00685 void reserve(size_type num = 0) 00686 { 00687 if (num == 0) 00688 trim(); 00689 else 00690 grow(num); 00691 } 00692 00694 // Comparisons 00696 00711 int compare(const String& str) const 00712 { 00713 return compare(0, d_cplength, str); 00714 } 00715 00745 int compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const 00746 { 00747 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 00748 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00749 00750 if ((len == npos) || (idx + len > d_cplength)) 00751 len = d_cplength - idx; 00752 00753 if ((str_len == npos) || (str_idx + str_len > str.d_cplength)) 00754 str_len = str.d_cplength - str_idx; 00755 00756 int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len); 00757 00758 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1; 00759 } 00760 00761 00781 int compare(const std::string& std_str) const 00782 { 00783 return compare(0, d_cplength, std_str); 00784 } 00785 00786 00820 int compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const 00821 { 00822 if (d_cplength < idx) 00823 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00824 00825 if (std_str.size() < str_idx) 00826 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 00827 00828 if ((len == npos) || (idx + len > d_cplength)) 00829 len = d_cplength - idx; 00830 00831 if ((str_len == npos) || (str_idx + str_len > std_str.size())) 00832 str_len = (size_type)std_str.size() - str_idx; 00833 00834 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len); 00835 00836 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1; 00837 } 00838 00839 00861 int compare(const utf8* utf8_str) const 00862 { 00863 return compare(0, d_cplength, utf8_str, encoded_size(utf8_str)); 00864 } 00865 00866 00896 int compare(size_type idx, size_type len, const utf8* utf8_str) const 00897 { 00898 return compare(idx, len, utf8_str, encoded_size(utf8_str)); 00899 } 00900 00934 int compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const 00935 { 00936 if (d_cplength < idx) 00937 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 00938 00939 if (str_cplen == npos) 00940 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 00941 00942 if ((len == npos) || (idx + len > d_cplength)) 00943 len = d_cplength - idx; 00944 00945 int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen); 00946 00947 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1; 00948 } 00949 00950 00966 int compare(const char* cstr) const 00967 { 00968 return compare(0, d_cplength, cstr, strlen(cstr)); 00969 } 00970 00971 00995 int compare(size_type idx, size_type len, const char* cstr) const 00996 { 00997 return compare(idx, len, cstr, strlen(cstr)); 00998 } 00999 01000 01028 int compare(size_type idx, size_type len, const char* chars, size_type chars_len) const 01029 { 01030 if (d_cplength < idx) 01031 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01032 01033 if (chars_len == npos) 01034 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 01035 01036 if ((len == npos) || (idx + len > d_cplength)) 01037 len = d_cplength - idx; 01038 01039 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len); 01040 01041 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1; 01042 } 01043 01044 01046 // Character access 01048 01062 reference operator[](size_type idx) 01063 { 01064 return (ptr()[idx]); 01065 } 01066 01081 value_type operator[](size_type idx) const 01082 { 01083 return ptr()[idx]; 01084 } 01085 01098 reference at(size_type idx) 01099 { 01100 if (d_cplength <= idx) 01101 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01102 01103 return ptr()[idx]; 01104 } 01105 01118 const_reference at(size_type idx) const 01119 { 01120 if (d_cplength <= idx) 01121 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01122 01123 return ptr()[idx]; 01124 } 01125 01126 01128 // C-Strings and arrays 01130 01143 const char* c_str(void) const 01144 { 01145 return (const char*)build_utf8_buff(); 01146 } 01147 01161 const utf8* data(void) const 01162 { 01163 return build_utf8_buff(); 01164 } 01165 01170 utf32* ptr(void) 01171 { 01172 return (d_reserve > CEGUI_STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff; 01173 } 01174 01179 const utf32* ptr(void) const 01180 { 01181 return (d_reserve > CEGUI_STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff; 01182 } 01183 01184 // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data 01185 // return number of utf8 code units placed into the buffer 01206 size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const 01207 { 01208 if (d_cplength < idx) 01209 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01210 01211 if (len == npos) 01212 len = d_cplength; 01213 01214 return encode(&ptr()[idx], buf, npos, len); 01215 } 01216 01218 // UTF8 Encoding length information 01220 // 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. 01236 size_type utf8_stream_len(size_type num = npos, size_type idx = 0) const 01237 { 01238 using namespace std; 01239 01240 if (d_cplength < idx) 01241 CEGUI_THROW(out_of_range("Index was out of range for CEGUI::String object")); 01242 01243 size_type maxlen = d_cplength - idx; 01244 01245 return encoded_size(&ptr()[idx], ceguimin(num, maxlen)); 01246 } 01247 01249 // Assignment Functions 01251 01261 String& operator=(const String& str) 01262 { 01263 return assign(str); 01264 } 01265 01284 String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos) 01285 { 01286 if (str.d_cplength < str_idx) 01287 CEGUI_THROW(std::out_of_range("Index was out of range for CEGUI::String object")); 01288 01289 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 01290 str_num = str.d_cplength - str_idx; 01291 01292 grow(str_num); 01293 setlen(str_num); 01294 memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32)); 01295 01296 return *this; 01297 } 01298 01315 String& operator=(const std::string& std_str) 01316 { 01317 return assign(std_str); 01318 } 01319 01343 String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos) 01344 { 01345 if (std_str.size() < str_idx) 01346 CEGUI_THROW(std::out_of_range("Index was out of range for std::string object")); 01347 01348 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 01349 str_num = (size_type)std_str.size() - str_idx; 01350 01351 grow(str_num); 01352 setlen(str_num); 01353 01354 while(str_num--) 01355 { 01356 ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx])); 01357 } 01358 01359 return *this; 01360 } 01361 01380 String& operator=(const utf8* utf8_str) 01381 { 01382 return assign(utf8_str, utf_length(utf8_str)); 01383 } 01384 01403 String& assign(const utf8* utf8_str) 01404 { 01405 return assign(utf8_str, utf_length(utf8_str)); 01406 } 01407 01429 String& assign(const utf8* utf8_str, size_type str_num) 01430 { 01431 if (str_num == npos) 01432 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 01433 01434 size_type enc_sze = encoded_size(utf8_str, str_num); 01435 01436 grow(enc_sze); 01437 encode(utf8_str, ptr(), d_reserve, str_num); 01438 setlen(enc_sze); 01439 return *this; 01440 } 01441 01452 String& operator=(utf32 code_point) 01453 { 01454 return assign(1, code_point); 01455 } 01456 01472 String& assign(size_type num, utf32 code_point) 01473 { 01474 if (num == npos) 01475 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 01476 01477 grow(num); 01478 setlen(num); 01479 utf32* p = ptr(); 01480 01481 while(num--) 01482 *p++ = code_point; 01483 01484 return *this; 01485 } 01486 01487 01500 String& operator=(const char* cstr) 01501 { 01502 return assign(cstr, strlen(cstr)); 01503 } 01504 01505 01518 String& assign(const char* cstr) 01519 { 01520 return assign(cstr, strlen(cstr)); 01521 } 01522 01523 01539 String& assign(const char* chars, size_type chars_len) 01540 { 01541 grow(chars_len); 01542 utf32* pt = ptr(); 01543 01544 for (size_type i = 0; i < chars_len; ++i) 01545 { 01546 *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++)); 01547 } 01548 01549 setlen(chars_len); 01550 return *this; 01551 } 01552 01553 01564 void swap(String& str) 01565 { 01566 size_type temp_len = d_cplength; 01567 d_cplength = str.d_cplength; 01568 str.d_cplength = temp_len; 01569 01570 size_type temp_res = d_reserve; 01571 d_reserve = str.d_reserve; 01572 str.d_reserve = temp_res; 01573 01574 utf32* temp_buf = d_buffer; 01575 d_buffer = str.d_buffer; 01576 str.d_buffer = temp_buf; 01577 01578 // see if we need to swap 'quick buffer' data 01579 if (temp_res <= CEGUI_STR_QUICKBUFF_SIZE) 01580 { 01581 utf32 temp_qbf[CEGUI_STR_QUICKBUFF_SIZE]; 01582 01583 memcpy(temp_qbf, d_quickbuff, CEGUI_STR_QUICKBUFF_SIZE * sizeof(utf32)); 01584 memcpy(d_quickbuff, str.d_quickbuff, CEGUI_STR_QUICKBUFF_SIZE * sizeof(utf32)); 01585 memcpy(str.d_quickbuff, temp_qbf, CEGUI_STR_QUICKBUFF_SIZE * sizeof(utf32)); 01586 } 01587 01588 } 01589 01591 // Appending Functions 01593 01605 String& operator+=(const String& str) 01606 { 01607 return append(str); 01608 } 01609 01629 String& append(const String& str, size_type str_idx = 0, size_type str_num = npos) 01630 { 01631 if (str.d_cplength < str_idx) 01632 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 01633 01634 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 01635 str_num = str.d_cplength - str_idx; 01636 01637 grow(d_cplength + str_num); 01638 memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32)); 01639 setlen(d_cplength + str_num); 01640 return *this; 01641 } 01642 01643 01660 String& operator+=(const std::string& std_str) 01661 { 01662 return append(std_str); 01663 } 01664 01688 String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos) 01689 { 01690 if (std_str.size() < str_idx) 01691 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 01692 01693 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 01694 str_num = (size_type)std_str.size() - str_idx; 01695 01696 size_type newsze = d_cplength + str_num; 01697 01698 grow(newsze); 01699 utf32* pt = &ptr()[newsze-1]; 01700 01701 while(str_num--) 01702 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num])); 01703 01704 setlen(newsze); 01705 return *this; 01706 } 01707 01708 01727 String& operator+=(const utf8* utf8_str) 01728 { 01729 return append(utf8_str, utf_length(utf8_str)); 01730 } 01731 01750 String& append(const utf8* utf8_str) 01751 { 01752 return append(utf8_str, utf_length(utf8_str)); 01753 } 01754 01755 01777 String& append(const utf8* utf8_str, size_type len) 01778 { 01779 if (len == npos) 01780 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 01781 01782 size_type encsz = encoded_size(utf8_str, len); 01783 size_type newsz = d_cplength + encsz; 01784 01785 grow(newsz); 01786 encode(utf8_str, &ptr()[d_cplength], encsz, len); 01787 setlen(newsz); 01788 01789 return *this; 01790 } 01791 01792 01805 String& operator+=(utf32 code_point) 01806 { 01807 return append(1, code_point); 01808 } 01809 01825 String& append(size_type num, utf32 code_point) 01826 { 01827 if (num == npos) 01828 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 01829 01830 size_type newsz = d_cplength + num; 01831 grow(newsz); 01832 01833 utf32* p = &ptr()[d_cplength]; 01834 01835 while(num--) 01836 *p++ = code_point; 01837 01838 setlen(newsz); 01839 01840 return *this; 01841 } 01842 01855 void push_back(utf32 code_point) 01856 { 01857 append(1, code_point); 01858 } 01859 01875 String& append(const_iterator iter_beg, const_iterator iter_end) 01876 { 01877 return replace(end(), end(), iter_beg, iter_end); 01878 } 01879 01880 01893 String& operator+=(const char* cstr) 01894 { 01895 return append(cstr, strlen(cstr)); 01896 } 01897 01898 01911 String& append(const char* cstr) 01912 { 01913 return append(cstr, strlen(cstr)); 01914 } 01915 01916 01932 String& append(const char* chars, size_type chars_len) 01933 { 01934 if (chars_len == npos) 01935 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 01936 01937 size_type newsz = d_cplength + chars_len; 01938 01939 grow(newsz); 01940 01941 utf32* pt = &ptr()[newsz-1]; 01942 01943 while(chars_len--) 01944 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 01945 01946 setlen(newsz); 01947 01948 return *this; 01949 } 01950 01951 01953 // Insertion Functions 01955 01971 String& insert(size_type idx, const String& str) 01972 { 01973 return insert(idx, str, 0, npos); 01974 } 01975 01998 String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num) 01999 { 02000 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 02001 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02002 02003 if ((str_num == npos) || (str_num > str.d_cplength - str_idx)) 02004 str_num = str.d_cplength - str_idx; 02005 02006 size_type newsz = d_cplength + str_num; 02007 grow(newsz); 02008 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02009 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32)); 02010 setlen(newsz); 02011 02012 return *this; 02013 } 02014 02035 String& insert(size_type idx, const std::string& std_str) 02036 { 02037 return insert(idx, std_str, 0, npos); 02038 } 02039 02066 String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num) 02067 { 02068 if (d_cplength < idx) 02069 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02070 02071 if (std_str.size() < str_idx) 02072 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 02073 02074 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx)) 02075 str_num = (size_type)std_str.size() - str_idx; 02076 02077 size_type newsz = d_cplength + str_num; 02078 grow(newsz); 02079 02080 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02081 02082 utf32* pt = &ptr()[idx + str_num - 1]; 02083 02084 while(str_num--) 02085 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num])); 02086 02087 setlen(newsz); 02088 02089 return *this; 02090 } 02091 02114 String& insert(size_type idx, const utf8* utf8_str) 02115 { 02116 return insert(idx, utf8_str, utf_length(utf8_str)); 02117 } 02118 02144 String& insert(size_type idx, const utf8* utf8_str, size_type len) 02145 { 02146 if (d_cplength < idx) 02147 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02148 02149 if (len == npos) 02150 CEGUI_THROW(std::length_error("Length of utf8 encoded string can not be 'npos'")); 02151 02152 size_type encsz = encoded_size(utf8_str, len); 02153 size_type newsz = d_cplength + encsz; 02154 02155 grow(newsz); 02156 memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02157 encode(utf8_str, &ptr()[idx], encsz, len); 02158 setlen(newsz); 02159 02160 return *this; 02161 } 02162 02182 String& insert(size_type idx, size_type num, utf32 code_point) 02183 { 02184 if (d_cplength < idx) 02185 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02186 02187 if (num == npos) 02188 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 02189 02190 size_type newsz = d_cplength + num; 02191 grow(newsz); 02192 02193 memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02194 02195 utf32* pt = &ptr()[idx + num - 1]; 02196 02197 while(num--) 02198 *pt-- = code_point; 02199 02200 setlen(newsz); 02201 02202 return *this; 02203 } 02204 02223 void insert(iterator pos, size_type num, utf32 code_point) 02224 { 02225 insert(safe_iter_dif(pos, begin()), num, code_point); 02226 } 02227 02243 iterator insert(iterator pos, utf32 code_point) 02244 { 02245 insert(pos, 1, code_point); 02246 return pos; 02247 } 02248 02267 void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end) 02268 { 02269 replace(iter_pos, iter_pos, iter_beg, iter_end); 02270 } 02271 02272 02289 String& insert(size_type idx, const char* cstr) 02290 { 02291 return insert(idx, cstr, strlen(cstr)); 02292 } 02293 02294 02314 String& insert(size_type idx, const char* chars, size_type chars_len) 02315 { 02316 if (d_cplength < idx) 02317 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02318 02319 if (chars_len == npos) 02320 CEGUI_THROW(std::length_error("Length of char array can not be 'npos'")); 02321 02322 size_type newsz = d_cplength + chars_len; 02323 02324 grow(newsz); 02325 memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32)); 02326 02327 utf32* pt = &ptr()[idx + chars_len - 1]; 02328 02329 while(chars_len--) 02330 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 02331 02332 setlen(newsz); 02333 02334 return *this; 02335 } 02336 02337 02339 // Erasing characters 02341 02348 void clear(void) 02349 { 02350 setlen(0); 02351 trim(); 02352 } 02353 02361 String& erase(void) 02362 { 02363 clear(); 02364 return *this; 02365 } 02366 02379 String& erase(size_type idx) 02380 { 02381 return erase(idx, 1); 02382 } 02383 02399 String& erase(size_type idx, size_type len) 02400 { 02401 // cover the no-op case. 02402 if (len == 0) 02403 return *this; 02404 02405 if (d_cplength <= idx) 02406 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02407 02408 if (len == npos) 02409 len = d_cplength - idx; 02410 02411 size_type newsz = d_cplength - len; 02412 02413 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32)); 02414 setlen(newsz); 02415 return *this; 02416 } 02417 02428 String& erase(iterator pos) 02429 { 02430 return erase(safe_iter_dif(pos, begin()), 1); 02431 } 02432 02446 String& erase(iterator iter_beg, iterator iter_end) 02447 { 02448 return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg)); 02449 } 02450 02452 // Resizing 02454 02466 void resize(size_type num) 02467 { 02468 resize(num, utf32()); 02469 } 02470 02486 void resize(size_type num, utf32 code_point) 02487 { 02488 if (num < d_cplength) 02489 { 02490 setlen(num); 02491 } 02492 else 02493 { 02494 append(num - d_cplength, code_point); 02495 } 02496 02497 } 02498 02500 // Replacing Characters 02502 02521 String& replace(size_type idx, size_type len, const String& str) 02522 { 02523 return replace(idx, len, str, 0, npos); 02524 } 02525 02547 String& replace(iterator iter_beg, iterator iter_end, const String& str) 02548 { 02549 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos); 02550 } 02551 02577 String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num) 02578 { 02579 if ((d_cplength < idx) || (str.d_cplength < str_idx)) 02580 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02581 02582 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos)) 02583 str_num = str.d_cplength - str_idx; 02584 02585 if (((len + idx) > d_cplength) || (len == npos)) 02586 len = d_cplength - idx; 02587 02588 size_type newsz = d_cplength + str_num - len; 02589 02590 grow(newsz); 02591 02592 if ((idx + len) < d_cplength) 02593 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02594 02595 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32)); 02596 setlen(newsz); 02597 02598 return *this; 02599 } 02600 02601 02625 String& replace(size_type idx, size_type len, const std::string& std_str) 02626 { 02627 return replace(idx, len, std_str, 0, npos); 02628 } 02629 02655 String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str) 02656 { 02657 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos); 02658 } 02659 02689 String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num) 02690 { 02691 if (d_cplength < idx) 02692 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02693 02694 if (std_str.size() < str_idx) 02695 CEGUI_THROW(std::out_of_range("Index is out of range for std::string")); 02696 02697 if (((str_idx + str_num) > std_str.size()) || (str_num == npos)) 02698 str_num = (size_type)std_str.size() - str_idx; 02699 02700 if (((len + idx) > d_cplength) || (len == npos)) 02701 len = d_cplength - idx; 02702 02703 size_type newsz = d_cplength + str_num - len; 02704 02705 grow(newsz); 02706 02707 if ((idx + len) < d_cplength) 02708 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02709 02710 utf32* pt = &ptr()[idx + str_num - 1]; 02711 02712 while (str_num--) 02713 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num])); 02714 02715 setlen(newsz); 02716 02717 return *this; 02718 } 02719 02720 02746 String& replace(size_type idx, size_type len, const utf8* utf8_str) 02747 { 02748 return replace(idx, len, utf8_str, utf_length(utf8_str)); 02749 } 02750 02778 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str) 02779 { 02780 return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str)); 02781 } 02782 02811 String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len) 02812 { 02813 if (d_cplength < idx) 02814 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02815 02816 if (str_len == npos) 02817 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 02818 02819 if (((len + idx) > d_cplength) || (len == npos)) 02820 len = d_cplength - idx; 02821 02822 size_type encsz = encoded_size(utf8_str, str_len); 02823 size_type newsz = d_cplength + encsz - len; 02824 02825 grow(newsz); 02826 02827 if ((idx + len) < d_cplength) 02828 memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02829 02830 encode(utf8_str, &ptr()[idx], encsz, str_len); 02831 02832 setlen(newsz); 02833 return *this; 02834 } 02835 02866 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len) 02867 { 02868 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len); 02869 } 02870 02893 String& replace(size_type idx, size_type len, size_type num, utf32 code_point) 02894 { 02895 if (d_cplength < idx) 02896 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 02897 02898 if (num == npos) 02899 CEGUI_THROW(std::length_error("Code point count can not be 'npos'")); 02900 02901 if (((len + idx) > d_cplength) || (len == npos)) 02902 len = d_cplength - idx; 02903 02904 size_type newsz = d_cplength + num - len; 02905 02906 grow(newsz); 02907 02908 if ((idx + len) < d_cplength) 02909 memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02910 02911 utf32* pt = &ptr()[idx + num - 1]; 02912 02913 while (num--) 02914 *pt-- = code_point; 02915 02916 setlen(newsz); 02917 02918 return *this; 02919 } 02920 02945 String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point) 02946 { 02947 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point); 02948 } 02949 02950 02975 String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd) 02976 { 02977 if (iter_newBeg == iter_newEnd) 02978 { 02979 erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg)); 02980 } 02981 else 02982 { 02983 size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg); 02984 size_type idx = safe_iter_dif(iter_beg, begin()); 02985 size_type len = safe_iter_dif(iter_end, iter_beg); 02986 02987 if ((len + idx) > d_cplength) 02988 len = d_cplength - idx; 02989 02990 size_type newsz = d_cplength + str_len - len; 02991 02992 grow(newsz); 02993 02994 if ((idx + len) < d_cplength) 02995 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 02996 02997 memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32)); 02998 setlen(newsz); 02999 } 03000 03001 return *this; 03002 } 03003 03004 03024 String& replace(size_type idx, size_type len, const char* cstr) 03025 { 03026 return replace(idx, len, cstr, strlen(cstr)); 03027 } 03028 03029 03051 String& replace(iterator iter_beg, iterator iter_end, const char* cstr) 03052 { 03053 return replace(iter_beg, iter_end, cstr, strlen(cstr)); 03054 } 03055 03056 03079 String& replace(size_type idx, size_type len, const char* chars, size_type chars_len) 03080 { 03081 if (d_cplength < idx) 03082 CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String")); 03083 03084 if (chars_len == npos) 03085 CEGUI_THROW(std::length_error("Length for the char array can not be 'npos'")); 03086 03087 if (((len + idx) > d_cplength) || (len == npos)) 03088 len = d_cplength - idx; 03089 03090 size_type newsz = d_cplength + chars_len - len; 03091 03092 grow(newsz); 03093 03094 if ((idx + len) < d_cplength) 03095 memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32)); 03096 03097 utf32* pt = &ptr()[idx + chars_len - 1]; 03098 03099 while (chars_len--) 03100 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len])); 03101 03102 setlen(newsz); 03103 return *this; 03104 } 03105 03106 03131 String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len) 03132 { 03133 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len); 03134 } 03135 03136 03138 // Find a code point 03140 03154 size_type find(utf32 code_point, size_type idx = 0) const 03155 { 03156 if (idx < d_cplength) 03157 { 03158 const utf32* pt = &ptr()[idx]; 03159 03160 while (idx < d_cplength) 03161 { 03162 if (*pt++ == code_point) 03163 return idx; 03164 03165 ++idx; 03166 } 03167 03168 } 03169 03170 return npos; 03171 } 03172 03187 size_type rfind(utf32 code_point, size_type idx = npos) const 03188 { 03189 if (idx >= d_cplength) 03190 idx = d_cplength - 1; 03191 03192 if (d_cplength > 0) 03193 { 03194 const utf32* pt = &ptr()[idx]; 03195 03196 do 03197 { 03198 if (*pt-- == code_point) 03199 return idx; 03200 03201 } while (idx-- != 0); 03202 03203 } 03204 03205 return npos; 03206 } 03207 03209 // Find a substring 03211 03225 size_type find(const String& str, size_type idx = 0) const 03226 { 03227 if ((str.d_cplength == 0) && (idx < d_cplength)) 03228 return idx; 03229 03230 if (idx < d_cplength) 03231 { 03232 // loop while search string could fit in to search area 03233 while (d_cplength - idx >= str.d_cplength) 03234 { 03235 if (0 == compare(idx, str.d_cplength, str)) 03236 return idx; 03237 03238 ++idx; 03239 } 03240 03241 } 03242 03243 return npos; 03244 } 03245 03260 size_type rfind(const String& str, size_type idx = npos) const 03261 { 03262 if (str.d_cplength == 0) 03263 return (idx < d_cplength) ? idx : d_cplength; 03264 03265 if (str.d_cplength <= d_cplength) 03266 { 03267 if (idx > (d_cplength - str.d_cplength)) 03268 idx = d_cplength - str.d_cplength; 03269 03270 do 03271 { 03272 if (0 == compare(idx, str.d_cplength, str)) 03273 return idx; 03274 03275 } while (idx-- != 0); 03276 03277 } 03278 03279 return npos; 03280 } 03281 03300 size_type find(const std::string& std_str, size_type idx = 0) const 03301 { 03302 std::string::size_type sze = std_str.size(); 03303 03304 if ((sze == 0) && (idx < d_cplength)) 03305 return idx; 03306 03307 if (idx < d_cplength) 03308 { 03309 // loop while search string could fit in to search area 03310 while (d_cplength - idx >= sze) 03311 { 03312 if (0 == compare(idx, (size_type)sze, std_str)) 03313 return idx; 03314 03315 ++idx; 03316 } 03317 03318 } 03319 03320 return npos; 03321 } 03322 03341 size_type rfind(const std::string& std_str, size_type idx = npos) const 03342 { 03343 std::string::size_type sze = std_str.size(); 03344 03345 if (sze == 0) 03346 return (idx < d_cplength) ? idx : d_cplength; 03347 03348 if (sze <= d_cplength) 03349 { 03350 if (idx > (d_cplength - sze)) 03351 idx = d_cplength - sze; 03352 03353 do 03354 { 03355 if (0 == compare(idx, (size_type)sze, std_str)) 03356 return idx; 03357 03358 } while (idx-- != 0); 03359 03360 } 03361 03362 return npos; 03363 } 03364 03387 size_type find(const utf8* utf8_str, size_type idx = 0) const 03388 { 03389 return find(utf8_str, idx, utf_length(utf8_str)); 03390 } 03391 03414 size_type rfind(const utf8* utf8_str, size_type idx = npos) const 03415 { 03416 return rfind(utf8_str, idx, utf_length(utf8_str)); 03417 } 03418 03444 size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const 03445 { 03446 if (str_len == npos) 03447 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03448 03449 size_type sze = encoded_size(utf8_str, str_len); 03450 03451 if ((sze == 0) && (idx < d_cplength)) 03452 return idx; 03453 03454 if (idx < d_cplength) 03455 { 03456 // loop while search string could fit in to search area 03457 while (d_cplength - idx >= sze) 03458 { 03459 if (0 == compare(idx, sze, utf8_str, sze)) 03460 return idx; 03461 03462 ++idx; 03463 } 03464 03465 } 03466 03467 return npos; 03468 } 03469 03495 size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const 03496 { 03497 if (str_len == npos) 03498 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03499 03500 size_type sze = encoded_size(utf8_str, str_len); 03501 03502 if (sze == 0) 03503 return (idx < d_cplength) ? idx : d_cplength; 03504 03505 if (sze <= d_cplength) 03506 { 03507 if (idx > (d_cplength - sze)) 03508 idx = d_cplength - sze; 03509 03510 do 03511 { 03512 if (0 == compare(idx, sze, utf8_str, sze)) 03513 return idx; 03514 03515 } while (idx-- != 0); 03516 03517 } 03518 03519 return npos; 03520 } 03521 03522 03539 size_type find(const char* cstr, size_type idx = 0) const 03540 { 03541 return find(cstr, idx, strlen(cstr)); 03542 } 03543 03544 03561 size_type rfind(const char* cstr, size_type idx = npos) const 03562 { 03563 return rfind(cstr, idx, strlen(cstr)); 03564 } 03565 03566 03586 size_type find(const char* chars, size_type idx, size_type chars_len) const 03587 { 03588 if (chars_len == npos) 03589 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 03590 03591 if ((chars_len == 0) && (idx < d_cplength)) 03592 return idx; 03593 03594 if (idx < d_cplength) 03595 { 03596 // loop while search string could fit in to search area 03597 while (d_cplength - idx >= chars_len) 03598 { 03599 if (0 == compare(idx, chars_len, chars, chars_len)) 03600 return idx; 03601 03602 ++idx; 03603 } 03604 03605 } 03606 03607 return npos; 03608 } 03609 03610 03630 size_type rfind(const char* chars, size_type idx, size_type chars_len) const 03631 { 03632 if (chars_len == npos) 03633 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 03634 03635 if (chars_len == 0) 03636 return (idx < d_cplength) ? idx : d_cplength; 03637 03638 if (chars_len <= d_cplength) 03639 { 03640 if (idx > (d_cplength - chars_len)) 03641 idx = d_cplength - chars_len; 03642 03643 do 03644 { 03645 if (0 == compare(idx, chars_len, chars, chars_len)) 03646 return idx; 03647 03648 } while (idx-- != 0); 03649 03650 } 03651 03652 return npos; 03653 } 03654 03655 03657 // Find first of different code-points 03659 03673 size_type find_first_of(const String& str, size_type idx = 0) const 03674 { 03675 if (idx < d_cplength) 03676 { 03677 const utf32* pt = &ptr()[idx]; 03678 03679 do 03680 { 03681 if (npos != str.find(*pt++)) 03682 return idx; 03683 03684 } while (++idx != d_cplength); 03685 03686 } 03687 03688 return npos; 03689 } 03690 03705 size_type find_first_not_of(const String& str, size_type idx = 0) const 03706 { 03707 if (idx < d_cplength) 03708 { 03709 const utf32* pt = &ptr()[idx]; 03710 03711 do 03712 { 03713 if (npos == str.find(*pt++)) 03714 return idx; 03715 03716 } while (++idx != d_cplength); 03717 03718 } 03719 03720 return npos; 03721 } 03722 03723 03742 size_type find_first_of(const std::string& std_str, size_type idx = 0) const 03743 { 03744 if (idx < d_cplength) 03745 { 03746 const utf32* pt = &ptr()[idx]; 03747 03748 do 03749 { 03750 if (npos != find_codepoint(std_str, *pt++)) 03751 return idx; 03752 03753 } while (++idx != d_cplength); 03754 03755 } 03756 03757 return npos; 03758 } 03759 03778 size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const 03779 { 03780 if (idx < d_cplength) 03781 { 03782 const utf32* pt = &ptr()[idx]; 03783 03784 do 03785 { 03786 if (npos == find_codepoint(std_str, *pt++)) 03787 return idx; 03788 03789 } while (++idx != d_cplength); 03790 03791 } 03792 03793 return npos; 03794 } 03795 03796 03819 size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const 03820 { 03821 return find_first_of(utf8_str, idx, utf_length(utf8_str)); 03822 } 03823 03846 size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const 03847 { 03848 return find_first_not_of(utf8_str, idx, utf_length(utf8_str)); 03849 } 03850 03876 size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const 03877 { 03878 if (str_len == npos) 03879 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03880 03881 if (idx < d_cplength) 03882 { 03883 size_type encsze = encoded_size(utf8_str, str_len); 03884 03885 const utf32* pt = &ptr()[idx]; 03886 03887 do 03888 { 03889 if (npos != find_codepoint(utf8_str, encsze, *pt++)) 03890 return idx; 03891 03892 } while (++idx != d_cplength); 03893 03894 } 03895 03896 return npos; 03897 } 03898 03924 size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const 03925 { 03926 if (str_len == npos) 03927 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 03928 03929 if (idx < d_cplength) 03930 { 03931 size_type encsze = encoded_size(utf8_str, str_len); 03932 03933 const utf32* pt = &ptr()[idx]; 03934 03935 do 03936 { 03937 if (npos == find_codepoint(utf8_str, encsze, *pt++)) 03938 return idx; 03939 03940 } while (++idx != d_cplength); 03941 03942 } 03943 03944 return npos; 03945 } 03946 03947 03962 size_type find_first_of(utf32 code_point, size_type idx = 0) const 03963 { 03964 return find(code_point, idx); 03965 } 03966 03983 size_type find_first_not_of(utf32 code_point, size_type idx = 0) const 03984 { 03985 if (idx < d_cplength) 03986 { 03987 do 03988 { 03989 if ((*this)[idx] != code_point) 03990 return idx; 03991 03992 } while(idx++ < d_cplength); 03993 03994 } 03995 03996 return npos; 03997 } 03998 03999 04016 size_type find_first_of(const char* cstr, size_type idx = 0) const 04017 { 04018 return find_first_of(cstr, idx, strlen(cstr)); 04019 } 04020 04021 04038 size_type find_first_not_of(const char* cstr, size_type idx = 0) const 04039 { 04040 return find_first_not_of(cstr, idx, strlen(cstr)); 04041 } 04042 04043 04063 size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const 04064 { 04065 if (chars_len == npos) 04066 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04067 04068 if (idx < d_cplength) 04069 { 04070 const utf32* pt = &ptr()[idx]; 04071 04072 do 04073 { 04074 if (npos != find_codepoint(chars, chars_len, *pt++)) 04075 return idx; 04076 04077 } while (++idx != d_cplength); 04078 04079 } 04080 04081 return npos; 04082 } 04083 04084 04104 size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const 04105 { 04106 if (chars_len == npos) 04107 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04108 04109 if (idx < d_cplength) 04110 { 04111 const utf32* pt = &ptr()[idx]; 04112 04113 do 04114 { 04115 if (npos == find_codepoint(chars, chars_len, *pt++)) 04116 return idx; 04117 04118 } while (++idx != d_cplength); 04119 04120 } 04121 04122 return npos; 04123 } 04124 04125 04127 // Find last of different code-points 04129 04143 size_type find_last_of(const String& str, size_type idx = npos) const 04144 { 04145 if (d_cplength > 0) 04146 { 04147 if (idx >= d_cplength) 04148 idx = d_cplength - 1; 04149 04150 const utf32* pt = &ptr()[idx]; 04151 04152 do 04153 { 04154 if (npos != str.find(*pt--)) 04155 return idx; 04156 04157 } while (idx-- != 0); 04158 04159 } 04160 04161 return npos; 04162 } 04163 04178 size_type find_last_not_of(const String& str, size_type idx = npos) const 04179 { 04180 if (d_cplength > 0) 04181 { 04182 if (idx >= d_cplength) 04183 idx = d_cplength - 1; 04184 04185 const utf32* pt = &ptr()[idx]; 04186 04187 do 04188 { 04189 if (npos == str.find(*pt--)) 04190 return idx; 04191 04192 } while (idx-- != 0); 04193 04194 } 04195 04196 return npos; 04197 } 04198 04199 04218 size_type find_last_of(const std::string& std_str, size_type idx = npos) const 04219 { 04220 if (d_cplength > 0) 04221 { 04222 if (idx >= d_cplength) 04223 idx = d_cplength - 1; 04224 04225 const utf32* pt = &ptr()[idx]; 04226 04227 do 04228 { 04229 if (npos != find_codepoint(std_str, *pt--)) 04230 return idx; 04231 04232 } while (idx-- != 0); 04233 04234 } 04235 04236 return npos; 04237 } 04238 04257 size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const 04258 { 04259 if (d_cplength > 0) 04260 { 04261 if (idx >= d_cplength) 04262 idx = d_cplength - 1; 04263 04264 const utf32* pt = &ptr()[idx]; 04265 04266 do 04267 { 04268 if (npos == find_codepoint(std_str, *pt--)) 04269 return idx; 04270 04271 } while (idx-- != 0); 04272 04273 } 04274 04275 return npos; 04276 } 04277 04278 04301 size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const 04302 { 04303 return find_last_of(utf8_str, idx, utf_length(utf8_str)); 04304 } 04305 04328 size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const 04329 { 04330 return find_last_not_of(utf8_str, idx, utf_length(utf8_str)); 04331 } 04332 04358 size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const 04359 { 04360 if (str_len == npos) 04361 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 04362 04363 if (d_cplength > 0) 04364 { 04365 if (idx >= d_cplength) 04366 idx = d_cplength - 1; 04367 04368 size_type encsze = encoded_size(utf8_str, str_len); 04369 04370 const utf32* pt = &ptr()[idx]; 04371 04372 do 04373 { 04374 if (npos != find_codepoint(utf8_str, encsze, *pt--)) 04375 return idx; 04376 04377 } while (idx-- != 0); 04378 04379 } 04380 04381 return npos; 04382 } 04383 04409 size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const 04410 { 04411 if (str_len == npos) 04412 CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'")); 04413 04414 if (d_cplength > 0) 04415 { 04416 if (idx >= d_cplength) 04417 idx = d_cplength - 1; 04418 04419 size_type encsze = encoded_size(utf8_str, str_len); 04420 04421 const utf32* pt = &ptr()[idx]; 04422 04423 do 04424 { 04425 if (npos == find_codepoint(utf8_str, encsze, *pt--)) 04426 return idx; 04427 04428 } while (idx-- != 0); 04429 04430 } 04431 04432 return npos; 04433 } 04434 04435 04450 size_type find_last_of(utf32 code_point, size_type idx = npos) const 04451 { 04452 return rfind(code_point, idx); 04453 } 04454 04469 size_type find_last_not_of(utf32 code_point, size_type idx = npos) const 04470 { 04471 if (d_cplength > 0) 04472 { 04473 if (idx >= d_cplength) 04474 idx = d_cplength - 1; 04475 04476 do 04477 { 04478 if ((*this)[idx] != code_point) 04479 return idx; 04480 04481 } while(idx-- != 0); 04482 04483 } 04484 04485 return npos; 04486 } 04487 04488 04505 size_type find_last_of(const char* cstr, size_type idx = npos) const 04506 { 04507 return find_last_of(cstr, idx, strlen(cstr)); 04508 } 04509 04510 04527 size_type find_last_not_of(const char* cstr, size_type idx = npos) const 04528 { 04529 return find_last_not_of(cstr, idx, strlen(cstr)); 04530 } 04531 04532 04552 size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const 04553 { 04554 if (chars_len == npos) 04555 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04556 04557 if (d_cplength > 0) 04558 { 04559 if (idx >= d_cplength) 04560 idx = d_cplength - 1; 04561 04562 const utf32* pt = &ptr()[idx]; 04563 04564 do 04565 { 04566 if (npos != find_codepoint(chars, chars_len, *pt--)) 04567 return idx; 04568 04569 } while (idx-- != 0); 04570 04571 } 04572 04573 return npos; 04574 } 04575 04576 04596 size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const 04597 { 04598 if (chars_len == npos) 04599 CEGUI_THROW(std::length_error("Length for char array can not be 'npos'")); 04600 04601 if (d_cplength > 0) 04602 { 04603 if (idx >= d_cplength) 04604 idx = d_cplength - 1; 04605 04606 const utf32* pt = &ptr()[idx]; 04607 04608 do 04609 { 04610 if (npos == find_codepoint(chars, chars_len, *pt--)) 04611 return idx; 04612 04613 } while (idx-- != 0); 04614 04615 } 04616 04617 return npos; 04618 } 04619 04620 04622 // Substring 04624 04639 String substr(size_type idx = 0, size_type len = npos) const 04640 { 04641 if (d_cplength < idx) 04642 CEGUI_THROW(std::out_of_range("Index is out of range for this CEGUI::String")); 04643 04644 return String(*this, idx, len); 04645 } 04646 04648 // Iterator creation 04650 04657 iterator begin(void) 04658 { 04659 return iterator(ptr()); 04660 } 04661 04669 const_iterator begin(void) const 04670 { 04671 return const_iterator(ptr()); 04672 } 04673 04681 iterator end(void) 04682 { 04683 return iterator(&ptr()[d_cplength]); 04684 } 04685 04693 const_iterator end(void) const 04694 { 04695 return const_iterator(&ptr()[d_cplength]); 04696 } 04697 04705 reverse_iterator rbegin(void) 04706 { 04707 return reverse_iterator(end()); 04708 } 04709 04717 const_reverse_iterator rbegin(void) const 04718 { 04719 return const_reverse_iterator(end()); 04720 } 04721 04729 reverse_iterator rend(void) 04730 { 04731 return reverse_iterator(begin()); 04732 } 04733 04741 const_reverse_iterator rend(void) const 04742 { 04743 return const_reverse_iterator(begin()); 04744 } 04745 04746 private: 04747 /************************************************************************* 04748 Implementation Functions 04749 *************************************************************************/ 04750 // string management 04751 04752 // change size of allocated buffer so it is at least 'new_size'. 04753 // May or may not cause re-allocation and copy of buffer if size is larger 04754 // will never re-allocate to make size smaller. (see trim()) 04755 bool grow(size_type new_size); 04756 04757 // perform re-allocation to remove wasted space. 04758 void trim(void); 04759 04760 // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first). 04761 void setlen(size_type len) 04762 { 04763 d_cplength = len; 04764 ptr()[len] = (utf32)(0); 04765 } 04766 04767 // initialise string object 04768 void init(void) 04769 { 04770 d_reserve = CEGUI_STR_QUICKBUFF_SIZE; 04771 d_encodedbuff = 0; 04772 d_encodedbufflen = 0; 04773 d_encodeddatlen = 0; 04774 d_buffer = 0; 04775 setlen(0); 04776 } 04777 04778 // return true if the given pointer is inside the string data 04779 bool inside(utf32* inptr) 04780 { 04781 if (inptr < ptr() || ptr() + d_cplength <= inptr) 04782 return false; 04783 else 04784 return true; 04785 } 04786 04787 // compute distance between two iterators, returning a 'safe' value 04788 size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const 04789 { 04790 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2); 04791 } 04792 04793 // encoding functions 04794 // for all: 04795 // src_len is in code units, or 0 for null terminated string. 04796 // dest_len is in code units. 04797 // returns number of code units put into dest buffer. 04798 size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const 04799 { 04800 // count length for null terminated source... 04801 if (src_len == 0) 04802 { 04803 src_len = utf_length(src); 04804 } 04805 04806 size_type destCapacity = dest_len; 04807 04808 // while there is data in the source buffer, 04809 for (uint idx = 0; idx < src_len; ++idx) 04810 { 04811 utf32 cp = src[idx]; 04812 04813 // check there is enough destination buffer to receive this encoded unit (exit loop & return if not) 04814 if (destCapacity < encoded_size(cp)) 04815 { 04816 break; 04817 } 04818 04819 if (cp < 0x80) 04820 { 04821 *dest++ = (utf8)cp; 04822 --destCapacity; 04823 } 04824 else if (cp < 0x0800) 04825 { 04826 *dest++ = (utf8)((cp >> 6) | 0xC0); 04827 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04828 destCapacity -= 2; 04829 } 04830 else if (cp < 0x10000) 04831 { 04832 *dest++ = (utf8)((cp >> 12) | 0xE0); 04833 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80); 04834 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04835 destCapacity -= 3; 04836 } 04837 else 04838 { 04839 *dest++ = (utf8)((cp >> 18) | 0xF0); 04840 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80); 04841 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80); 04842 *dest++ = (utf8)((cp & 0x3F) | 0x80); 04843 destCapacity -= 4; 04844 } 04845 04846 } 04847 04848 return dest_len - destCapacity; 04849 } 04850 04851 size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const 04852 { 04853 // count length for null terminated source... 04854 if (src_len == 0) 04855 { 04856 src_len = utf_length(src); 04857 } 04858 04859 size_type destCapacity = dest_len; 04860 04861 // while there is data in the source buffer, and space in the dest buffer 04862 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));) 04863 { 04864 utf32 cp; 04865 utf8 cu = src[idx++]; 04866 04867 if (cu < 0x80) 04868 { 04869 cp = (utf32)(cu); 04870 } 04871 else if (cu < 0xE0) 04872 { 04873 cp = ((cu & 0x1F) << 6); 04874 cp |= (src[idx++] & 0x3F); 04875 } 04876 else if (cu < 0xF0) 04877 { 04878 cp = ((cu & 0x0F) << 12); 04879 cp |= ((src[idx++] & 0x3F) << 6); 04880 cp |= (src[idx++] & 0x3F); 04881 } 04882 else 04883 { 04884 cp = ((cu & 0x07) << 18); 04885 cp |= ((src[idx++] & 0x3F) << 12); 04886 cp |= ((src[idx++] & 0x3F) << 6); 04887 cp |= (src[idx++] & 0x3F); 04888 } 04889 04890 *dest++ = cp; 04891 --destCapacity; 04892 } 04893 04894 return dest_len - destCapacity; 04895 } 04896 04897 // return the number of utf8 code units required to encode the given utf32 code point 04898 size_type encoded_size(utf32 code_point) const 04899 { 04900 if (code_point < 0x80) 04901 return 1; 04902 else if (code_point < 0x0800) 04903 return 2; 04904 else if (code_point < 0x10000) 04905 return 3; 04906 else 04907 return 4; 04908 } 04909 04910 // return number of code units required to re-encode given null-terminated utf32 data as utf8. return does not include terminating null. 04911 size_type encoded_size(const utf32* buf) const 04912 { 04913 return encoded_size(buf, utf_length(buf)); 04914 } 04915 04916 // return number of code units required to re-encode given utf32 data as utf8. len is number of code units in 'buf'. 04917 size_type encoded_size(const utf32* buf, size_type len) const 04918 { 04919 size_type count = 0; 04920 04921 while (len--) 04922 { 04923 count += encoded_size(*buf++); 04924 } 04925 04926 return count; 04927 } 04928 04929 // return number of utf32 code units required to re-encode given utf8 data as utf32. return does not include terminating null. 04930 size_type encoded_size(const utf8* buf) const 04931 { 04932 return encoded_size(buf, utf_length(buf)); 04933 } 04934 04935 // return number of utf32 code units required to re-encode given utf8 data as utf32. len is number of code units in 'buf'. 04936 size_type encoded_size(const utf8* buf, size_type len) const 04937 { 04938 utf8 tcp; 04939 size_type count = 0; 04940 04941 while (len--) 04942 { 04943 tcp = *buf++; 04944 ++count; 04945 size_type size = 0; 04946 04947 if (tcp < 0x80) 04948 { 04949 } 04950 else if (tcp < 0xE0) 04951 { 04952 size = 1; 04953 ++buf; 04954 } 04955 else if (tcp < 0xF0) 04956 { 04957 size = 2; 04958 buf += 2; 04959 } 04960 else 04961 { 04962 size = 3; 04963 buf += 3; 04964 } 04965 04966 if (len >= size) 04967 len -= size; 04968 else 04969 break; 04970 } 04971 04972 return count; 04973 } 04974 04975 // return number of code units in a null terminated string 04976 size_type utf_length(const utf8* utf8_str) const 04977 { 04978 size_type cnt = 0; 04979 while (*utf8_str++) 04980 cnt++; 04981 04982 return cnt; 04983 } 04984 04985 // return number of code units in a null terminated string 04986 size_type utf_length(const utf32* utf32_str) const 04987 { 04988 size_type cnt = 0; 04989 while (*utf32_str++) 04990 cnt++; 04991 04992 return cnt; 04993 } 04994 04995 // build an internal buffer with the string encoded as utf8 (remains valid until string is modified). 04996 utf8* build_utf8_buff(void) const; 04997 04998 // compare two utf32 buffers 04999 int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const 05000 { 05001 if (!cp_count) 05002 return 0; 05003 05004 while ((--cp_count) && (*buf1 == *buf2)) 05005 buf1++, buf2++; 05006 05007 return *buf1 - *buf2; 05008 } 05009 05010 // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF) 05011 int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const 05012 { 05013 if (!cp_count) 05014 return 0; 05015 05016 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2)))) 05017 buf1++, buf2++; 05018 05019 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2)); 05020 } 05021 05022 // compare utf32 buffer with encoded utf8 data 05023 int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const 05024 { 05025 if (!cp_count) 05026 return 0; 05027 05028 utf32 cp; 05029 utf8 cu; 05030 05031 do 05032 { 05033 cu = *buf2++; 05034 05035 if (cu < 0x80) 05036 { 05037 cp = (utf32)(cu); 05038 } 05039 else if (cu < 0xE0) 05040 { 05041 cp = ((cu & 0x1F) << 6); 05042 cp |= (*buf2++ & 0x3F); 05043 } 05044 else if (cu < 0xF0) 05045 { 05046 cp = ((cu & 0x0F) << 12); 05047 cp |= ((*buf2++ & 0x3F) << 6); 05048 cp |= (*buf2++ & 0x3F); 05049 } 05050 else 05051 { 05052 cp = ((cu & 0x07) << 18); 05053 cp |= ((*buf2++ & 0x3F) << 12); 05054 cp |= ((*buf2++ & 0x3F) << 6); 05055 cp |= (*buf2++ & 0x3F); 05056 } 05057 05058 } while ((*buf1++ == cp) && (--cp_count)); 05059 05060 return (*--buf1) - cp; 05061 } 05062 05063 // return index of first occurrence of 'code_point' in std::string 'str', or npos if none 05064 size_type find_codepoint(const std::string& str, utf32 code_point) const 05065 { 05066 size_type idx = 0, sze = (size_type)str.size(); 05067 05068 while (idx != sze) 05069 { 05070 if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx]))) 05071 return idx; 05072 05073 ++idx; 05074 } 05075 05076 return npos; 05077 } 05078 05079 // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none. len is in code points. 05080 size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const 05081 { 05082 size_type idx = 0; 05083 05084 utf32 cp; 05085 utf8 cu; 05086 05087 while (idx != len) { 05088 cu = *str++; 05089 05090 if (cu < 0x80) 05091 { 05092 cp = (utf32)(cu); 05093 } 05094 else if (cu < 0xE0) 05095 { 05096 cp = ((cu & 0x1F) << 6); 05097 cp |= (*str++ & 0x3F); 05098 } 05099 else if (cu < 0xF0) 05100 { 05101 cp = ((cu & 0x0F) << 12); 05102 cp |= ((*str++ & 0x3F) << 6); 05103 cp |= (*str++ & 0x3F); 05104 } 05105 else 05106 { 05107 cp = ((cu & 0x07) << 18); 05108 cp |= ((*str++ & 0x3F) << 12); 05109 cp |= ((*str++ & 0x3F) << 6); 05110 cp |= (*str++ & 0x3F); 05111 } 05112 05113 if (code_point == cp) 05114 return idx; 05115 05116 ++idx; 05117 } 05118 05119 return npos; 05120 } 05121 05122 05123 // return index of first occurrence of 'code_point' in char array 'chars', or npos if none 05124 size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const 05125 { 05126 for (size_type idx = 0; idx != chars_len; ++idx) 05127 { 05128 if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx]))) 05129 return idx; 05130 } 05131 05132 return npos; 05133 } 05134 05135 }; 05136 05137 05139 // Comparison operators 05141 05145 bool CEGUIEXPORT operator==(const String& str1, const String& str2); 05146 05151 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str); 05152 05157 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str); 05158 05163 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str); 05164 05169 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str); 05170 05175 bool CEGUIEXPORT operator!=(const String& str1, const String& str2); 05176 05181 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str); 05182 05187 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str); 05188 05193 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str); 05194 05199 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str); 05200 05205 bool CEGUIEXPORT operator<(const String& str1, const String& str2); 05206 05211 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str); 05212 05217 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str); 05218 05223 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str); 05224 05229 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str); 05230 05235 bool CEGUIEXPORT operator>(const String& str1, const String& str2); 05236 05241 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str); 05242 05247 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str); 05248 05253 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str); 05254 05259 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str); 05260 05265 bool CEGUIEXPORT operator<=(const String& str1, const String& str2); 05266 05271 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str); 05272 05277 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str); 05278 05283 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str); 05284 05289 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str); 05290 05295 bool CEGUIEXPORT operator>=(const String& str1, const String& str2); 05296 05301 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str); 05302 05307 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str); 05308 05313 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str); 05314 05319 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str); 05320 05325 bool CEGUIEXPORT operator==(const String& str, const char* c_str); 05326 05331 bool CEGUIEXPORT operator==(const char* c_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 05394 // Concatenation operator functions 05396 05411 String CEGUIEXPORT operator+(const String& str1, const String& str2); 05412 05428 String CEGUIEXPORT operator+(const String& str, const std::string& std_str); 05429 05445 String CEGUIEXPORT operator+(const std::string& std_str, const String& str); 05446 05462 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str); 05463 05479 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str); 05480 05496 String CEGUIEXPORT operator+(const String& str, utf32 code_point); 05497 05513 String CEGUIEXPORT operator+(utf32 code_point, const String& str); 05514 05530 String CEGUIEXPORT operator+(const String& str, const char* c_str); 05531 05547 String CEGUIEXPORT operator+(const char* c_str, const String& str); 05548 05549 05551 // Output (stream) functions 05553 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str); 05554 05555 05557 // Modifying operations 05559 05572 void CEGUIEXPORT swap(String& str1, String& str2); 05573 05579 struct StringFastLessCompare 05580 { 05581 bool operator() (const String& a, const String& b) const 05582 { 05583 const size_t la = a.length(); 05584 const size_t lb = b.length(); 05585 if (la == lb) 05586 return (memcmp(a.ptr(), b.ptr(), la * sizeof(utf32)) < 0); 05587 05588 return (la < lb); 05589 } 05590 }; 05591 05592 #else 05593 05595 typedef char encoded_char; 05596 05597 #if CEGUI_STRING_CLASS == CEGUI_STRING_CLASS_STD 05598 05599 typedef std::string String; 05600 05601 #else // CEGUI_STRING_CLASS_STD_AO 05602 05603 typedef std::basic_string<char, std::char_traits<char>, STLAllocatorWrapper<char, AllocatorConfig<STLAllocator>::Allocator> > String; 05604 05605 #endif 05606 05612 struct StringFastLessCompare 05613 { 05614 bool operator() (const String& a, const String& b) const 05615 { 05616 const size_t la = a.length(); 05617 const size_t lb = b.length(); 05618 if (la == lb) 05619 return (memcmp(a.c_str(), b.c_str(), la * sizeof(String::value_type)) < 0); 05620 05621 return (la < lb); 05622 } 05623 }; 05624 05625 #if defined(_MSC_VER) 05626 # pragma warning(disable : 4251) 05627 #endif 05628 05629 #endif 05630 05631 } // End of CEGUI namespace section 05632 05633 05634 #endif // end of guard _CEGUIString_h_