CEGUIString.h

00001 /************************************************************************
00002         filename:       CEGUIString.h
00003         created:        26/2/2004
00004         author:         Paul D Turner
00005         
00006         purpose:        Defines string class used within the GUI system.
00007 *************************************************************************/
00008 /*************************************************************************
00009     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00010     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00011 
00012     This library is free software; you can redistribute it and/or
00013     modify it under the terms of the GNU Lesser General Public
00014     License as published by the Free Software Foundation; either
00015     version 2.1 of the License, or (at your option) any later version.
00016 
00017     This library is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020     Lesser General Public License for more details.
00021 
00022     You should have received a copy of the GNU Lesser General Public
00023     License along with this library; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // Start of CEGUI namespace section
00035 namespace CEGUI
00036 {
00037 #define STR_QUICKBUFF_SIZE      32
00038         /*************************************************************************
00039                 Basic Types
00040         *************************************************************************/
00041         typedef         uint8   utf8;
00042         //typedef               uint16  utf16;  // removed typedef to prevent usage, as utf16 is not supported (yet)
00043         typedef         uint32  utf32;
00044 
00053 class CEGUIEXPORT String
00054 {
00055 public:
00056         /*************************************************************************
00057                 Integral Types
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                 Implementation data
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                 Iterator Classes
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                 // data
00102                 const utf32*    d_ptr;
00103 
00104 
00106                 // Methods
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         // Default Construction and Destructor
00351 
00355         String(void)
00356         {
00357                 init();
00358         }
00359 
00364         ~String(void);
00365 
00367         // Construction via CEGUI::String
00369 
00379         String(const String& str)
00380         {
00381                 init();
00382                 assign(str);
00383         }
00384         
00385 
00402         String(const String& str, size_type str_idx, size_type str_num = npos)
00403         {
00404                 init();
00405                 assign(str, str_idx, str_num);
00406         }
00407 
00409         // Construction via std::string
00411 
00427         String(const std::string& std_str)
00428         {
00429                 init();
00430                 assign(std_str);
00431         }
00432                 
00455         String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
00456         {
00457                 init();
00458                 assign(std_str, str_idx, str_num);
00459         }
00460 
00461 
00463         // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
00465 
00483         String(const utf8* utf8_str)
00484         {
00485                 init();
00486                 assign(utf8_str);
00487         }
00488 
00515         String(const utf8* utf8_str, size_type chars_len)
00516         {
00517                 init();
00518                 assign(utf8_str, chars_len);
00519         }
00520 
00522         // Construction via code-point (using a UTF-32 code unit)
00524 
00539         String(size_type num, utf32 code_point)
00540         {
00541                 init();
00542                 assign(num, code_point);
00543         }
00544 
00546         // Construction via iterator
00548         // Create string with characters in the range [beg, end)
00562         String(const_iterator iter_beg, const_iterator iter_end)
00563         {
00564                 init();
00565                 append(iter_beg, iter_end);
00566         }
00567 
00568 
00570         // Construction via c-string
00572 
00584         String(const char* cstr)
00585         {
00586                 init();
00587                 assign(cstr);
00588         }
00589 
00605         String(const char* chars, size_type chars_len)
00606         {
00607                 init();
00608                 assign(chars, chars_len);
00609         }
00610 
00611 
00613         // Size operations
00615 
00622         size_type       size(void) const
00623         {
00624                 return d_cplength;
00625         }
00626 
00634         size_type       length(void) const
00635         {
00636                 return d_cplength;
00637         }
00638 
00646         bool    empty(void) const
00647         {
00648                 return  (d_cplength == 0);
00649         }
00650 
00660         static size_type        max_size(void)
00661         {
00662                 return (((size_type)-1) / sizeof(utf32));
00663         }
00664 
00666         // Capacity Operations
00668         // return the number of code points the string could hold without re-allocation
00669         // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
00678         size_type capacity(void) const
00679         {
00680                 return d_reserve - 1;
00681         }
00682 
00683         // reserve internal memory for at-least 'num' code-points (characters).  if num is 0, request is shrink-to-fit.
00698         void    reserve(size_type num = 0)
00699         {
00700                 if (num == 0)
00701                         trim();
00702                 else
00703                         grow(num);
00704         }
00705 
00707         // Comparisons
00709 
00724         int             compare(const String& str) const
00725         {
00726                 return compare(0, d_cplength, str);
00727         }
00728 
00758         int             compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
00759         {
00760                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
00761                         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         // Character access
01061 
01075         reference       operator[](size_type idx)
01076         {
01077                 return (ptr()[idx]);
01078         }
01079 
01094         value_type      operator[](size_type idx) const
01095         {
01096                 return ptr()[idx];
01097         }
01098 
01111         reference       at(size_type idx)
01112         {
01113                 if (d_cplength <= idx)
01114                         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         // C-Strings and arrays
01143 
01156         const char* c_str(void) const
01157         {
01158                 return (const char*)build_utf8_buff();
01159         }
01160 
01174         const utf8* data(void) const
01175         {
01176                 return build_utf8_buff();
01177         }
01178 
01179         // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
01180         // return number of utf8 code units placed into the buffer
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         // UTF8 Encoding length information
01215         // return the number of bytes required to hold 'num' code-points, starting at code-point 'idx', of the the string when encoded as utf8 data.
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         // Assignment Functions
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                 // see if we need to swap 'quick buffer' data
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         // Appending Functions
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         // Insertion Functions
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         // Erasing characters
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         // Resizing
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         // Replacing Characters
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         // Find a code point
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         // Find a substring
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                         // loop while search string could fit in to search area
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                         // loop while search string could fit in to search area
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                         // loop while search string could fit in to search area
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                         // loop while search string could fit in to search area
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         // Find first of different code-points
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         // Find last of different code-points
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         // Substring
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         // Iterator creation
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                 Implementation Functions
04740         *************************************************************************/
04741         // string management
04742 
04743         // change size of allocated buffer so it is at least 'new_size'.
04744         // May or may not cause re-allocation and copy of buffer if size is larger
04745         // will never re-allocate to make size smaller.  (see trim())
04746     bool        grow(size_type new_size);
04747 
04748         // perform re-allocation to remove wasted space.
04749     void        trim(void);
04750 
04751         // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
04752         void    setlen(size_type len)
04753         {
04754                 d_cplength = len;
04755                 ptr()[len] = (utf32)(0);
04756         }
04757 
04758         // return a ptr to the buffer in use.
04759         utf32*  ptr(void)
04760         {
04761                 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
04762         }
04763 
04764         // return a ptr tot he buffer in use (const version)
04765         const utf32*    ptr(void) const
04766         {
04767                 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
04768         }
04769 
04770         // initialise string object
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         // return true if the given pointer is inside the string data
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         // compute distance between two iterators, returning a 'safe' value
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         // encoding functions
04796         // for all:
04797         //      src_len is in code units, or 0 for null terminated string.
04798         //      dest_len is in code units.
04799         //      returns number of code units put into dest buffer.
04800         size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
04801         {
04802                 // count length for null terminated source...
04803                 if (src_len == 0)
04804                 {
04805                         src_len = utf_length(src);
04806                 }
04807 
04808                 size_type destCapacity = dest_len;
04809 
04810                 // while there is data in the source buffer,
04811                 for (uint idx = 0; idx < src_len; ++idx)
04812                 {
04813                         utf32   cp = src[idx];
04814 
04815                         // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
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                 // count length for null terminated source...
04856                 if (src_len == 0)
04857                 {
04858                         src_len = utf_length(src);
04859                 }
04860 
04861                 size_type destCapacity = dest_len;
04862 
04863                 // while there is data in the source buffer, and space in the dest buffer
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         // return the number of utf8 code units required to encode the given utf32 code point
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         // return number of code units required to re-encode given null-terminated utf32 data as utf8.  return does not include terminating null.
04913         size_type encoded_size(const utf32* buf) const
04914         {
04915                 return encoded_size(buf, utf_length(buf));
04916         }
04917 
04918         // return number of code units required to re-encode given utf32 data as utf8.   len is number of code units in 'buf'.
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         // return number of utf32 code units required to re-encode given utf8 data as utf32.  return does not include terminating null.
04932         size_type encoded_size(const utf8* buf) const
04933         {
04934                 return encoded_size(buf, utf_length(buf));
04935         }
04936 
04937         // return number of utf32 code units required to re-encode given utf8 data as utf32.  len is number of code units in 'buf'.
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         // return number of code units in a null terminated string
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         // return number of code units in a null terminated string
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         // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
04993     utf8* build_utf8_buff(void) const;
04994 
04995         // compare two utf32 buffers
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         // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
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         // compare utf32 buffer with encoded utf8 data
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         // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
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         // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none.  len is in code points.
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         // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
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 // Comparison operators
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 // Concatenation operator functions
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 // Output (stream) functions
05550 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
05551 
05552 
05554 // Modifying operations
05556 
05569 void CEGUIEXPORT swap(String& str1, String& str2);
05570 
05571 
05572 } // End of  CEGUI namespace section
05573 
05574 
05575 #endif  // end of guard _CEGUIString_h_

Generated on Sat Nov 26 10:09:55 2005 for Crazy Eddies GUI System by  doxygen 1.4.5