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
00027
00028
00029
00030 #ifndef _CEGUIString_h_
00031 #define _CEGUIString_h_
00032
00033 #include "CEGUIBase.h"
00034 #include <string>
00035 #include <string.h>
00036 #include <stdexcept>
00037
00038
00039 namespace CEGUI
00040 {
00041 #define STR_QUICKBUFF_SIZE 32
00042
00043
00044
00045 typedef uint8 utf8;
00046
00047 typedef uint32 utf32;
00048
00057 class CEGUIEXPORT String
00058 {
00059 public:
00060
00061
00062
00063 typedef utf32 value_type;
00064 typedef size_t size_type;
00065 typedef ptrdiff_t difference_type;
00066 typedef utf32& reference;
00067 typedef const utf32& const_reference;
00068 typedef utf32* pointer;
00069 typedef const utf32* const_pointer;
00070
00071 static const size_type npos;
00072
00073 private:
00074
00075
00076
00077 size_type d_cplength;
00078 size_type d_reserve;
00079
00080 mutable utf8* d_encodedbuff;
00081 mutable size_type d_encodeddatlen;
00082 mutable size_type d_encodedbufflen;
00083
00084 utf32 d_quickbuff[STR_QUICKBUFF_SIZE];
00085 utf32* d_buffer;
00086
00087 public:
00088
00089
00090
00095 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00096 class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32>
00097 #else
00098 class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32, std::ptrdiff_t, const utf32*, const utf32&>
00099 #endif
00100 {
00101
00102 public:
00104
00106 const utf32* d_ptr;
00107
00108
00110
00112 const_iterator(void)
00113 {
00114 d_ptr = 0;
00115 }
00116 const_iterator(const_pointer ptr)
00117 {
00118 d_ptr = ptr;
00119 }
00120
00121 const_reference operator*() const
00122 {
00123 return *d_ptr;
00124 }
00125
00126 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00127 # pragma warning (push)
00128 # pragma warning (disable : 4284)
00129 #endif
00130 const_pointer operator->() const
00131 {
00132 return &**this;
00133 }
00134
00135 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00136 # pragma warning (pop)
00137 #endif
00138
00139 const_iterator& operator++()
00140 {
00141 ++d_ptr;
00142 return *this;
00143 }
00144
00145 const_iterator operator++(int)
00146 {
00147 const_iterator temp = *this;
00148 ++*this;
00149 return temp;
00150 }
00151
00152 const_iterator& operator--()
00153 {
00154 --d_ptr;
00155 return *this;
00156 }
00157
00158 const_iterator operator--(int)
00159 {
00160 const_iterator temp = *this;
00161 --*this;
00162 return temp;
00163 }
00164
00165 const_iterator& operator+=(difference_type offset)
00166 {
00167 d_ptr += offset;
00168 return *this;
00169 }
00170
00171 const_iterator operator+(difference_type offset) const
00172 {
00173 const_iterator temp = *this;
00174 return temp += offset;
00175 }
00176
00177 const_iterator& operator-=(difference_type offset)
00178 {
00179 return *this += -offset;
00180 }
00181
00182 const_iterator operator-(difference_type offset) const
00183 {
00184 const_iterator temp = *this;
00185 return temp -= offset;
00186 }
00187
00188 difference_type operator-(const const_iterator& iter) const
00189 {
00190 return d_ptr - iter.d_ptr;
00191 }
00192
00193 const_reference operator[](difference_type offset) const
00194 {
00195 return *(*this + offset);
00196 }
00197
00198 bool operator==(const const_iterator& iter) const
00199 {
00200 return d_ptr == iter.d_ptr;
00201 }
00202
00203 bool operator!=(const const_iterator& iter) const
00204 {
00205 return !(*this == iter);
00206 }
00207
00208 bool operator<(const const_iterator& iter) const
00209 {
00210 return d_ptr < iter.d_ptr;
00211 }
00212
00213 bool operator>(const const_iterator& iter) const
00214 {
00215 return (!(iter < *this));
00216 }
00217
00218 bool operator<=(const const_iterator& iter) const
00219 {
00220 return (!(iter < *this));
00221 }
00222
00223 bool operator>=(const const_iterator& iter) const
00224 {
00225 return (!(*this < iter));
00226 }
00227
00228 friend const_iterator operator+(difference_type offset, const const_iterator& iter)
00229 {
00230 return iter + offset;
00231 }
00232
00233 };
00234
00239 class iterator : public const_iterator
00240 {
00241 public:
00242 iterator(void) {}
00243 iterator(pointer ptr) : const_iterator(ptr) {}
00244
00245
00246 reference operator*() const
00247 {
00248 return ((reference)**(const_iterator *)this);
00249 }
00250
00251 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00252 # pragma warning (push)
00253 # pragma warning (disable : 4284)
00254 #endif
00255
00256 pointer operator->() const
00257 {
00258 return &**this;
00259 }
00260
00261 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00262 # pragma warning (pop)
00263 #endif
00264
00265 iterator& operator++()
00266 {
00267 ++this->d_ptr;
00268 return *this;
00269 }
00270
00271 iterator operator++(int)
00272 {
00273 iterator temp = *this;
00274 ++*this;
00275 return temp;
00276 }
00277
00278 iterator& operator--()
00279 {
00280 --this->d_ptr;
00281 return *this;
00282 }
00283
00284 iterator operator--(int)
00285 {
00286 iterator temp = *this;
00287 --*this;
00288 return temp;
00289 }
00290
00291 iterator& operator+=(difference_type offset)
00292 {
00293 this->d_ptr += offset;
00294 return *this;
00295 }
00296
00297 iterator operator+(difference_type offset) const
00298 {
00299 iterator temp = *this;
00300 return temp + offset;
00301 }
00302
00303 iterator& operator-=(difference_type offset)
00304 {
00305 return *this += -offset;
00306 }
00307
00308 iterator operator-(difference_type offset) const
00309 {
00310 iterator temp = *this;
00311 return temp -= offset;
00312 }
00313
00314 difference_type operator-(const const_iterator& iter) const
00315 {
00316 return ((const_iterator)*this - iter);
00317 }
00318
00319 reference operator[](difference_type offset) const
00320 {
00321 return *(*this + offset);
00322 }
00323
00324 friend iterator operator+(difference_type offset, const iterator& iter)
00325 {
00326 return iter + offset;
00327 }
00328
00329 };
00330
00335 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
00336 typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator;
00337 #else
00338 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00339 #endif
00340
00345 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
00346 typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator;
00347 #else
00348 typedef std::reverse_iterator<iterator> reverse_iterator;
00349 #endif
00350
00351 public:
00357 struct FastLessCompare
00358 {
00359 bool operator() (const String& a, const String& b) const
00360 {
00361 const size_t la = a.length();
00362 const size_t lb = b.length();
00363 if (la == lb)
00364 return (memcmp(a.ptr(), b.ptr(), la*sizeof(utf32)) < 0);
00365 return (la < lb);
00366 }
00367 };
00368
00369 public:
00371
00373
00377 String(void)
00378 {
00379 init();
00380 }
00381
00386 ~String(void);
00387
00389
00391
00401 String(const String& str)
00402 {
00403 init();
00404 assign(str);
00405 }
00406
00407
00424 String(const String& str, size_type str_idx, size_type str_num = npos)
00425 {
00426 init();
00427 assign(str, str_idx, str_num);
00428 }
00429
00431
00433
00449 String(const std::string& std_str)
00450 {
00451 init();
00452 assign(std_str);
00453 }
00454
00477 String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
00478 {
00479 init();
00480 assign(std_str, str_idx, str_num);
00481 }
00482
00483
00485
00487
00505 String(const utf8* utf8_str)
00506 {
00507 init();
00508 assign(utf8_str);
00509 }
00510
00537 String(const utf8* utf8_str, size_type chars_len)
00538 {
00539 init();
00540 assign(utf8_str, chars_len);
00541 }
00542
00544
00546
00561 String(size_type num, utf32 code_point)
00562 {
00563 init();
00564 assign(num, code_point);
00565 }
00566
00568
00570
00584 String(const_iterator iter_beg, const_iterator iter_end)
00585 {
00586 init();
00587 append(iter_beg, iter_end);
00588 }
00589
00590
00592
00594
00606 String(const char* cstr)
00607 {
00608 init();
00609 assign(cstr);
00610 }
00611
00627 String(const char* chars, size_type chars_len)
00628 {
00629 init();
00630 assign(chars, chars_len);
00631 }
00632
00633
00635
00637
00644 size_type size(void) const
00645 {
00646 return d_cplength;
00647 }
00648
00656 size_type length(void) const
00657 {
00658 return d_cplength;
00659 }
00660
00668 bool empty(void) const
00669 {
00670 return (d_cplength == 0);
00671 }
00672
00682 static size_type max_size(void)
00683 {
00684 return (((size_type)-1) / sizeof(utf32));
00685 }
00686
00688
00690
00691
00700 size_type capacity(void) const
00701 {
00702 return d_reserve - 1;
00703 }
00704
00705
00720 void reserve(size_type num = 0)
00721 {
00722 if (num == 0)
00723 trim();
00724 else
00725 grow(num);
00726 }
00727
00729
00731
00746 int compare(const String& str) const
00747 {
00748 return compare(0, d_cplength, str);
00749 }
00750
00780 int compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
00781 {
00782 if ((d_cplength < idx) || (str.d_cplength < str_idx))
00783 throw std::out_of_range("Index is out of range for CEGUI::String");
00784
00785 if ((len == npos) || (idx + len > d_cplength))
00786 len = d_cplength - idx;
00787
00788 if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
00789 str_len = str.d_cplength - str_idx;
00790
00791 int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
00792
00793 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
00794 }
00795
00796
00816 int compare(const std::string& std_str) const
00817 {
00818 return compare(0, d_cplength, std_str);
00819 }
00820
00821
00855 int compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
00856 {
00857 if (d_cplength < idx)
00858 throw std::out_of_range("Index is out of range for CEGUI::String");
00859
00860 if (std_str.size() < str_idx)
00861 throw std::out_of_range("Index is out of range for std::string");
00862
00863 if ((len == npos) || (idx + len > d_cplength))
00864 len = d_cplength - idx;
00865
00866 if ((str_len == npos) || (str_idx + str_len > std_str.size()))
00867 str_len = (size_type)std_str.size() - str_idx;
00868
00869 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
00870
00871 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
00872 }
00873
00874
00896 int compare(const utf8* utf8_str) const
00897 {
00898 return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
00899 }
00900
00901
00931 int compare(size_type idx, size_type len, const utf8* utf8_str) const
00932 {
00933 return compare(idx, len, utf8_str, encoded_size(utf8_str));
00934 }
00935
00969 int compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
00970 {
00971 if (d_cplength < idx)
00972 throw std::out_of_range("Index is out of range for CEGUI::String");
00973
00974 if (str_cplen == npos)
00975 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
00976
00977 if ((len == npos) || (idx + len > d_cplength))
00978 len = d_cplength - idx;
00979
00980 int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
00981
00982 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
00983 }
00984
00985
01001 int compare(const char* cstr) const
01002 {
01003 return compare(0, d_cplength, cstr, strlen(cstr));
01004 }
01005
01006
01030 int compare(size_type idx, size_type len, const char* cstr) const
01031 {
01032 return compare(idx, len, cstr, strlen(cstr));
01033 }
01034
01035
01063 int compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
01064 {
01065 if (d_cplength < idx)
01066 throw std::out_of_range("Index is out of range for CEGUI::String");
01067
01068 if (chars_len == npos)
01069 throw std::length_error("Length for char array can not be 'npos'");
01070
01071 if ((len == npos) || (idx + len > d_cplength))
01072 len = d_cplength - idx;
01073
01074 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
01075
01076 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
01077 }
01078
01079
01081
01083
01097 reference operator[](size_type idx)
01098 {
01099 return (ptr()[idx]);
01100 }
01101
01116 value_type operator[](size_type idx) const
01117 {
01118 return ptr()[idx];
01119 }
01120
01133 reference at(size_type idx)
01134 {
01135 if (d_cplength <= idx)
01136 throw std::out_of_range("Index is out of range for CEGUI::String");
01137
01138 return ptr()[idx];
01139 }
01140
01153 const_reference at(size_type idx) const
01154 {
01155 if (d_cplength <= idx)
01156 throw std::out_of_range("Index is out of range for CEGUI::String");
01157
01158 return ptr()[idx];
01159 }
01160
01161
01163
01165
01178 const char* c_str(void) const
01179 {
01180 return (const char*)build_utf8_buff();
01181 }
01182
01196 const utf8* data(void) const
01197 {
01198 return build_utf8_buff();
01199 }
01200
01205 utf32* ptr(void)
01206 {
01207 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
01208 }
01209
01214 const utf32* ptr(void) const
01215 {
01216 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
01217 }
01218
01219
01220
01241 size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const
01242 {
01243 if (d_cplength < idx)
01244 throw std::out_of_range("Index is out of range for CEGUI::String");
01245
01246 if (len == npos)
01247 len = d_cplength;
01248
01249 return encode(&ptr()[idx], buf, npos, len);
01250 }
01251
01253
01255
01271 size_type utf8_stream_len(size_type num = npos, size_type idx = 0) const
01272 {
01273 using namespace std;
01274
01275 if (d_cplength < idx)
01276 throw out_of_range("Index was out of range for CEGUI::String object");
01277
01278 size_type maxlen = d_cplength - idx;
01279
01280 return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
01281 }
01282
01284
01286
01296 String& operator=(const String& str)
01297 {
01298 return assign(str);
01299 }
01300
01319 String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
01320 {
01321 if (str.d_cplength < str_idx)
01322 throw std::out_of_range("Index was out of range for CEGUI::String object");
01323
01324 if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
01325 str_num = str.d_cplength - str_idx;
01326
01327 grow(str_num);
01328 setlen(str_num);
01329 memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
01330
01331 return *this;
01332 }
01333
01350 String& operator=(const std::string& std_str)
01351 {
01352 return assign(std_str);
01353 }
01354
01378 String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
01379 {
01380 if (std_str.size() < str_idx)
01381 throw std::out_of_range("Index was out of range for std::string object");
01382
01383 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
01384 str_num = (size_type)std_str.size() - str_idx;
01385
01386 grow(str_num);
01387 setlen(str_num);
01388
01389 while(str_num--)
01390 {
01391 ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
01392 }
01393
01394 return *this;
01395 }
01396
01415 String& operator=(const utf8* utf8_str)
01416 {
01417 return assign(utf8_str, utf_length(utf8_str));
01418 }
01419
01438 String& assign(const utf8* utf8_str)
01439 {
01440 return assign(utf8_str, utf_length(utf8_str));
01441 }
01442
01464 String& assign(const utf8* utf8_str, size_type str_num)
01465 {
01466 if (str_num == npos)
01467 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
01468
01469 size_type enc_sze = encoded_size(utf8_str, str_num);
01470
01471 grow(enc_sze);
01472 encode(utf8_str, ptr(), d_reserve, str_num);
01473 setlen(enc_sze);
01474 return *this;
01475 }
01476
01487 String& operator=(utf32 code_point)
01488 {
01489 return assign(1, code_point);
01490 }
01491
01507 String& assign(size_type num, utf32 code_point)
01508 {
01509 if (num == npos)
01510 throw std::length_error("Code point count can not be 'npos'");
01511
01512 grow(num);
01513 setlen(num);
01514 utf32* p = ptr();
01515
01516 while(num--)
01517 *p++ = code_point;
01518
01519 return *this;
01520 }
01521
01522
01535 String& operator=(const char* cstr)
01536 {
01537 return assign(cstr, strlen(cstr));
01538 }
01539
01540
01553 String& assign(const char* cstr)
01554 {
01555 return assign(cstr, strlen(cstr));
01556 }
01557
01558
01574 String& assign(const char* chars, size_type chars_len)
01575 {
01576 grow(chars_len);
01577 utf32* pt = ptr();
01578
01579 for (size_type i = 0; i < chars_len; ++i)
01580 {
01581 *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
01582 }
01583
01584 setlen(chars_len);
01585 return *this;
01586 }
01587
01588
01599 void swap(String& str)
01600 {
01601 size_type temp_len = d_cplength;
01602 d_cplength = str.d_cplength;
01603 str.d_cplength = temp_len;
01604
01605 size_type temp_res = d_reserve;
01606 d_reserve = str.d_reserve;
01607 str.d_reserve = temp_res;
01608
01609 utf32* temp_buf = d_buffer;
01610 d_buffer = str.d_buffer;
01611 str.d_buffer = temp_buf;
01612
01613
01614 if (temp_res <= STR_QUICKBUFF_SIZE)
01615 {
01616 utf32 temp_qbf[STR_QUICKBUFF_SIZE];
01617
01618 memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
01619 memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
01620 memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
01621 }
01622
01623 }
01624
01626
01628
01640 String& operator+=(const String& str)
01641 {
01642 return append(str);
01643 }
01644
01664 String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
01665 {
01666 if (str.d_cplength < str_idx)
01667 throw std::out_of_range("Index is out of range for CEGUI::String");
01668
01669 if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
01670 str_num = str.d_cplength - str_idx;
01671
01672 grow(d_cplength + str_num);
01673 memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
01674 setlen(d_cplength + str_num);
01675 return *this;
01676 }
01677
01678
01695 String& operator+=(const std::string& std_str)
01696 {
01697 return append(std_str);
01698 }
01699
01723 String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
01724 {
01725 if (std_str.size() < str_idx)
01726 throw std::out_of_range("Index is out of range for std::string");
01727
01728 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
01729 str_num = (size_type)std_str.size() - str_idx;
01730
01731 size_type newsze = d_cplength + str_num;
01732
01733 grow(newsze);
01734 utf32* pt = &ptr()[newsze-1];
01735
01736 while(str_num--)
01737 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
01738
01739 setlen(newsze);
01740 return *this;
01741 }
01742
01743
01762 String& operator+=(const utf8* utf8_str)
01763 {
01764 return append(utf8_str, utf_length(utf8_str));
01765 }
01766
01785 String& append(const utf8* utf8_str)
01786 {
01787 return append(utf8_str, utf_length(utf8_str));
01788 }
01789
01790
01812 String& append(const utf8* utf8_str, size_type len)
01813 {
01814 if (len == npos)
01815 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
01816
01817 size_type encsz = encoded_size(utf8_str, len);
01818 size_type newsz = d_cplength + encsz;
01819
01820 grow(newsz);
01821 encode(utf8_str, &ptr()[d_cplength], encsz, len);
01822 setlen(newsz);
01823
01824 return *this;
01825 }
01826
01827
01840 String& operator+=(utf32 code_point)
01841 {
01842 return append(1, code_point);
01843 }
01844
01860 String& append(size_type num, utf32 code_point)
01861 {
01862 if (num == npos)
01863 throw std::length_error("Code point count can not be 'npos'");
01864
01865 size_type newsz = d_cplength + num;
01866 grow(newsz);
01867
01868 utf32* p = &ptr()[d_cplength];
01869
01870 while(num--)
01871 *p++ = code_point;
01872
01873 setlen(newsz);
01874
01875 return *this;
01876 }
01877
01890 void push_back(utf32 code_point)
01891 {
01892 append(1, code_point);
01893 }
01894
01910 String& append(const_iterator iter_beg, const_iterator iter_end)
01911 {
01912 return replace(end(), end(), iter_beg, iter_end);
01913 }
01914
01915
01928 String& operator+=(const char* cstr)
01929 {
01930 return append(cstr, strlen(cstr));
01931 }
01932
01933
01946 String& append(const char* cstr)
01947 {
01948 return append(cstr, strlen(cstr));
01949 }
01950
01951
01967 String& append(const char* chars, size_type chars_len)
01968 {
01969 if (chars_len == npos)
01970 throw std::length_error("Length for char array can not be 'npos'");
01971
01972 size_type newsz = d_cplength + chars_len;
01973
01974 grow(newsz);
01975
01976 utf32* pt = &ptr()[newsz-1];
01977
01978 while(chars_len--)
01979 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
01980
01981 setlen(newsz);
01982
01983 return *this;
01984 }
01985
01986
01988
01990
02006 String& insert(size_type idx, const String& str)
02007 {
02008 return insert(idx, str, 0, npos);
02009 }
02010
02033 String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
02034 {
02035 if ((d_cplength < idx) || (str.d_cplength < str_idx))
02036 throw std::out_of_range("Index is out of range for CEGUI::String");
02037
02038 if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
02039 str_num = str.d_cplength - str_idx;
02040
02041 size_type newsz = d_cplength + str_num;
02042 grow(newsz);
02043 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02044 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02045 setlen(newsz);
02046
02047 return *this;
02048 }
02049
02070 String& insert(size_type idx, const std::string& std_str)
02071 {
02072 return insert(idx, std_str, 0, npos);
02073 }
02074
02101 String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
02102 {
02103 if (d_cplength < idx)
02104 throw std::out_of_range("Index is out of range for CEGUI::String");
02105
02106 if (std_str.size() < str_idx)
02107 throw std::out_of_range("Index is out of range for std::string");
02108
02109 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
02110 str_num = (size_type)std_str.size() - str_idx;
02111
02112 size_type newsz = d_cplength + str_num;
02113 grow(newsz);
02114
02115 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02116
02117 utf32* pt = &ptr()[idx + str_num - 1];
02118
02119 while(str_num--)
02120 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02121
02122 setlen(newsz);
02123
02124 return *this;
02125 }
02126
02149 String& insert(size_type idx, const utf8* utf8_str)
02150 {
02151 return insert(idx, utf8_str, utf_length(utf8_str));
02152 }
02153
02179 String& insert(size_type idx, const utf8* utf8_str, size_type len)
02180 {
02181 if (d_cplength < idx)
02182 throw std::out_of_range("Index is out of range for CEGUI::String");
02183
02184 if (len == npos)
02185 throw std::length_error("Length of utf8 encoded string can not be 'npos'");
02186
02187 size_type encsz = encoded_size(utf8_str, len);
02188 size_type newsz = d_cplength + encsz;
02189
02190 grow(newsz);
02191 memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02192 encode(utf8_str, &ptr()[idx], encsz, len);
02193 setlen(newsz);
02194
02195 return *this;
02196 }
02197
02217 String& insert(size_type idx, size_type num, utf32 code_point)
02218 {
02219 if (d_cplength < idx)
02220 throw std::out_of_range("Index is out of range for CEGUI::String");
02221
02222 if (num == npos)
02223 throw std::length_error("Code point count can not be 'npos'");
02224
02225 size_type newsz = d_cplength + num;
02226 grow(newsz);
02227
02228 memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02229
02230 utf32* pt = &ptr()[idx + num - 1];
02231
02232 while(num--)
02233 *pt-- = code_point;
02234
02235 setlen(newsz);
02236
02237 return *this;
02238 }
02239
02258 void insert(iterator pos, size_type num, utf32 code_point)
02259 {
02260 insert(safe_iter_dif(pos, begin()), num, code_point);
02261 }
02262
02278 iterator insert(iterator pos, utf32 code_point)
02279 {
02280 insert(pos, 1, code_point);
02281 return pos;
02282 }
02283
02302 void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
02303 {
02304 replace(iter_pos, iter_pos, iter_beg, iter_end);
02305 }
02306
02307
02324 String& insert(size_type idx, const char* cstr)
02325 {
02326 return insert(idx, cstr, strlen(cstr));
02327 }
02328
02329
02349 String& insert(size_type idx, const char* chars, size_type chars_len)
02350 {
02351 if (d_cplength < idx)
02352 throw std::out_of_range("Index is out of range for CEGUI::String");
02353
02354 if (chars_len == npos)
02355 throw std::length_error("Length of char array can not be 'npos'");
02356
02357 size_type newsz = d_cplength + chars_len;
02358
02359 grow(newsz);
02360 memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02361
02362 utf32* pt = &ptr()[idx + chars_len - 1];
02363
02364 while(chars_len--)
02365 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
02366
02367 setlen(newsz);
02368
02369 return *this;
02370 }
02371
02372
02374
02376
02383 void clear(void)
02384 {
02385 setlen(0);
02386 trim();
02387 }
02388
02396 String& erase(void)
02397 {
02398 clear();
02399 return *this;
02400 }
02401
02414 String& erase(size_type idx)
02415 {
02416 return erase(idx, 1);
02417 }
02418
02434 String& erase(size_type idx, size_type len = npos)
02435 {
02436 if (d_cplength < idx)
02437 throw std::out_of_range("Index is out of range foe CEGUI::String");
02438
02439 if (len == npos)
02440 len = d_cplength - idx;
02441
02442 size_type newsz = d_cplength - len;
02443
02444 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
02445 setlen(newsz);
02446 return *this;
02447 }
02448
02459 String& erase(iterator pos)
02460 {
02461 return erase(safe_iter_dif(pos, begin()), 1);
02462 }
02463
02477 String& erase(iterator iter_beg, iterator iter_end)
02478 {
02479 return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
02480 }
02481
02483
02485
02497 void resize(size_type num)
02498 {
02499 resize(num, utf32());
02500 }
02501
02517 void resize(size_type num, utf32 code_point)
02518 {
02519 if (num < d_cplength)
02520 {
02521 setlen(num);
02522 }
02523 else
02524 {
02525 append(num - d_cplength, code_point);
02526 }
02527
02528 }
02529
02531
02533
02552 String& replace(size_type idx, size_type len, const String& str)
02553 {
02554 return replace(idx, len, str, 0, npos);
02555 }
02556
02578 String& replace(iterator iter_beg, iterator iter_end, const String& str)
02579 {
02580 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
02581 }
02582
02608 String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
02609 {
02610 if ((d_cplength < idx) || (str.d_cplength < str_idx))
02611 throw std::out_of_range("Index is out of range for CEGUI::String");
02612
02613 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
02614 str_num = str.d_cplength - str_idx;
02615
02616 if (((len + idx) > d_cplength) || (len == npos))
02617 len = d_cplength - idx;
02618
02619 size_type newsz = d_cplength + str_num - len;
02620
02621 grow(newsz);
02622
02623 if ((idx + len) < d_cplength)
02624 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02625
02626 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02627 setlen(newsz);
02628
02629 return *this;
02630 }
02631
02632
02656 String& replace(size_type idx, size_type len, const std::string& std_str)
02657 {
02658 return replace(idx, len, std_str, 0, npos);
02659 }
02660
02686 String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
02687 {
02688 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
02689 }
02690
02720 String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
02721 {
02722 if (d_cplength < idx)
02723 throw std::out_of_range("Index is out of range for CEGUI::String");
02724
02725 if (std_str.size() < str_idx)
02726 throw std::out_of_range("Index is out of range for std::string");
02727
02728 if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
02729 str_num = (size_type)std_str.size() - str_idx;
02730
02731 if (((len + idx) > d_cplength) || (len == npos))
02732 len = d_cplength - idx;
02733
02734 size_type newsz = d_cplength + str_num - len;
02735
02736 grow(newsz);
02737
02738 if ((idx + len) < d_cplength)
02739 memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02740
02741 utf32* pt = &ptr()[idx + str_num - 1];
02742
02743 while (str_num--)
02744 *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02745
02746 setlen(newsz);
02747
02748 return *this;
02749 }
02750
02751
02777 String& replace(size_type idx, size_type len, const utf8* utf8_str)
02778 {
02779 return replace(idx, len, utf8_str, utf_length(utf8_str));
02780 }
02781
02809 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
02810 {
02811 return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
02812 }
02813
02842 String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
02843 {
02844 if (d_cplength < idx)
02845 throw std::out_of_range("Index is out of range for CEGUI::String");
02846
02847 if (str_len == npos)
02848 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
02849
02850 if (((len + idx) > d_cplength) || (len == npos))
02851 len = d_cplength - idx;
02852
02853 size_type encsz = encoded_size(utf8_str, str_len);
02854 size_type newsz = d_cplength + encsz - len;
02855
02856 grow(newsz);
02857
02858 if ((idx + len) < d_cplength)
02859 memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02860
02861 encode(utf8_str, &ptr()[idx], encsz, str_len);
02862
02863 setlen(newsz);
02864 return *this;
02865 }
02866
02897 String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
02898 {
02899 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
02900 }
02901
02924 String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
02925 {
02926 if (d_cplength < idx)
02927 throw std::out_of_range("Index is out of range for CEGUI::String");
02928
02929 if (num == npos)
02930 throw std::length_error("Code point count can not be 'npos'");
02931
02932 if (((len + idx) > d_cplength) || (len == npos))
02933 len = d_cplength - idx;
02934
02935 size_type newsz = d_cplength + num - len;
02936
02937 grow(newsz);
02938
02939 if ((idx + len) < d_cplength)
02940 memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02941
02942 utf32* pt = &ptr()[idx + num - 1];
02943
02944 while (num--)
02945 *pt-- = code_point;
02946
02947 setlen(newsz);
02948
02949 return *this;
02950 }
02951
02976 String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
02977 {
02978 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
02979 }
02980
02981
03006 String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
03007 {
03008 if (iter_beg == iter_end)
03009 {
03010 erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
03011 }
03012 else
03013 {
03014 size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
03015 size_type idx = safe_iter_dif(iter_beg, begin());
03016 size_type len = safe_iter_dif(iter_end, iter_beg);
03017
03018 if ((len + idx) > d_cplength)
03019 len = d_cplength - idx;
03020
03021 size_type newsz = d_cplength + str_len - len;
03022
03023 grow(newsz);
03024
03025 if ((idx + len) < d_cplength)
03026 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
03027
03028 memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
03029 setlen(newsz);
03030 }
03031
03032 return *this;
03033 }
03034
03035
03055 String& replace(size_type idx, size_type len, const char* cstr)
03056 {
03057 return replace(idx, len, cstr, strlen(cstr));
03058 }
03059
03060
03082 String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
03083 {
03084 return replace(iter_beg, iter_end, cstr, strlen(cstr));
03085 }
03086
03087
03110 String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
03111 {
03112 if (d_cplength < idx)
03113 throw std::out_of_range("Index is out of range for CEGUI::String");
03114
03115 if (chars_len == npos)
03116 throw std::length_error("Length for the char array can not be 'npos'");
03117
03118 if (((len + idx) > d_cplength) || (len == npos))
03119 len = d_cplength - idx;
03120
03121 size_type newsz = d_cplength + chars_len - len;
03122
03123 grow(newsz);
03124
03125 if ((idx + len) < d_cplength)
03126 memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
03127
03128 utf32* pt = &ptr()[idx + chars_len - 1];
03129
03130 while (chars_len--)
03131 *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
03132
03133 setlen(newsz);
03134 return *this;
03135 }
03136
03137
03162 String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
03163 {
03164 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
03165 }
03166
03167
03169
03171
03185 size_type find(utf32 code_point, size_type idx = 0) const
03186 {
03187 if (idx < d_cplength)
03188 {
03189 const utf32* pt = &ptr()[idx];
03190
03191 while (idx < d_cplength)
03192 {
03193 if (*pt++ == code_point)
03194 return idx;
03195
03196 ++idx;
03197 }
03198
03199 }
03200
03201 return npos;
03202 }
03203
03218 size_type rfind(utf32 code_point, size_type idx = npos) const
03219 {
03220 if (idx >= d_cplength)
03221 idx = d_cplength - 1;
03222
03223 if (d_cplength > 0)
03224 {
03225 const utf32* pt = &ptr()[idx];
03226
03227 do
03228 {
03229 if (*pt-- == code_point)
03230 return idx;
03231
03232 } while (idx-- != 0);
03233
03234 }
03235
03236 return npos;
03237 }
03238
03240
03242
03256 size_type find(const String& str, size_type idx = 0) const
03257 {
03258 if ((str.d_cplength == 0) && (idx < d_cplength))
03259 return idx;
03260
03261 if (idx < d_cplength)
03262 {
03263
03264 while (d_cplength - idx >= str.d_cplength)
03265 {
03266 if (0 == compare(idx, str.d_cplength, str))
03267 return idx;
03268
03269 ++idx;
03270 }
03271
03272 }
03273
03274 return npos;
03275 }
03276
03291 size_type rfind(const String& str, size_type idx = npos) const
03292 {
03293 if (str.d_cplength == 0)
03294 return (idx < d_cplength) ? idx : d_cplength;
03295
03296 if (str.d_cplength <= d_cplength)
03297 {
03298 if (idx > (d_cplength - str.d_cplength))
03299 idx = d_cplength - str.d_cplength;
03300
03301 do
03302 {
03303 if (0 == compare(idx, str.d_cplength, str))
03304 return idx;
03305
03306 } while (idx-- != 0);
03307
03308 }
03309
03310 return npos;
03311 }
03312
03331 size_type find(const std::string& std_str, size_type idx = 0) const
03332 {
03333 std::string::size_type sze = std_str.size();
03334
03335 if ((sze == 0) && (idx < d_cplength))
03336 return idx;
03337
03338 if (idx < d_cplength)
03339 {
03340
03341 while (d_cplength - idx >= sze)
03342 {
03343 if (0 == compare(idx, (size_type)sze, std_str))
03344 return idx;
03345
03346 ++idx;
03347 }
03348
03349 }
03350
03351 return npos;
03352 }
03353
03372 size_type rfind(const std::string& std_str, size_type idx = npos) const
03373 {
03374 std::string::size_type sze = std_str.size();
03375
03376 if (sze == 0)
03377 return (idx < d_cplength) ? idx : d_cplength;
03378
03379 if (sze <= d_cplength)
03380 {
03381 if (idx > (d_cplength - sze))
03382 idx = d_cplength - sze;
03383
03384 do
03385 {
03386 if (0 == compare(idx, (size_type)sze, std_str))
03387 return idx;
03388
03389 } while (idx-- != 0);
03390
03391 }
03392
03393 return npos;
03394 }
03395
03418 size_type find(const utf8* utf8_str, size_type idx = 0) const
03419 {
03420 return find(utf8_str, idx, utf_length(utf8_str));
03421 }
03422
03445 size_type rfind(const utf8* utf8_str, size_type idx = npos) const
03446 {
03447 return rfind(utf8_str, idx, utf_length(utf8_str));
03448 }
03449
03475 size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const
03476 {
03477 if (str_len == npos)
03478 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03479
03480 size_type sze = encoded_size(utf8_str, str_len);
03481
03482 if ((sze == 0) && (idx < d_cplength))
03483 return idx;
03484
03485 if (idx < d_cplength)
03486 {
03487
03488 while (d_cplength - idx >= sze)
03489 {
03490 if (0 == compare(idx, sze, utf8_str, sze))
03491 return idx;
03492
03493 ++idx;
03494 }
03495
03496 }
03497
03498 return npos;
03499 }
03500
03526 size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
03527 {
03528 if (str_len == npos)
03529 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03530
03531 size_type sze = encoded_size(utf8_str, str_len);
03532
03533 if (sze == 0)
03534 return (idx < d_cplength) ? idx : d_cplength;
03535
03536 if (sze <= d_cplength)
03537 {
03538 if (idx > (d_cplength - sze))
03539 idx = d_cplength - sze;
03540
03541 do
03542 {
03543 if (0 == compare(idx, sze, utf8_str, sze))
03544 return idx;
03545
03546 } while (idx-- != 0);
03547
03548 }
03549
03550 return npos;
03551 }
03552
03553
03570 size_type find(const char* cstr, size_type idx = 0) const
03571 {
03572 return find(cstr, idx, strlen(cstr));
03573 }
03574
03575
03592 size_type rfind(const char* cstr, size_type idx = npos) const
03593 {
03594 return rfind(cstr, idx, strlen(cstr));
03595 }
03596
03597
03617 size_type find(const char* chars, size_type idx, size_type chars_len) const
03618 {
03619 if (chars_len == npos)
03620 throw std::length_error("Length for char array can not be 'npos'");
03621
03622 if ((chars_len == 0) && (idx < d_cplength))
03623 return idx;
03624
03625 if (idx < d_cplength)
03626 {
03627
03628 while (d_cplength - idx >= chars_len)
03629 {
03630 if (0 == compare(idx, chars_len, chars, chars_len))
03631 return idx;
03632
03633 ++idx;
03634 }
03635
03636 }
03637
03638 return npos;
03639 }
03640
03641
03661 size_type rfind(const char* chars, size_type idx, size_type chars_len) const
03662 {
03663 if (chars_len == npos)
03664 throw std::length_error("Length for char array can not be 'npos'");
03665
03666 if (chars_len == 0)
03667 return (idx < d_cplength) ? idx : d_cplength;
03668
03669 if (chars_len <= d_cplength)
03670 {
03671 if (idx > (d_cplength - chars_len))
03672 idx = d_cplength - chars_len;
03673
03674 do
03675 {
03676 if (0 == compare(idx, chars_len, chars, chars_len))
03677 return idx;
03678
03679 } while (idx-- != 0);
03680
03681 }
03682
03683 return npos;
03684 }
03685
03686
03688
03690
03704 size_type find_first_of(const String& str, size_type idx = 0) const
03705 {
03706 if (idx < d_cplength)
03707 {
03708 const utf32* pt = &ptr()[idx];
03709
03710 do
03711 {
03712 if (npos != str.find(*pt++))
03713 return idx;
03714
03715 } while (++idx != d_cplength);
03716
03717 }
03718
03719 return npos;
03720 }
03721
03736 size_type find_first_not_of(const String& str, size_type idx = 0) const
03737 {
03738 if (idx < d_cplength)
03739 {
03740 const utf32* pt = &ptr()[idx];
03741
03742 do
03743 {
03744 if (npos == str.find(*pt++))
03745 return idx;
03746
03747 } while (++idx != d_cplength);
03748
03749 }
03750
03751 return npos;
03752 }
03753
03754
03773 size_type find_first_of(const std::string& std_str, size_type idx = 0) const
03774 {
03775 if (idx < d_cplength)
03776 {
03777 const utf32* pt = &ptr()[idx];
03778
03779 do
03780 {
03781 if (npos != find_codepoint(std_str, *pt++))
03782 return idx;
03783
03784 } while (++idx != d_cplength);
03785
03786 }
03787
03788 return npos;
03789 }
03790
03809 size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const
03810 {
03811 if (idx < d_cplength)
03812 {
03813 const utf32* pt = &ptr()[idx];
03814
03815 do
03816 {
03817 if (npos == find_codepoint(std_str, *pt++))
03818 return idx;
03819
03820 } while (++idx != d_cplength);
03821
03822 }
03823
03824 return npos;
03825 }
03826
03827
03850 size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const
03851 {
03852 return find_first_of(utf8_str, idx, utf_length(utf8_str));
03853 }
03854
03877 size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
03878 {
03879 return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
03880 }
03881
03907 size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03908 {
03909 if (str_len == npos)
03910 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03911
03912 if (idx < d_cplength)
03913 {
03914 size_type encsze = encoded_size(utf8_str, str_len);
03915
03916 const utf32* pt = &ptr()[idx];
03917
03918 do
03919 {
03920 if (npos != find_codepoint(utf8_str, encsze, *pt++))
03921 return idx;
03922
03923 } while (++idx != d_cplength);
03924
03925 }
03926
03927 return npos;
03928 }
03929
03955 size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03956 {
03957 if (str_len == npos)
03958 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03959
03960 if (idx < d_cplength)
03961 {
03962 size_type encsze = encoded_size(utf8_str, str_len);
03963
03964 const utf32* pt = &ptr()[idx];
03965
03966 do
03967 {
03968 if (npos == find_codepoint(utf8_str, encsze, *pt++))
03969 return idx;
03970
03971 } while (++idx != d_cplength);
03972
03973 }
03974
03975 return npos;
03976 }
03977
03978
03993 size_type find_first_of(utf32 code_point, size_type idx = 0) const
03994 {
03995 return find(code_point, idx);
03996 }
03997
04014 size_type find_first_not_of(utf32 code_point, size_type idx = 0) const
04015 {
04016 if (idx < d_cplength)
04017 {
04018 do
04019 {
04020 if ((*this)[idx] != code_point)
04021 return idx;
04022
04023 } while(idx++ < d_cplength);
04024
04025 }
04026
04027 return npos;
04028 }
04029
04030
04047 size_type find_first_of(const char* cstr, size_type idx = 0) const
04048 {
04049 return find_first_of(cstr, idx, strlen(cstr));
04050 }
04051
04052
04069 size_type find_first_not_of(const char* cstr, size_type idx = 0) const
04070 {
04071 return find_first_not_of(cstr, idx, strlen(cstr));
04072 }
04073
04074
04094 size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const
04095 {
04096 if (chars_len == npos)
04097 throw std::length_error("Length for char array can not be 'npos'");
04098
04099 if (idx < d_cplength)
04100 {
04101 const utf32* pt = &ptr()[idx];
04102
04103 do
04104 {
04105 if (npos != find_codepoint(chars, chars_len, *pt++))
04106 return idx;
04107
04108 } while (++idx != d_cplength);
04109
04110 }
04111
04112 return npos;
04113 }
04114
04115
04135 size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
04136 {
04137 if (chars_len == npos)
04138 throw std::length_error("Length for char array can not be 'npos'");
04139
04140 if (idx < d_cplength)
04141 {
04142 const utf32* pt = &ptr()[idx];
04143
04144 do
04145 {
04146 if (npos == find_codepoint(chars, chars_len, *pt++))
04147 return idx;
04148
04149 } while (++idx != d_cplength);
04150
04151 }
04152
04153 return npos;
04154 }
04155
04156
04158
04160
04174 size_type find_last_of(const String& str, size_type idx = npos) const
04175 {
04176 if (d_cplength > 0)
04177 {
04178 if (idx >= d_cplength)
04179 idx = d_cplength - 1;
04180
04181 const utf32* pt = &ptr()[idx];
04182
04183 do
04184 {
04185 if (npos != str.find(*pt--))
04186 return idx;
04187
04188 } while (idx-- != 0);
04189
04190 }
04191
04192 return npos;
04193 }
04194
04209 size_type find_last_not_of(const String& 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 == str.find(*pt--))
04221 return idx;
04222
04223 } while (idx-- != 0);
04224
04225 }
04226
04227 return npos;
04228 }
04229
04230
04249 size_type find_last_of(const std::string& std_str, size_type idx = npos) const
04250 {
04251 if (d_cplength > 0)
04252 {
04253 if (idx >= d_cplength)
04254 idx = d_cplength - 1;
04255
04256 const utf32* pt = &ptr()[idx];
04257
04258 do
04259 {
04260 if (npos != find_codepoint(std_str, *pt--))
04261 return idx;
04262
04263 } while (idx-- != 0);
04264
04265 }
04266
04267 return npos;
04268 }
04269
04288 size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const
04289 {
04290 if (d_cplength > 0)
04291 {
04292 if (idx >= d_cplength)
04293 idx = d_cplength - 1;
04294
04295 const utf32* pt = &ptr()[idx];
04296
04297 do
04298 {
04299 if (npos == find_codepoint(std_str, *pt--))
04300 return idx;
04301
04302 } while (idx-- != 0);
04303
04304 }
04305
04306 return npos;
04307 }
04308
04309
04332 size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const
04333 {
04334 return find_last_of(utf8_str, idx, utf_length(utf8_str));
04335 }
04336
04359 size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
04360 {
04361 return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
04362 }
04363
04389 size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04390 {
04391 if (str_len == npos)
04392 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
04393
04394 if (d_cplength > 0)
04395 {
04396 if (idx >= d_cplength)
04397 idx = d_cplength - 1;
04398
04399 size_type encsze = encoded_size(utf8_str, str_len);
04400
04401 const utf32* pt = &ptr()[idx];
04402
04403 do
04404 {
04405 if (npos != find_codepoint(utf8_str, encsze, *pt--))
04406 return idx;
04407
04408 } while (idx-- != 0);
04409
04410 }
04411
04412 return npos;
04413 }
04414
04440 size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04441 {
04442 if (str_len == npos)
04443 throw std::length_error("Length for utf8 encoded string can not be 'npos'");
04444
04445 if (d_cplength > 0)
04446 {
04447 if (idx >= d_cplength)
04448 idx = d_cplength - 1;
04449
04450 size_type encsze = encoded_size(utf8_str, str_len);
04451
04452 const utf32* pt = &ptr()[idx];
04453
04454 do
04455 {
04456 if (npos == find_codepoint(utf8_str, encsze, *pt--))
04457 return idx;
04458
04459 } while (idx-- != 0);
04460
04461 }
04462
04463 return npos;
04464 }
04465
04466
04481 size_type find_last_of(utf32 code_point, size_type idx = npos) const
04482 {
04483 return rfind(code_point, idx);
04484 }
04485
04500 size_type find_last_not_of(utf32 code_point, size_type idx = npos) const
04501 {
04502 if (d_cplength > 0)
04503 {
04504 if (idx >= d_cplength)
04505 idx = d_cplength - 1;
04506
04507 do
04508 {
04509 if ((*this)[idx] != code_point)
04510 return idx;
04511
04512 } while(idx-- != 0);
04513
04514 }
04515
04516 return npos;
04517 }
04518
04519
04536 size_type find_last_of(const char* cstr, size_type idx = npos) const
04537 {
04538 return find_last_of(cstr, idx, strlen(cstr));
04539 }
04540
04541
04558 size_type find_last_not_of(const char* cstr, size_type idx = npos) const
04559 {
04560 return find_last_not_of(cstr, idx, strlen(cstr));
04561 }
04562
04563
04583 size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const
04584 {
04585 if (chars_len == npos)
04586 throw std::length_error("Length for char array can not be 'npos'");
04587
04588 if (d_cplength > 0)
04589 {
04590 if (idx >= d_cplength)
04591 idx = d_cplength - 1;
04592
04593 const utf32* pt = &ptr()[idx];
04594
04595 do
04596 {
04597 if (npos != find_codepoint(chars, chars_len, *pt--))
04598 return idx;
04599
04600 } while (idx-- != 0);
04601
04602 }
04603
04604 return npos;
04605 }
04606
04607
04627 size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
04628 {
04629 if (chars_len == npos)
04630 throw std::length_error("Length for char array can not be 'npos'");
04631
04632 if (d_cplength > 0)
04633 {
04634 if (idx >= d_cplength)
04635 idx = d_cplength - 1;
04636
04637 const utf32* pt = &ptr()[idx];
04638
04639 do
04640 {
04641 if (npos == find_codepoint(chars, chars_len, *pt--))
04642 return idx;
04643
04644 } while (idx-- != 0);
04645
04646 }
04647
04648 return npos;
04649 }
04650
04651
04653
04655
04670 String substr(size_type idx = 0, size_type len = npos) const
04671 {
04672 if (d_cplength < idx)
04673 throw std::out_of_range("Index is out of range for this CEGUI::String");
04674
04675 return String(*this, idx, len);
04676 }
04677
04679
04681
04688 iterator begin(void)
04689 {
04690 return iterator(ptr());
04691 }
04692
04700 const_iterator begin(void) const
04701 {
04702 return const_iterator(ptr());
04703 }
04704
04712 iterator end(void)
04713 {
04714 return iterator(&ptr()[d_cplength]);
04715 }
04716
04724 const_iterator end(void) const
04725 {
04726 return const_iterator(&ptr()[d_cplength]);
04727 }
04728
04736 reverse_iterator rbegin(void)
04737 {
04738 return reverse_iterator(end());
04739 }
04740
04748 const_reverse_iterator rbegin(void) const
04749 {
04750 return const_reverse_iterator(end());
04751 }
04752
04760 reverse_iterator rend(void)
04761 {
04762 return reverse_iterator(begin());
04763 }
04764
04772 const_reverse_iterator rend(void) const
04773 {
04774 return const_reverse_iterator(begin());
04775 }
04776
04777 private:
04778
04779
04780
04781
04782
04783
04784
04785
04786 bool grow(size_type new_size);
04787
04788
04789 void trim(void);
04790
04791
04792 void setlen(size_type len)
04793 {
04794 d_cplength = len;
04795 ptr()[len] = (utf32)(0);
04796 }
04797
04798
04799 void init(void)
04800 {
04801 d_reserve = STR_QUICKBUFF_SIZE;
04802 d_encodedbuff = 0;
04803 d_encodedbufflen = 0;
04804 d_encodeddatlen = 0;
04805 d_buffer = 0;
04806 setlen(0);
04807 }
04808
04809
04810 bool inside(utf32* inptr)
04811 {
04812 if (inptr < ptr() || ptr() + d_cplength <= inptr)
04813 return false;
04814 else
04815 return true;
04816 }
04817
04818
04819 size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
04820 {
04821 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
04822 }
04823
04824
04825
04826
04827
04828
04829 size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
04830 {
04831
04832 if (src_len == 0)
04833 {
04834 src_len = utf_length(src);
04835 }
04836
04837 size_type destCapacity = dest_len;
04838
04839
04840 for (uint idx = 0; idx < src_len; ++idx)
04841 {
04842 utf32 cp = src[idx];
04843
04844
04845 if (destCapacity < encoded_size(cp))
04846 {
04847 break;
04848 }
04849
04850 if (cp < 0x80)
04851 {
04852 *dest++ = (utf8)cp;
04853 --destCapacity;
04854 }
04855 else if (cp < 0x0800)
04856 {
04857 *dest++ = (utf8)((cp >> 6) | 0xC0);
04858 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04859 destCapacity -= 2;
04860 }
04861 else if (cp < 0x10000)
04862 {
04863 *dest++ = (utf8)((cp >> 12) | 0xE0);
04864 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04865 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04866 destCapacity -= 3;
04867 }
04868 else
04869 {
04870 *dest++ = (utf8)((cp >> 18) | 0xF0);
04871 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
04872 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04873 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04874 destCapacity -= 4;
04875 }
04876
04877 }
04878
04879 return dest_len - destCapacity;
04880 }
04881
04882 size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
04883 {
04884
04885 if (src_len == 0)
04886 {
04887 src_len = utf_length(src);
04888 }
04889
04890 size_type destCapacity = dest_len;
04891
04892
04893 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
04894 {
04895 utf32 cp;
04896 utf8 cu = src[idx++];
04897
04898 if (cu < 0x80)
04899 {
04900 cp = (utf32)(cu);
04901 }
04902 else if (cu < 0xE0)
04903 {
04904 cp = ((cu & 0x1F) << 6);
04905 cp |= (src[idx++] & 0x3F);
04906 }
04907 else if (cu < 0xF0)
04908 {
04909 cp = ((cu & 0x0F) << 12);
04910 cp |= ((src[idx++] & 0x3F) << 6);
04911 cp |= (src[idx++] & 0x3F);
04912 }
04913 else
04914 {
04915 cp = ((cu & 0x07) << 18);
04916 cp |= ((src[idx++] & 0x3F) << 12);
04917 cp |= ((src[idx++] & 0x3F) << 6);
04918 cp |= (src[idx++] & 0x3F);
04919 }
04920
04921 *dest++ = cp;
04922 --destCapacity;
04923 }
04924
04925 return dest_len - destCapacity;
04926 }
04927
04928
04929 size_type encoded_size(utf32 code_point) const
04930 {
04931 if (code_point < 0x80)
04932 return 1;
04933 else if (code_point < 0x0800)
04934 return 2;
04935 else if (code_point < 0x10000)
04936 return 3;
04937 else
04938 return 4;
04939 }
04940
04941
04942 size_type encoded_size(const utf32* buf) const
04943 {
04944 return encoded_size(buf, utf_length(buf));
04945 }
04946
04947
04948 size_type encoded_size(const utf32* buf, size_type len) const
04949 {
04950 size_type count = 0;
04951
04952 while (len--)
04953 {
04954 count += encoded_size(*buf++);
04955 }
04956
04957 return count;
04958 }
04959
04960
04961 size_type encoded_size(const utf8* buf) const
04962 {
04963 return encoded_size(buf, utf_length(buf));
04964 }
04965
04966
04967 size_type encoded_size(const utf8* buf, size_type len) const
04968 {
04969 utf8 tcp;
04970 size_type count = 0;
04971
04972 while (len--)
04973 {
04974 tcp = *buf++;
04975 ++count;
04976
04977 if (tcp < 0x80)
04978 {
04979 }
04980 else if (tcp < 0xE0)
04981 {
04982 --len;
04983 ++buf;
04984 }
04985 else if (tcp < 0xF0)
04986 {
04987 len -= 2;
04988 buf += 2;
04989 }
04990 else
04991 {
04992 len -= 2;
04993 buf += 3;
04994 }
04995
04996 }
04997
04998 return count;
04999 }
05000
05001
05002 size_type utf_length(const utf8* utf8_str) const
05003 {
05004 size_type cnt = 0;
05005 while (*utf8_str++)
05006 cnt++;
05007
05008 return cnt;
05009 }
05010
05011
05012 size_type utf_length(const utf32* utf32_str) const
05013 {
05014 size_type cnt = 0;
05015 while (*utf32_str++)
05016 cnt++;
05017
05018 return cnt;
05019 }
05020
05021
05022 utf8* build_utf8_buff(void) const;
05023
05024
05025 int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
05026 {
05027 if (!cp_count)
05028 return 0;
05029
05030 while ((--cp_count) && (*buf1 == *buf2))
05031 buf1++, buf2++;
05032
05033 return *buf1 - *buf2;
05034 }
05035
05036
05037 int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
05038 {
05039 if (!cp_count)
05040 return 0;
05041
05042 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
05043 buf1++, buf2++;
05044
05045 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
05046 }
05047
05048
05049 int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
05050 {
05051 if (!cp_count)
05052 return 0;
05053
05054 utf32 cp;
05055 utf8 cu;
05056
05057 do
05058 {
05059 cu = *buf2++;
05060
05061 if (cu < 0x80)
05062 {
05063 cp = (utf32)(cu);
05064 }
05065 else if (cu < 0xE0)
05066 {
05067 cp = ((cu & 0x1F) << 6);
05068 cp |= (*buf2++ & 0x3F);
05069 }
05070 else if (cu < 0xF0)
05071 {
05072 cp = ((cu & 0x0F) << 12);
05073 cp |= ((*buf2++ & 0x3F) << 6);
05074 cp |= (*buf2++ & 0x3F);
05075 }
05076 else
05077 {
05078 cp = ((cu & 0x07) << 18);
05079 cp |= ((*buf2++ & 0x3F) << 12);
05080 cp |= ((*buf2++ & 0x3F) << 6);
05081 cp |= (*buf2++ & 0x3F);
05082 }
05083
05084 } while ((*buf1++ == cp) && (--cp_count));
05085
05086 return (*--buf1) - cp;
05087 }
05088
05089
05090 size_type find_codepoint(const std::string& str, utf32 code_point) const
05091 {
05092 size_type idx = 0, sze = (size_type)str.size();
05093
05094 while (idx != sze)
05095 {
05096 if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
05097 return idx;
05098
05099 ++idx;
05100 }
05101
05102 return npos;
05103 }
05104
05105
05106 size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
05107 {
05108 size_type idx = 0;
05109
05110 utf32 cp;
05111 utf8 cu;
05112
05113 while (idx != len) {
05114 cu = *str++;
05115
05116 if (cu < 0x80)
05117 {
05118 cp = (utf32)(cu);
05119 }
05120 else if (cu < 0xE0)
05121 {
05122 cp = ((cu & 0x1F) << 6);
05123 cp |= (*str++ & 0x3F);
05124 }
05125 else if (cu < 0xF0)
05126 {
05127 cp = ((cu & 0x0F) << 12);
05128 cp |= ((*str++ & 0x3F) << 6);
05129 cp |= (*str++ & 0x3F);
05130 }
05131 else
05132 {
05133 cp = ((cu & 0x07) << 18);
05134 cp |= ((*str++ & 0x3F) << 12);
05135 cp |= ((*str++ & 0x3F) << 6);
05136 cp |= (*str++ & 0x3F);
05137 }
05138
05139 if (code_point == cp)
05140 return idx;
05141
05142 ++idx;
05143 }
05144
05145 return npos;
05146 }
05147
05148
05149
05150 size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
05151 {
05152 for (size_type idx = 0; idx != chars_len; ++idx)
05153 {
05154 if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
05155 return idx;
05156 }
05157
05158 return npos;
05159 }
05160
05161 };
05162
05163
05165
05167
05171 bool CEGUIEXPORT operator==(const String& str1, const String& str2);
05172
05177 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str);
05178
05183 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str);
05184
05189 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str);
05190
05195 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str);
05196
05201 bool CEGUIEXPORT operator!=(const String& str1, const String& str2);
05202
05207 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str);
05208
05213 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str);
05214
05219 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str);
05220
05225 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str);
05226
05231 bool CEGUIEXPORT operator<(const String& str1, const String& str2);
05232
05237 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str);
05238
05243 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str);
05244
05249 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str);
05250
05255 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str);
05256
05261 bool CEGUIEXPORT operator>(const String& str1, const String& str2);
05262
05267 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str);
05268
05273 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str);
05274
05279 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str);
05280
05285 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str);
05286
05291 bool CEGUIEXPORT operator<=(const String& str1, const String& str2);
05292
05297 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str);
05298
05303 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str);
05304
05309 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str);
05310
05315 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str);
05316
05321 bool CEGUIEXPORT operator>=(const String& str1, const String& str2);
05322
05327 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str);
05328
05333 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str);
05334
05339 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str);
05340
05345 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str);
05346
05351 bool CEGUIEXPORT operator==(const String& str, const char* c_str);
05352
05357 bool CEGUIEXPORT operator==(const char* c_str, const String& str);
05358
05363 bool CEGUIEXPORT operator!=(const String& str, const char* c_str);
05364
05369 bool CEGUIEXPORT operator!=(const char* c_str, const String& str);
05370
05375 bool CEGUIEXPORT operator<(const String& str, const char* c_str);
05376
05381 bool CEGUIEXPORT operator<(const char* c_str, const String& str);
05382
05387 bool CEGUIEXPORT operator>(const String& str, const char* c_str);
05388
05393 bool CEGUIEXPORT operator>(const char* c_str, const String& str);
05394
05399 bool CEGUIEXPORT operator<=(const String& str, const char* c_str);
05400
05405 bool CEGUIEXPORT operator<=(const char* c_str, const String& str);
05406
05411 bool CEGUIEXPORT operator>=(const String& str, const char* c_str);
05412
05417 bool CEGUIEXPORT operator>=(const char* c_str, const String& str);
05418
05420
05422
05437 String CEGUIEXPORT operator+(const String& str1, const String& str2);
05438
05454 String CEGUIEXPORT operator+(const String& str, const std::string& std_str);
05455
05471 String CEGUIEXPORT operator+(const std::string& std_str, const String& str);
05472
05488 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str);
05489
05505 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str);
05506
05522 String CEGUIEXPORT operator+(const String& str, utf32 code_point);
05523
05539 String CEGUIEXPORT operator+(utf32 code_point, const String& str);
05540
05556 String CEGUIEXPORT operator+(const String& str, const char* c_str);
05557
05573 String CEGUIEXPORT operator+(const char* c_str, const String& str);
05574
05575
05577
05579 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
05580
05581
05583
05585
05598 void CEGUIEXPORT swap(String& str1, String& str2);
05599
05600
05601 }
05602
05603
05604 #endif // end of guard _CEGUIString_h_