00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef _CEGUIString_h_
00027 #define _CEGUIString_h_
00028
00029 #include "CEGUIBase.h"
00030 #include <string>
00031 #include <string.h>
00032 #include <stdexcept>
00033
00034
00035 namespace CEGUI
00036 {
00037 #define STR_QUICKBUFF_SIZE 32
00038
00039
00040
00041 typedef uint8 utf8;
00042
00043 typedef uint32 utf32;
00044
00053 class CEGUIEXPORT String
00054 {
00055 public:
00056
00057
00058
00059 typedef utf32 value_type;
00060 typedef size_t size_type;
00061 typedef ptrdiff_t difference_type;
00062 typedef utf32& reference;
00063 typedef const utf32& const_reference;
00064 typedef utf32* pointer;
00065 typedef const utf32* const_pointer;
00066
00067 static const size_type npos;
00068
00069 private:
00070
00071
00072
00073 size_type d_cplength;
00074 size_type d_reserve;
00075
00076 mutable utf8* d_encodedbuff;
00077 mutable size_type d_encodeddatlen;
00078 mutable size_type d_encodedbufflen;
00079
00080 utf32 d_quickbuff[STR_QUICKBUFF_SIZE];
00081 utf32* d_buffer;
00082
00083 public:
00084
00085
00086
00091 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00092 class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32>
00093 #else
00094 class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32, std::ptrdiff_t, const utf32*, const utf32&>
00095 #endif
00096 {
00097
00098 public:
00100
00102 const utf32* d_ptr;
00103
00104
00106
00108 const_iterator(void)
00109 {
00110 d_ptr = 0;
00111 }
00112 const_iterator(const_pointer ptr)
00113 {
00114 d_ptr = ptr;
00115 }
00116
00117 const_reference operator*() const
00118 {
00119 return *d_ptr;
00120 }
00121
00122 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00123 # pragma warning (push)
00124 # pragma warning (disable : 4284)
00125 #endif
00126 const_pointer operator->() const
00127 {
00128 return &**this;
00129 }
00130
00131 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00132 # pragma warning (pop)
00133 #endif
00134
00135 const_iterator& operator++()
00136 {
00137 ++d_ptr;
00138 return *this;
00139 }
00140
00141 const_iterator operator++(int)
00142 {
00143 const_iterator temp = *this;
00144 ++*this;
00145 return temp;
00146 }
00147
00148 const_iterator& operator--()
00149 {
00150 --d_ptr;
00151 return *this;
00152 }
00153
00154 const_iterator operator--(int)
00155 {
00156 const_iterator temp = *this;
00157 --*this;
00158 return temp;
00159 }
00160
00161 const_iterator& operator+=(difference_type offset)
00162 {
00163 d_ptr += offset;
00164 return *this;
00165 }
00166
00167 const_iterator operator+(difference_type offset) const
00168 {
00169 const_iterator temp = *this;
00170 return temp += offset;
00171 }
00172
00173 const_iterator& operator-=(difference_type offset)
00174 {
00175 return *this += -offset;
00176 }
00177
00178 const_iterator operator-(difference_type offset) const
00179 {
00180 const_iterator temp = *this;
00181 return temp -= offset;
00182 }
00183
00184 difference_type operator-(const const_iterator& iter) const
00185 {
00186 return d_ptr - iter.d_ptr;
00187 }
00188
00189 const_reference operator[](difference_type offset) const
00190 {
00191 return *(*this + offset);
00192 }
00193
00194 bool operator==(const const_iterator& iter) const
00195 {
00196 return d_ptr == iter.d_ptr;
00197 }
00198
00199 bool operator!=(const const_iterator& iter) const
00200 {
00201 return !(*this == iter);
00202 }
00203
00204 bool operator<(const const_iterator& iter) const
00205 {
00206 return d_ptr < iter.d_ptr;
00207 }
00208
00209 bool operator>(const const_iterator& iter) const
00210 {
00211 return (!(iter < *this));
00212 }
00213
00214 bool operator<=(const const_iterator& iter) const
00215 {
00216 return (!(iter < *this));
00217 }
00218
00219 bool operator>=(const const_iterator& iter) const
00220 {
00221 return (!(*this < iter));
00222 }
00223
00224 friend const_iterator operator+(difference_type offset, const const_iterator& iter)
00225 {
00226 return iter + offset;
00227 }
00228
00229 };
00230
00235 class iterator : public const_iterator
00236 {
00237 public:
00238 iterator(void) {}
00239 iterator(pointer ptr) : const_iterator(ptr) {}
00240
00241
00242 reference operator*() const
00243 {
00244 return ((reference)**(const_iterator *)this);
00245 }
00246
00247 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00248 # pragma warning (push)
00249 # pragma warning (disable : 4284)
00250 #endif
00251
00252 pointer operator->() const
00253 {
00254 return &**this;
00255 }
00256
00257 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00258 # pragma warning (pop)
00259 #endif
00260
00261 iterator& operator++()
00262 {
00263 ++this->d_ptr;
00264 return *this;
00265 }
00266
00267 iterator operator++(int)
00268 {
00269 iterator temp = *this;
00270 ++*this;
00271 return temp;
00272 }
00273
00274 iterator& operator--()
00275 {
00276 --this->d_ptr;
00277 return *this;
00278 }
00279
00280 iterator operator--(int)
00281 {
00282 iterator temp = *this;
00283 --*this;
00284 return temp;
00285 }
00286
00287 iterator& operator+=(difference_type offset)
00288 {
00289 this->d_ptr += offset;
00290 return *this;
00291 }
00292
00293 iterator operator+(difference_type offset) const
00294 {
00295 iterator temp = *this;
00296 return temp + offset;
00297 }
00298
00299 iterator& operator-=(difference_type offset)
00300 {
00301 return *this += -offset;
00302 }
00303
00304 iterator operator-(difference_type offset) const
00305 {
00306 iterator temp = *this;
00307 return temp -= offset;
00308 }
00309
00310 difference_type operator-(const const_iterator& iter) const
00311 {
00312 return ((const_iterator)*this - iter);
00313 }
00314
00315 reference operator[](difference_type offset) const
00316 {
00317 return *(*this + offset);
00318 }
00319
00320 friend iterator operator+(difference_type offset, const iterator& iter)
00321 {
00322 return iter + offset;
00323 }
00324
00325 };
00326
00331 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
00332 typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator;
00333 #else
00334 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00335 #endif
00336
00341 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
00342 typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator;
00343 #else
00344 typedef std::reverse_iterator<iterator> reverse_iterator;
00345 #endif
00346
00347 public:
00349
00351
00355 String(void)
00356 {
00357 init();
00358 }
00359
00364 ~String(void);
00365
00367
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
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
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
00524
00539 String(size_type num, utf32 code_point)
00540 {
00541 init();
00542 assign(num, code_point);
00543 }
00544
00546
00548
00562 String(const_iterator iter_beg, const_iterator iter_end)
00563 {
00564 init();
00565 append(iter_beg, iter_end);
00566 }
00567
00568
00570
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
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
00668
00669
00678 size_type capacity(void) const
00679 {
00680 return d_reserve - 1;
00681 }
00682
00683
00698 void reserve(size_type num = 0)
00699 {
00700 if (num == 0)
00701 trim();
00702 else
00703 grow(num);
00704 }
00705
00707
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 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 throw std::out_of_range("Index is out of range for CEGUI::String");
00837
00838 if (std_str.size() < str_idx)
00839 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 throw std::out_of_range("Index is out of range for CEGUI::String");
00951
00952 if (str_cplen == npos)
00953 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 throw std::out_of_range("Index is out of range for CEGUI::String");
01045
01046 if (chars_len == npos)
01047 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
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 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 throw std::out_of_range("Index is out of range for CEGUI::String");
01135
01136 return ptr()[idx];
01137 }
01138
01139
01141
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
01179
01180
01201 size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const
01202 {
01203 if (d_cplength < idx)
01204 throw std::out_of_range("Index is out of range for CEGUI::String");
01205
01206 if (len == npos)
01207 len = d_cplength;
01208
01209 return encode(&ptr()[idx], buf, npos, len);
01210 }
01211
01213
01215
01231 size_type utf8_stream_len(size_type num = npos, size_type idx = 0)
01232 {
01233 using namespace std;
01234
01235 if (d_cplength < idx)
01236 throw out_of_range("Index was out of range for CEGUI::String object");
01237
01238 size_type maxlen = d_cplength - idx;
01239
01240 return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
01241 }
01242
01244
01246
01256 String& operator=(const String& str)
01257 {
01258 return assign(str);
01259 }
01260
01279 String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
01280 {
01281 if (str.d_cplength < str_idx)
01282 throw std::out_of_range("Index was out of range for CEGUI::String object");
01283
01284 if (str_num == npos)
01285 str_num = str.d_cplength - str_idx;
01286
01287 grow(str_num);
01288 setlen(str_num);
01289 memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
01290
01291 return *this;
01292 }
01293
01310 String& operator=(const std::string& std_str)
01311 {
01312 return assign(std_str);
01313 }
01314
01338 String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
01339 {
01340 if (std_str.size() < str_idx)
01341 throw std::out_of_range("Index was out of range for std::string object");
01342
01343 if (str_num == npos)
01344 str_num = (size_type)std_str.size() - str_idx;
01345
01346 grow(str_num);
01347 setlen(str_num);
01348
01349 while(str_num--)
01350 {
01351 ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
01352 }
01353
01354 return *this;
01355 }
01356
01375 String& operator=(const utf8* utf8_str)
01376 {
01377 return assign(utf8_str, utf_length(utf8_str));
01378 }
01379
01398 String& assign(const utf8* utf8_str)
01399 {
01400 return assign(utf8_str, utf_length(utf8_str));
01401 }
01402
01424 String& assign(const utf8* utf8_str, size_type str_num)
01425 {
01426 if (str_num == npos)
01427 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
01428
01429 size_type enc_sze = encoded_size(utf8_str, str_num);
01430
01431 grow(enc_sze);
01432 encode(utf8_str, ptr(), d_reserve, str_num);
01433 setlen(enc_sze);
01434 return *this;
01435 }
01436
01447 String& operator=(utf32 code_point)
01448 {
01449 return assign(1, code_point);
01450 }
01451
01467 String& assign(size_type num, utf32 code_point)
01468 {
01469 if (num == npos)
01470 throw std::length_error("Code point count can not be 'npos'");
01471
01472 grow(num);
01473 setlen(num);
01474 utf32* p = ptr();
01475
01476 while(num--)
01477 *p = code_point;
01478
01479 return *this;
01480 }
01481
01482
01495 String& operator=(const char* cstr)
01496 {
01497 return assign(cstr, strlen(cstr));
01498 }
01499
01500
01513 String& assign(const char* cstr)
01514 {
01515 return assign(cstr, strlen(cstr));
01516 }
01517
01518
01534 String& assign(const char* chars, size_type chars_len)
01535 {
01536 grow(chars_len);
01537 utf32* pt = ptr();
01538
01539 for (size_type i = 0; i < chars_len; ++i)
01540 {
01541 *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
01542 }
01543
01544 setlen(chars_len);
01545 return *this;
01546 }
01547
01548
01559 void swap(String& str)
01560 {
01561 size_type temp_len = d_cplength;
01562 d_cplength = str.d_cplength;
01563 str.d_cplength = temp_len;
01564
01565 size_type temp_res = d_reserve;
01566 d_reserve = str.d_reserve;
01567 str.d_reserve = temp_res;
01568
01569 utf32* temp_buf = d_buffer;
01570 d_buffer = str.d_buffer;
01571 str.d_buffer = temp_buf;
01572
01573
01574 if (temp_res <= STR_QUICKBUFF_SIZE)
01575 {
01576 utf32 temp_qbf[STR_QUICKBUFF_SIZE];
01577
01578 memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
01579 memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
01580 memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
01581 }
01582
01583 }
01584
01586
01588
01600 String& operator+=(const String& str)
01601 {
01602 return append(str);
01603 }
01604
01624 String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
01625 {
01626 if (str.d_cplength < str_idx)
01627 throw std::out_of_range("Index is out of range for CEGUI::String");
01628
01629 if (str_num == npos)
01630 str_num = str.d_cplength - str_idx;
01631
01632 grow(d_cplength + str_num);
01633 memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
01634 setlen(d_cplength + str_num);
01635 return *this;
01636 }
01637
01638
01655 String& operator+=(const std::string& std_str)
01656 {
01657 return append(std_str);
01658 }
01659
01683 String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
01684 {
01685 if (std_str.size() < str_idx)
01686 throw std::out_of_range("Index is out of range for std::string");
01687
01688 if (str_num == npos)
01689 str_num = (size_type)std_str.size() - str_idx;
01690
01691 size_type newsze = d_cplength + str_num;
01692
01693 grow(newsze);
01694 utf32* pt = &ptr()[newsze-1];
01695
01696 while(str_num--)
01697 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
01698
01699 setlen(newsze);
01700 return *this;
01701 }
01702
01703
01722 String& operator+=(const utf8* utf8_str)
01723 {
01724 return append(utf8_str, utf_length(utf8_str));
01725 }
01726
01745 String& append(const utf8* utf8_str)
01746 {
01747 return append(utf8_str, utf_length(utf8_str));
01748 }
01749
01750
01772 String& append(const utf8* utf8_str, size_type len)
01773 {
01774 if (len == npos)
01775 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
01776
01777 size_type encsz = encoded_size(utf8_str, len);
01778 size_type newsz = d_cplength + encsz;
01779
01780 grow(newsz);
01781 encode(utf8_str, &ptr()[d_cplength], encsz, len);
01782 setlen(newsz);
01783
01784 return *this;
01785 }
01786
01787
01800 String& operator+=(utf32 code_point)
01801 {
01802 return append(1, code_point);
01803 }
01804
01820 String& append(size_type num, utf32 code_point)
01821 {
01822 if (num == npos)
01823 throw std::length_error("Code point count can not be 'npos'");
01824
01825 size_type newsz = d_cplength + num;
01826 grow(newsz);
01827
01828 utf32* p = &ptr()[d_cplength];
01829
01830 while(num--)
01831 *p++ = code_point;
01832
01833 setlen(newsz);
01834
01835 return *this;
01836 }
01837
01850 void push_back(utf32 code_point)
01851 {
01852 append(1, code_point);
01853 }
01854
01870 String& append(const_iterator iter_beg, const_iterator iter_end)
01871 {
01872 return replace(end(), end(), iter_beg, iter_end);
01873 }
01874
01875
01888 String& operator+=(const char* cstr)
01889 {
01890 return append(cstr, strlen(cstr));
01891 }
01892
01893
01906 String& append(const char* cstr)
01907 {
01908 return append(cstr, strlen(cstr));
01909 }
01910
01911
01927 String& append(const char* chars, size_type chars_len)
01928 {
01929 if (chars_len == npos)
01930 throw std::length_error("Length for char array can not be 'npos'");
01931
01932 size_type newsz = d_cplength + chars_len;
01933
01934 grow(newsz);
01935
01936 utf32* pt = &ptr()[newsz-1];
01937
01938 while(chars_len--)
01939 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
01940
01941 setlen(newsz);
01942
01943 return *this;
01944 }
01945
01946
01948
01950
01966 String& insert(size_type idx, const String& str)
01967 {
01968 return insert(idx, str, 0, npos);
01969 }
01970
01993 String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
01994 {
01995 if ((d_cplength < idx) || (str.d_cplength < str_idx))
01996 throw std::out_of_range("Index is out of range for CEGUI::String");
01997
01998 if (str_num == npos)
01999 str_num = str.d_cplength - str_idx;
02000
02001 size_type newsz = d_cplength + str_num;
02002 grow(newsz);
02003 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02004 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02005 setlen(newsz);
02006
02007 return *this;
02008 }
02009
02030 String& insert(size_type idx, const std::string& std_str)
02031 {
02032 return insert(idx, std_str, 0, npos);
02033 }
02034
02061 String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
02062 {
02063 if (d_cplength < idx)
02064 throw std::out_of_range("Index is out of range for CEGUI::String");
02065
02066 if (std_str.size() < str_idx)
02067 throw std::out_of_range("Index is out of range for std::string");
02068
02069 if (str_num == npos)
02070 str_num = (size_type)std_str.size() - str_idx;
02071
02072 size_type newsz = d_cplength + str_num;
02073 grow(newsz);
02074
02075 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02076
02077 utf32* pt = &ptr()[idx + str_num - 1];
02078
02079 while(str_num--)
02080 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02081
02082 setlen(newsz);
02083
02084 return *this;
02085 }
02086
02109 String& insert(size_type idx, const utf8* utf8_str)
02110 {
02111 return insert(idx, utf8_str, utf_length(utf8_str));
02112 }
02113
02139 String& insert(size_type idx, const utf8* utf8_str, size_type len)
02140 {
02141 if (d_cplength < idx)
02142 throw std::out_of_range("Index is out of range for CEGUI::String");
02143
02144 if (len == npos)
02145 throw std::length_error("Length of utf8 encoded string can not be 'npos'");
02146
02147 size_type encsz = encoded_size(utf8_str, len);
02148 size_type newsz = d_cplength + encsz;
02149
02150 grow(newsz);
02151 memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02152 encode(utf8_str, &ptr()[idx], encsz, len);
02153 setlen(newsz);
02154
02155 return *this;
02156 }
02157
02177 String& insert(size_type idx, size_type num, utf32 code_point)
02178 {
02179 if (d_cplength < idx)
02180 throw std::out_of_range("Index is out of range for CEGUI::String");
02181
02182 if (num == npos)
02183 throw std::length_error("Code point count can not be 'npos'");
02184
02185 size_type newsz = d_cplength + num;
02186 grow(newsz);
02187
02188 memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02189
02190 utf32* pt = &ptr()[idx + num - 1];
02191
02192 while(num--)
02193 *pt-- = code_point;
02194
02195 setlen(newsz);
02196
02197 return *this;
02198 }
02199
02218 void insert(iterator pos, size_type num, utf32 code_point)
02219 {
02220 insert(safe_iter_dif(pos, begin()), num, code_point);
02221 }
02222
02238 iterator insert(iterator pos, utf32 code_point)
02239 {
02240 insert(pos, 1, code_point);
02241 return pos;
02242 }
02243
02262 void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
02263 {
02264 replace(iter_pos, iter_pos, iter_beg, iter_end);
02265 }
02266
02267
02284 String& insert(size_type idx, const char* cstr)
02285 {
02286 return insert(idx, cstr, strlen(cstr));
02287 }
02288
02289
02309 String& insert(size_type idx, const char* chars, size_type chars_len)
02310 {
02311 if (d_cplength < idx)
02312 throw std::out_of_range("Index is out of range for CEGUI::String");
02313
02314 if (chars_len == npos)
02315 throw std::length_error("Length of char array can not be 'npos'");
02316
02317 size_type newsz = d_cplength + chars_len;
02318
02319 grow(newsz);
02320 memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02321
02322 utf32* pt = &ptr()[idx + chars_len - 1];
02323
02324 while(chars_len--)
02325 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
02326
02327 setlen(newsz);
02328
02329 return *this;
02330 }
02331
02332
02334
02336
02343 void clear(void)
02344 {
02345 setlen(0);
02346 trim();
02347 }
02348
02356 String& erase(void)
02357 {
02358 clear();
02359 return *this;
02360 }
02361
02374 String& erase(size_type idx)
02375 {
02376 return erase(idx, 1);
02377 }
02378
02394 String& erase(size_type idx, size_type len = npos)
02395 {
02396 if (d_cplength < idx)
02397 throw std::out_of_range("Index is out of range foe CEGUI::String");
02398
02399 if (len == npos)
02400 len = d_cplength - idx;
02401
02402 size_type newsz = d_cplength - len;
02403
02404 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
02405 setlen(newsz);
02406 return *this;
02407 }
02408
02419 String& erase(iterator pos)
02420 {
02421 return erase(safe_iter_dif(pos, begin()), 1);
02422 }
02423
02437 String& erase(iterator iter_beg, iterator iter_end)
02438 {
02439 return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
02440 }
02441
02443
02445
02457 void resize(size_type num)
02458 {
02459 resize(num, utf32());
02460 }
02461
02477 void resize(size_type num, utf32 code_point)
02478 {
02479 if (num < d_cplength)
02480 {
02481 setlen(num);
02482 }
02483 else
02484 {
02485 append(num - d_cplength, code_point);
02486 }
02487
02488 }
02489
02491
02493
02512 String& replace(size_type idx, size_type len, const String& str)
02513 {
02514 return replace(idx, len, str, 0, npos);
02515 }
02516
02538 String& replace(iterator iter_beg, iterator iter_end, const String& str)
02539 {
02540 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
02541 }
02542
02568 String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
02569 {
02570 if ((d_cplength < idx) || (str.d_cplength < str_idx))
02571 throw std::out_of_range("Index is out of range for CEGUI::String");
02572
02573 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
02574 str_num = str.d_cplength - str_idx;
02575
02576 if (((len + idx) > d_cplength) || (len == npos))
02577 len = d_cplength - idx;
02578
02579 size_type newsz = d_cplength + str_num - len;
02580
02581 grow(newsz);
02582
02583 if ((idx + len) < d_cplength)
02584 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02585
02586 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02587 setlen(newsz);
02588
02589 return *this;
02590 }
02591
02592
02616 String& replace(size_type idx, size_type len, const std::string& std_str)
02617 {
02618 return replace(idx, len, std_str, 0, npos);
02619 }
02620
02646 String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
02647 {
02648 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
02649 }
02650
02680 String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
02681 {
02682 if (d_cplength < idx)
02683 throw std::out_of_range("Index is out of range for CEGUI::String");
02684
02685 if (std_str.size() < str_idx)
02686 throw std::out_of_range("Index is out of range for std::string");
02687
02688 if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
02689 str_num = (size_type)std_str.size() - str_idx;
02690
02691 if (((len + idx) > d_cplength) || (len == npos))
02692 len = d_cplength - idx;
02693
02694 size_type newsz = d_cplength + str_num - len;
02695
02696 grow(newsz);
02697
02698 if ((idx + len) < d_cplength)
02699 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02700
02701 utf32* pt = &ptr()[idx + str_num - 1];
02702
02703 while (str_num--)
02704 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02705
02706 setlen(newsz);
02707
02708 return *this;
02709 }
02710
02711
02737 String& replace(size_type idx, size_type len, const utf8* utf8_str)
02738 {
02739 return replace(idx, len, utf8_str, utf_length(utf8_str));
02740 }
02741
02769 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
02770 {
02771 return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
02772 }
02773
02802 String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
02803 {
02804 if (d_cplength < idx)
02805 throw std::out_of_range("Index is out of range for CEGUI::String");
02806
02807 if (str_len == npos)
02808 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
02809
02810 if (((len + idx) > d_cplength) || (len == npos))
02811 len = d_cplength - idx;
02812
02813 size_type encsz = encoded_size(utf8_str, str_len);
02814 size_type newsz = d_cplength + encsz - len;
02815
02816 grow(newsz);
02817
02818 if ((idx + len) < d_cplength)
02819 memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02820
02821 encode(utf8_str, &ptr()[idx], encsz, str_len);
02822
02823 setlen(newsz);
02824 return *this;
02825 }
02826
02857 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
02858 {
02859 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
02860 }
02861
02884 String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
02885 {
02886 if (d_cplength < idx)
02887 throw std::out_of_range("Index is out of range for CEGUI::String");
02888
02889 if (num == npos)
02890 throw std::length_error("Code point count can not be 'npos'");
02891
02892 if (((len + idx) > d_cplength) || (len == npos))
02893 len = d_cplength - idx;
02894
02895 size_type newsz = d_cplength + num - len;
02896
02897 grow(newsz);
02898
02899 if ((idx + len) < d_cplength)
02900 memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02901
02902 utf32* pt = &ptr()[idx + num - 1];
02903
02904 while (num--)
02905 *pt-- = code_point;
02906
02907 setlen(newsz);
02908
02909 return *this;
02910 }
02911
02936 String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
02937 {
02938 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
02939 }
02940
02941
02966 String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
02967 {
02968 if (iter_beg == iter_end)
02969 {
02970 erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
02971 }
02972 else
02973 {
02974 size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
02975 size_type idx = safe_iter_dif(iter_beg, begin());
02976 size_type len = safe_iter_dif(iter_end, iter_beg);
02977
02978 if ((len + idx) > d_cplength)
02979 len = d_cplength - idx;
02980
02981 size_type newsz = d_cplength + str_len - len;
02982
02983 grow(newsz);
02984
02985 if ((idx + len) < d_cplength)
02986 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02987
02988 memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
02989 setlen(newsz);
02990 }
02991
02992 return *this;
02993 }
02994
02995
03015 String& replace(size_type idx, size_type len, const char* cstr)
03016 {
03017 return replace(idx, len, cstr, strlen(cstr));
03018 }
03019
03020
03042 String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
03043 {
03044 return replace(iter_beg, iter_end, cstr, strlen(cstr));
03045 }
03046
03047
03070 String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
03071 {
03072 if (d_cplength < idx)
03073 throw std::out_of_range("Index is out of range for CEGUI::String");
03074
03075 if (chars_len == npos)
03076 throw std::length_error("Length for the char array can not be 'npos'");
03077
03078 if (((len + idx) > d_cplength) || (len == npos))
03079 len = d_cplength - idx;
03080
03081 size_type newsz = d_cplength + chars_len - len;
03082
03083 grow(newsz);
03084
03085 if ((idx + len) < d_cplength)
03086 memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
03087
03088 utf32* pt = &ptr()[idx + chars_len - 1];
03089
03090 while (chars_len--)
03091 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
03092
03093 setlen(newsz);
03094 return *this;
03095 }
03096
03097
03122 String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
03123 {
03124 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
03125 }
03126
03127
03129
03131
03145 size_type find(utf32 code_point, size_type idx = 0) const
03146 {
03147 if (idx < d_cplength)
03148 {
03149 const utf32* pt = &ptr()[idx];
03150
03151 while (idx < d_cplength)
03152 {
03153 if (*pt++ == code_point)
03154 return idx;
03155
03156 ++idx;
03157 }
03158
03159 }
03160
03161 return npos;
03162 }
03163
03178 size_type rfind(utf32 code_point, size_type idx = npos) const
03179 {
03180 if (idx >= d_cplength)
03181 idx = d_cplength - 1;
03182
03183 if (d_cplength > 0)
03184 {
03185 const utf32* pt = &ptr()[idx];
03186
03187 do
03188 {
03189 if (*pt-- == code_point)
03190 return idx;
03191
03192 } while (idx-- != 0);
03193
03194 }
03195
03196 return npos;
03197 }
03198
03200
03202
03216 size_type find(const String& str, size_type idx = 0) const
03217 {
03218 if ((str.d_cplength == 0) && (idx < d_cplength))
03219 return idx;
03220
03221 if (idx < d_cplength)
03222 {
03223
03224 while (d_cplength - idx >= str.d_cplength)
03225 {
03226 if (0 == compare(idx, str.d_cplength, str))
03227 return idx;
03228
03229 ++idx;
03230 }
03231
03232 }
03233
03234 return npos;
03235 }
03236
03251 size_type rfind(const String& str, size_type idx = npos) const
03252 {
03253 if (str.d_cplength == 0)
03254 return (idx < d_cplength) ? idx : d_cplength;
03255
03256 if (str.d_cplength <= d_cplength)
03257 {
03258 if (idx > (d_cplength - str.d_cplength))
03259 idx = d_cplength - str.d_cplength;
03260
03261 do
03262 {
03263 if (0 == compare(idx, str.d_cplength, str))
03264 return idx;
03265
03266 } while (idx-- != 0);
03267
03268 }
03269
03270 return npos;
03271 }
03272
03291 size_type find(const std::string& std_str, size_type idx = 0) const
03292 {
03293 std::string::size_type sze = std_str.size();
03294
03295 if ((sze == 0) && (idx < d_cplength))
03296 return idx;
03297
03298 if (idx < d_cplength)
03299 {
03300
03301 while (d_cplength - idx >= sze)
03302 {
03303 if (0 == compare(idx, (size_type)sze, std_str))
03304 return idx;
03305
03306 ++idx;
03307 }
03308
03309 }
03310
03311 return npos;
03312 }
03313
03332 size_type rfind(const std::string& std_str, size_type idx = npos) const
03333 {
03334 std::string::size_type sze = std_str.size();
03335
03336 if (sze == 0)
03337 return (idx < d_cplength) ? idx : d_cplength;
03338
03339 if (sze <= d_cplength)
03340 {
03341 if (idx > (d_cplength - sze))
03342 idx = d_cplength - sze;
03343
03344 do
03345 {
03346 if (0 == compare(idx, (size_type)sze, std_str))
03347 return idx;
03348
03349 } while (idx-- != 0);
03350
03351 }
03352
03353 return npos;
03354 }
03355
03378 size_type find(const utf8* utf8_str, size_type idx = 0) const
03379 {
03380 return find(utf8_str, idx, utf_length(utf8_str));
03381 }
03382
03405 size_type rfind(const utf8* utf8_str, size_type idx = npos) const
03406 {
03407 return rfind(utf8_str, idx, utf_length(utf8_str));
03408 }
03409
03435 size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const
03436 {
03437 if (str_len == npos)
03438 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03439
03440 size_type sze = encoded_size(utf8_str, str_len);
03441
03442 if ((sze == 0) && (idx < d_cplength))
03443 return idx;
03444
03445 if (idx < d_cplength)
03446 {
03447
03448 while (d_cplength - idx >= sze)
03449 {
03450 if (0 == compare(idx, sze, utf8_str, sze))
03451 return idx;
03452
03453 ++idx;
03454 }
03455
03456 }
03457
03458 return npos;
03459 }
03460
03486 size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
03487 {
03488 if (str_len == npos)
03489 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03490
03491 size_type sze = encoded_size(utf8_str, str_len);
03492
03493 if (sze == 0)
03494 return (idx < d_cplength) ? idx : d_cplength;
03495
03496 if (sze <= d_cplength)
03497 {
03498 if (idx > (d_cplength - sze))
03499 idx = d_cplength - sze;
03500
03501 do
03502 {
03503 if (0 == compare(idx, sze, utf8_str, sze))
03504 return idx;
03505
03506 } while (idx-- != 0);
03507
03508 }
03509
03510 return npos;
03511 }
03512
03513
03530 size_type find(const char* cstr, size_type idx = 0) const
03531 {
03532 return find(cstr, idx, strlen(cstr));
03533 }
03534
03535
03552 size_type rfind(const char* cstr, size_type idx = npos) const
03553 {
03554 return rfind(cstr, idx, strlen(cstr));
03555 }
03556
03557
03577 size_type find(const char* chars, size_type idx, size_type chars_len) const
03578 {
03579 if (chars_len == npos)
03580 throw std::length_error("Length for char array can not be 'npos'");
03581
03582 if ((chars_len == 0) && (idx < d_cplength))
03583 return idx;
03584
03585 if (idx < d_cplength)
03586 {
03587
03588 while (d_cplength - idx >= chars_len)
03589 {
03590 if (0 == compare(idx, chars_len, chars, chars_len))
03591 return idx;
03592
03593 ++idx;
03594 }
03595
03596 }
03597
03598 return npos;
03599 }
03600
03601
03621 size_type rfind(const char* chars, size_type idx, size_type chars_len) const
03622 {
03623 if (chars_len == npos)
03624 throw std::length_error("Length for char array can not be 'npos'");
03625
03626 if (chars_len == 0)
03627 return (idx < d_cplength) ? idx : d_cplength;
03628
03629 if (chars_len <= d_cplength)
03630 {
03631 if (idx > (d_cplength - chars_len))
03632 idx = d_cplength - chars_len;
03633
03634 do
03635 {
03636 if (0 == compare(idx, chars_len, chars, chars_len))
03637 return idx;
03638
03639 } while (idx-- != 0);
03640
03641 }
03642
03643 return npos;
03644 }
03645
03646
03648
03650
03664 size_type find_first_of(const String& str, size_type idx = 0) const
03665 {
03666 if (idx < d_cplength)
03667 {
03668 const utf32* pt = &ptr()[idx];
03669
03670 do
03671 {
03672 if (npos != str.find(*pt++))
03673 return idx;
03674
03675 } while (++idx != d_cplength);
03676
03677 }
03678
03679 return npos;
03680 }
03681
03696 size_type find_first_not_of(const String& str, size_type idx = 0) const
03697 {
03698 if (idx < d_cplength)
03699 {
03700 const utf32* pt = &ptr()[idx];
03701
03702 do
03703 {
03704 if (npos == str.find(*pt++))
03705 return idx;
03706
03707 } while (++idx != d_cplength);
03708
03709 }
03710
03711 return npos;
03712 }
03713
03714
03733 size_type find_first_of(const std::string& std_str, size_type idx = 0) const
03734 {
03735 if (idx < d_cplength)
03736 {
03737 const utf32* pt = &ptr()[idx];
03738
03739 do
03740 {
03741 if (npos != find_codepoint(std_str, *pt++))
03742 return idx;
03743
03744 } while (++idx != d_cplength);
03745
03746 }
03747
03748 return npos;
03749 }
03750
03769 size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const
03770 {
03771 if (idx < d_cplength)
03772 {
03773 const utf32* pt = &ptr()[idx];
03774
03775 do
03776 {
03777 if (npos == find_codepoint(std_str, *pt++))
03778 return idx;
03779
03780 } while (++idx != d_cplength);
03781
03782 }
03783
03784 return npos;
03785 }
03786
03787
03810 size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const
03811 {
03812 return find_first_of(utf8_str, idx, utf_length(utf8_str));
03813 }
03814
03837 size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
03838 {
03839 return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
03840 }
03841
03867 size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03868 {
03869 if (str_len == npos)
03870 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03871
03872 if (idx < d_cplength)
03873 {
03874 size_type encsze = encoded_size(utf8_str, str_len);
03875
03876 const utf32* pt = &ptr()[idx];
03877
03878 do
03879 {
03880 if (npos != find_codepoint(utf8_str, encsze, *pt++))
03881 return idx;
03882
03883 } while (++idx != d_cplength);
03884
03885 }
03886
03887 return npos;
03888 }
03889
03915 size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03916 {
03917 if (str_len == npos)
03918 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03919
03920 if (idx < d_cplength)
03921 {
03922 size_type encsze = encoded_size(utf8_str, str_len);
03923
03924 const utf32* pt = &ptr()[idx];
03925
03926 do
03927 {
03928 if (npos == find_codepoint(utf8_str, encsze, *pt++))
03929 return idx;
03930
03931 } while (++idx != d_cplength);
03932
03933 }
03934
03935 return npos;
03936 }
03937
03938
03953 size_type find_first_of(utf32 code_point, size_type idx = 0) const
03954 {
03955 return find(code_point, idx);
03956 }
03957
03974 size_type find_first_not_of(utf32 code_point, size_type idx = 0) const
03975 {
03976 if (idx < d_cplength)
03977 {
03978 do
03979 {
03980 if ((*this)[idx] != code_point)
03981 return idx;
03982
03983 } while(idx++ < d_cplength);
03984
03985 }
03986
03987 return npos;
03988 }
03989
03990
04007 size_type find_first_of(const char* cstr, size_type idx = 0) const
04008 {
04009 return find_first_of(cstr, idx, strlen(cstr));
04010 }
04011
04012
04029 size_type find_first_not_of(const char* cstr, size_type idx = 0) const
04030 {
04031 return find_first_not_of(cstr, idx, strlen(cstr));
04032 }
04033
04034
04054 size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const
04055 {
04056 if (chars_len == npos)
04057 throw std::length_error("Length for char array can not be 'npos'");
04058
04059 if (idx < d_cplength)
04060 {
04061 const utf32* pt = &ptr()[idx];
04062
04063 do
04064 {
04065 if (npos != find_codepoint(chars, chars_len, *pt++))
04066 return idx;
04067
04068 } while (++idx != d_cplength);
04069
04070 }
04071
04072 return npos;
04073 }
04074
04075
04095 size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
04096 {
04097 if (chars_len == npos)
04098 throw std::length_error("Length for char array can not be 'npos'");
04099
04100 if (idx < d_cplength)
04101 {
04102 const utf32* pt = &ptr()[idx];
04103
04104 do
04105 {
04106 if (npos == find_codepoint(chars, chars_len, *pt++))
04107 return idx;
04108
04109 } while (++idx != d_cplength);
04110
04111 }
04112
04113 return npos;
04114 }
04115
04116
04118
04120
04134 size_type find_last_of(const String& str, size_type idx = npos) const
04135 {
04136 if (d_cplength > 0)
04137 {
04138 if (idx >= d_cplength)
04139 idx = d_cplength - 1;
04140
04141 const utf32* pt = &ptr()[idx];
04142
04143 do
04144 {
04145 if (npos != str.find(*pt--))
04146 return idx;
04147
04148 } while (idx-- != 0);
04149
04150 }
04151
04152 return npos;
04153 }
04154
04169 size_type find_last_not_of(const String& str, size_type idx = npos) const
04170 {
04171 if (d_cplength > 0)
04172 {
04173 if (idx >= d_cplength)
04174 idx = d_cplength - 1;
04175
04176 const utf32* pt = &ptr()[idx];
04177
04178 do
04179 {
04180 if (npos == str.find(*pt--))
04181 return idx;
04182
04183 } while (idx-- != 0);
04184
04185 }
04186
04187 return npos;
04188 }
04189
04190
04209 size_type find_last_of(const std::string& std_str, size_type idx = npos) const
04210 {
04211 if (d_cplength > 0)
04212 {
04213 if (idx >= d_cplength)
04214 idx = d_cplength - 1;
04215
04216 const utf32* pt = &ptr()[idx];
04217
04218 do
04219 {
04220 if (npos != find_codepoint(std_str, *pt--))
04221 return idx;
04222
04223 } while (idx-- != 0);
04224
04225 }
04226
04227 return npos;
04228 }
04229
04248 size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const
04249 {
04250 if (d_cplength > 0)
04251 {
04252 if (idx >= d_cplength)
04253 idx = d_cplength - 1;
04254
04255 const utf32* pt = &ptr()[idx];
04256
04257 do
04258 {
04259 if (npos == find_codepoint(std_str, *pt--))
04260 return idx;
04261
04262 } while (idx-- != 0);
04263
04264 }
04265
04266 return npos;
04267 }
04268
04269
04292 size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const
04293 {
04294 return find_last_of(utf8_str, idx, utf_length(utf8_str));
04295 }
04296
04319 size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
04320 {
04321 return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
04322 }
04323
04349 size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04350 {
04351 if (str_len == npos)
04352 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
04353
04354 if (d_cplength > 0)
04355 {
04356 if (idx >= d_cplength)
04357 idx = d_cplength - 1;
04358
04359 size_type encsze = encoded_size(utf8_str, str_len);
04360
04361 const utf32* pt = &ptr()[idx];
04362
04363 do
04364 {
04365 if (npos != find_codepoint(utf8_str, encsze, *pt--))
04366 return idx;
04367
04368 } while (idx-- != 0);
04369
04370 }
04371
04372 return npos;
04373 }
04374
04400 size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04401 {
04402 if (str_len == npos)
04403 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
04404
04405 if (d_cplength > 0)
04406 {
04407 if (idx >= d_cplength)
04408 idx = d_cplength - 1;
04409
04410 size_type encsze = encoded_size(utf8_str, str_len);
04411
04412 const utf32* pt = &ptr()[idx];
04413
04414 do
04415 {
04416 if (npos == find_codepoint(utf8_str, encsze, *pt--))
04417 return idx;
04418
04419 } while (idx-- != 0);
04420
04421 }
04422
04423 return npos;
04424 }
04425
04426
04441 size_type find_last_of(utf32 code_point, size_type idx = npos) const
04442 {
04443 return rfind(code_point, idx);
04444 }
04445
04460 size_type find_last_not_of(utf32 code_point, size_type idx = npos) const
04461 {
04462 if (d_cplength > 0)
04463 {
04464 if (idx >= d_cplength)
04465 idx = d_cplength - 1;
04466
04467 do
04468 {
04469 if ((*this)[idx] != code_point)
04470 return idx;
04471
04472 } while(idx-- != 0);
04473
04474 }
04475
04476 return npos;
04477 }
04478
04479
04496 size_type find_last_of(const char* cstr, size_type idx = npos) const
04497 {
04498 return find_last_of(cstr, idx, strlen(cstr));
04499 }
04500
04501
04518 size_type find_last_not_of(const char* cstr, size_type idx = npos) const
04519 {
04520 return find_last_not_of(cstr, idx, strlen(cstr));
04521 }
04522
04523
04543 size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const
04544 {
04545 if (chars_len == npos)
04546 throw std::length_error("Length for char array can not be 'npos'");
04547
04548 if (d_cplength > 0)
04549 {
04550 if (idx >= d_cplength)
04551 idx = d_cplength - 1;
04552
04553 const utf32* pt = &ptr()[idx];
04554
04555 do
04556 {
04557 if (npos != find_codepoint(chars, chars_len, *pt--))
04558 return idx;
04559
04560 } while (idx-- != 0);
04561
04562 }
04563
04564 return npos;
04565 }
04566
04567
04587 size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
04588 {
04589 if (chars_len == npos)
04590 throw std::length_error("Length for char array can not be 'npos'");
04591
04592 if (d_cplength > 0)
04593 {
04594 if (idx >= d_cplength)
04595 idx = d_cplength - 1;
04596
04597 const utf32* pt = &ptr()[idx];
04598
04599 do
04600 {
04601 if (npos == find_codepoint(chars, chars_len, *pt--))
04602 return idx;
04603
04604 } while (idx-- != 0);
04605
04606 }
04607
04608 return npos;
04609 }
04610
04611
04613
04615
04630 String substr(size_type idx = 0, size_type len = npos) const
04631 {
04632 if (d_cplength < idx)
04633 throw std::out_of_range("Index is out of range for this CEGUI::String");
04634
04635 return String(*this, idx, len);
04636 }
04637
04639
04641
04648 iterator begin(void)
04649 {
04650 return iterator(ptr());
04651 }
04652
04660 const_iterator begin(void) const
04661 {
04662 return const_iterator(ptr());
04663 }
04664
04672 iterator end(void)
04673 {
04674 return iterator(&ptr()[d_cplength]);
04675 }
04676
04684 const_iterator end(void) const
04685 {
04686 return const_iterator(&ptr()[d_cplength]);
04687 }
04688
04696 reverse_iterator rbegin(void)
04697 {
04698 return reverse_iterator(end());
04699 }
04700
04708 const_reverse_iterator rbegin(void) const
04709 {
04710 return const_reverse_iterator(end());
04711 }
04712
04720 reverse_iterator rend(void)
04721 {
04722 return reverse_iterator(begin());
04723 }
04724
04732 const_reverse_iterator rend(void) const
04733 {
04734 return const_reverse_iterator(begin());
04735 }
04736
04737 private:
04738
04739
04740
04741
04742
04743
04744
04745
04746 bool grow(size_type new_size);
04747
04748
04749 void trim(void);
04750
04751
04752 void setlen(size_type len)
04753 {
04754 d_cplength = len;
04755 ptr()[len] = (utf32)(0);
04756 }
04757
04758
04759 utf32* ptr(void)
04760 {
04761 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
04762 }
04763
04764
04765 const utf32* ptr(void) const
04766 {
04767 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
04768 }
04769
04770
04771 void init(void)
04772 {
04773 d_reserve = STR_QUICKBUFF_SIZE;
04774 d_encodedbuff = NULL;
04775 d_encodedbufflen = 0;
04776 d_encodeddatlen = 0;
04777 setlen(0);
04778 }
04779
04780
04781 bool inside(utf32* inptr)
04782 {
04783 if (inptr < ptr() || ptr() + d_cplength <= inptr)
04784 return false;
04785 else
04786 return true;
04787 }
04788
04789
04790 size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
04791 {
04792 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
04793 }
04794
04795
04796
04797
04798
04799
04800 size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
04801 {
04802
04803 if (src_len == 0)
04804 {
04805 src_len = utf_length(src);
04806 }
04807
04808 size_type destCapacity = dest_len;
04809
04810
04811 for (uint idx = 0; idx < src_len; ++idx)
04812 {
04813 utf32 cp = src[idx];
04814
04815
04816 if (destCapacity < encoded_size(cp))
04817 {
04818 break;
04819 }
04820
04821 if (cp < 0x80)
04822 {
04823 *dest++ = (utf8)cp;
04824 --destCapacity;
04825 }
04826 else if (cp < 0x0800)
04827 {
04828 *dest++ = (utf8)((cp >> 6) | 0xC0);
04829 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04830 destCapacity -= 2;
04831 }
04832 else if (cp < 0x10000)
04833 {
04834 *dest++ = (utf8)((cp >> 12) | 0xE0);
04835 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04836 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04837 destCapacity -= 3;
04838 }
04839 else
04840 {
04841 *dest++ = (utf8)((cp >> 18) | 0xF0);
04842 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
04843 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04844 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04845 destCapacity -= 4;
04846 }
04847
04848 }
04849
04850 return dest_len - destCapacity;
04851 }
04852
04853 size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
04854 {
04855
04856 if (src_len == 0)
04857 {
04858 src_len = utf_length(src);
04859 }
04860
04861 size_type destCapacity = dest_len;
04862
04863
04864 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
04865 {
04866 utf32 cp;
04867 utf8 cu = src[idx++];
04868
04869 if (cu < 0x80)
04870 {
04871 cp = (utf32)(cu);
04872 }
04873 else if (cu < 0xE0)
04874 {
04875 cp = ((cu & 0x1F) << 6);
04876 cp |= (src[idx++] & 0x3F);
04877 }
04878 else if (cu < 0xF0)
04879 {
04880 cp = ((cu & 0x0F) << 12);
04881 cp |= ((src[idx++] & 0x3F) << 6);
04882 cp |= (src[idx++] & 0x3F);
04883 }
04884 else
04885 {
04886 cp = ((cu & 0x07) << 18);
04887 cp |= ((src[idx++] & 0x3F) << 12);
04888 cp |= ((src[idx++] & 0x3F) << 6);
04889 cp |= (src[idx++] & 0x3F);
04890 }
04891
04892 *dest++ = cp;
04893 --destCapacity;
04894 }
04895
04896 return dest_len - destCapacity;
04897 }
04898
04899
04900 size_type encoded_size(utf32 code_point) const
04901 {
04902 if (code_point < 0x80)
04903 return 1;
04904 else if (code_point < 0x0800)
04905 return 2;
04906 else if (code_point < 0x10000)
04907 return 3;
04908 else
04909 return 4;
04910 }
04911
04912
04913 size_type encoded_size(const utf32* buf) const
04914 {
04915 return encoded_size(buf, utf_length(buf));
04916 }
04917
04918
04919 size_type encoded_size(const utf32* buf, size_type len) const
04920 {
04921 size_type count = 0;
04922
04923 while (len--)
04924 {
04925 count += encoded_size(*buf++);
04926 }
04927
04928 return count;
04929 }
04930
04931
04932 size_type encoded_size(const utf8* buf) const
04933 {
04934 return encoded_size(buf, utf_length(buf));
04935 }
04936
04937
04938 size_type encoded_size(const utf8* buf, size_type len) const
04939 {
04940 utf8 tcp;
04941 size_type count = 0;
04942
04943 while (len--)
04944 {
04945 tcp = *buf++;
04946 ++count;
04947
04948 if (tcp < 0x80)
04949 {
04950 }
04951 else if (tcp < 0xE0)
04952 {
04953 --len;
04954 ++buf;
04955 }
04956 else if (tcp < 0xF0)
04957 {
04958 len -= 2;
04959 buf += 2;
04960 }
04961 else
04962 {
04963 len -= 2;
04964 buf += 3;
04965 }
04966
04967 }
04968
04969 return count;
04970 }
04971
04972
04973 size_type utf_length(const utf8* utf8_str) const
04974 {
04975 size_type cnt = 0;
04976 while (*utf8_str++)
04977 cnt++;
04978
04979 return cnt;
04980 }
04981
04982
04983 size_type utf_length(const utf32* utf32_str) const
04984 {
04985 size_type cnt = 0;
04986 while (*utf32_str++)
04987 cnt++;
04988
04989 return cnt;
04990 }
04991
04992
04993 utf8* build_utf8_buff(void) const;
04994
04995
04996 int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
04997 {
04998 if (!cp_count)
04999 return 0;
05000
05001 while ((--cp_count) && (*buf1 == *buf2))
05002 buf1++, buf2++;
05003
05004 return *buf1 - *buf2;
05005 }
05006
05007
05008 int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
05009 {
05010 if (!cp_count)
05011 return 0;
05012
05013 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
05014 buf1++, buf2++;
05015
05016 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
05017 }
05018
05019
05020 int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
05021 {
05022 if (!cp_count)
05023 return 0;
05024
05025 utf32 cp;
05026 utf8 cu;
05027
05028 do
05029 {
05030 cu = *buf2++;
05031
05032 if (cu < 0x80)
05033 {
05034 cp = (utf32)(cu);
05035 }
05036 else if (cu < 0xE0)
05037 {
05038 cp = ((cu & 0x1F) << 6);
05039 cp |= (*buf2++ & 0x3F);
05040 }
05041 else if (cu < 0xF0)
05042 {
05043 cp = ((cu & 0x0F) << 12);
05044 cp |= ((*buf2++ & 0x3F) << 6);
05045 cp |= (*buf2++ & 0x3F);
05046 }
05047 else
05048 {
05049 cp = ((cu & 0x07) << 18);
05050 cp |= ((*buf2++ & 0x3F) << 12);
05051 cp |= ((*buf2++ & 0x3F) << 6);
05052 cp |= (*buf2++ & 0x3F);
05053 }
05054
05055 } while ((*buf1++ == cp) && (--cp_count));
05056
05057 return (*--buf1) - cp;
05058 }
05059
05060
05061 size_type find_codepoint(const std::string& str, utf32 code_point) const
05062 {
05063 size_type idx = 0, sze = (size_type)str.size();
05064
05065 while (idx != sze)
05066 {
05067 if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
05068 return idx;
05069
05070 ++idx;
05071 }
05072
05073 return npos;
05074 }
05075
05076
05077 size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
05078 {
05079 size_type idx = 0;
05080
05081 utf32 cp;
05082 utf8 cu;
05083
05084 while (idx != len) {
05085 cu = *str++;
05086
05087 if (cu < 0x80)
05088 {
05089 cp = (utf32)(cu);
05090 }
05091 else if (cu < 0xE0)
05092 {
05093 cp = ((cu & 0x1F) << 6);
05094 cp |= (*str++ & 0x3F);
05095 }
05096 else if (cu < 0xF0)
05097 {
05098 cp = ((cu & 0x0F) << 12);
05099 cp |= ((*str++ & 0x3F) << 6);
05100 cp |= (*str++ & 0x3F);
05101 }
05102 else
05103 {
05104 cp = ((cu & 0x07) << 18);
05105 cp |= ((*str++ & 0x3F) << 12);
05106 cp |= ((*str++ & 0x3F) << 6);
05107 cp |= (*str++ & 0x3F);
05108 }
05109
05110 if (code_point == cp)
05111 return idx;
05112
05113 ++idx;
05114 }
05115
05116 return npos;
05117 }
05118
05119
05120
05121 size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
05122 {
05123 for (size_type idx = 0; idx != chars_len; ++idx)
05124 {
05125 if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
05126 return idx;
05127 }
05128
05129 return npos;
05130 }
05131
05132 };
05133
05134
05136
05138
05142 bool CEGUIEXPORT operator==(const String& str1, const String& str2);
05143
05148 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str);
05149
05154 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str);
05155
05160 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str);
05161
05166 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str);
05167
05172 bool CEGUIEXPORT operator!=(const String& str1, const String& str2);
05173
05178 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str);
05179
05184 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str);
05185
05190 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str);
05191
05196 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str);
05197
05202 bool CEGUIEXPORT operator<(const String& str1, const String& str2);
05203
05208 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str);
05209
05214 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str);
05215
05220 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str);
05221
05226 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str);
05227
05232 bool CEGUIEXPORT operator>(const String& str1, const String& str2);
05233
05238 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str);
05239
05244 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str);
05245
05250 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str);
05251
05256 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str);
05257
05262 bool CEGUIEXPORT operator<=(const String& str1, const String& str2);
05263
05268 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str);
05269
05274 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str);
05275
05280 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str);
05281
05286 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str);
05287
05292 bool CEGUIEXPORT operator>=(const String& str1, const String& str2);
05293
05298 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str);
05299
05304 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str);
05305
05310 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str);
05311
05316 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str);
05317
05322 bool CEGUIEXPORT operator==(const String& str, const char* c_str);
05323
05328 bool CEGUIEXPORT operator==(const char* c_str, const String& str);
05329
05334 bool CEGUIEXPORT operator!=(const String& str, const char* c_str);
05335
05340 bool CEGUIEXPORT operator!=(const char* c_str, const String& str);
05341
05346 bool CEGUIEXPORT operator<(const String& str, const char* c_str);
05347
05352 bool CEGUIEXPORT operator<(const char* c_str, const String& str);
05353
05358 bool CEGUIEXPORT operator>(const String& str, const char* c_str);
05359
05364 bool CEGUIEXPORT operator>(const char* c_str, const String& str);
05365
05370 bool CEGUIEXPORT operator<=(const String& str, const char* c_str);
05371
05376 bool CEGUIEXPORT operator<=(const char* c_str, const String& str);
05377
05382 bool CEGUIEXPORT operator>=(const String& str, const char* c_str);
05383
05388 bool CEGUIEXPORT operator>=(const char* c_str, const String& str);
05389
05391
05393
05408 String CEGUIEXPORT operator+(const String& str1, const String& str2);
05409
05425 String CEGUIEXPORT operator+(const String& str, const std::string& std_str);
05426
05442 String CEGUIEXPORT operator+(const std::string& std_str, const String& str);
05443
05459 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str);
05460
05476 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str);
05477
05493 String CEGUIEXPORT operator+(const String& str, utf32 code_point);
05494
05510 String CEGUIEXPORT operator+(utf32 code_point, const String& str);
05511
05527 String CEGUIEXPORT operator+(const String& str, const char* c_str);
05528
05544 String CEGUIEXPORT operator+(const char* c_str, const String& str);
05545
05546
05548
05550 std::ostream& operator<<(std::ostream& s, const String& str);
05551
05552
05554
05556
05569 void CEGUIEXPORT swap(String& str1, String& str2);
05570
05571
05572 }
05573
05574
05575 #endif // end of guard _CEGUIString_h_