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