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