• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List

CEGUIString.h

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

Generated on Fri Nov 19 2010 12:01:20 for Crazy Eddies GUI System by  doxygen 1.7.2