• 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         *************************************************************************/
00095 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00096         class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32>
00097 #else
00098         class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32, std::ptrdiff_t, const utf32*, const utf32&>
00099 #endif
00100         {
00101 
00102         public:
00104                 // data
00106                 const utf32*    d_ptr;
00107 
00108 
00110                 // Methods
00112                 const_iterator(void)
00113                 {
00114                         d_ptr = 0;
00115                 }
00116                 const_iterator(const_pointer ptr)
00117                 {
00118                         d_ptr = ptr;
00119                 }
00120 
00121                 const_reference operator*() const
00122                 {
00123                         return *d_ptr;
00124                 }
00125 
00126 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00127 #       pragma warning (push)
00128 #       pragma warning (disable : 4284)
00129 #endif
00130                 const_pointer   operator->() const
00131                 {
00132                         return &**this;
00133                 }
00134 
00135 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00136 #       pragma warning (pop)
00137 #endif
00138 
00139                 const_iterator& operator++()
00140                 {
00141                         ++d_ptr;
00142                         return *this;
00143                 }
00144 
00145                 const_iterator  operator++(int)
00146                 {
00147                         const_iterator temp = *this;
00148                         ++*this;
00149                         return temp;
00150                 }
00151 
00152                 const_iterator& operator--()
00153                 {
00154                         --d_ptr;
00155                         return *this;
00156                 }
00157 
00158                 const_iterator  operator--(int)
00159                 {
00160                         const_iterator temp = *this;
00161                         --*this;
00162                         return temp;
00163                 }
00164 
00165                 const_iterator& operator+=(difference_type offset)
00166                 {
00167                         d_ptr += offset;
00168                         return *this;
00169                 }
00170 
00171                 const_iterator operator+(difference_type offset) const
00172                 {
00173                         const_iterator temp = *this;
00174                         return temp += offset;
00175                 }
00176 
00177                 const_iterator& operator-=(difference_type offset)
00178                 {
00179                         return *this += -offset;
00180                 }
00181 
00182                 const_iterator operator-(difference_type offset) const
00183                 {
00184                         const_iterator temp = *this;
00185                         return temp -= offset;
00186                 }
00187 
00188                 difference_type operator-(const const_iterator& iter) const
00189                 {
00190                         return d_ptr - iter.d_ptr;
00191                 }
00192 
00193                 const_reference operator[](difference_type offset) const
00194                 {
00195                         return *(*this + offset);
00196                 }
00197 
00198                 bool operator==(const const_iterator& iter) const
00199                 {
00200                         return d_ptr == iter.d_ptr;
00201                 }
00202 
00203                 bool operator!=(const const_iterator& iter) const
00204                 {
00205                         return !(*this == iter);
00206                 }
00207 
00208                 bool operator<(const const_iterator& iter) const
00209                 {
00210                         return d_ptr < iter.d_ptr;
00211                 }
00212 
00213                 bool operator>(const const_iterator& iter) const
00214                 {
00215                         return (!(iter < *this));
00216                 }
00217 
00218                 bool operator<=(const const_iterator& iter) const
00219                 {
00220                         return (!(iter < *this));
00221                 }
00222 
00223                 bool operator>=(const const_iterator& iter) const
00224                 {
00225                         return (!(*this < iter));
00226                 }
00227 
00228                 friend const_iterator operator+(difference_type offset, const const_iterator& iter)
00229                 {
00230                         return iter + offset;
00231                 }
00232 
00233         };
00234 
00239         class iterator : public const_iterator
00240         {
00241         public:
00242                 iterator(void) {}
00243                 iterator(pointer ptr) : const_iterator(ptr) {}
00244 
00245 
00246                 reference operator*() const
00247                 {
00248                         return ((reference)**(const_iterator *)this);
00249                 }
00250 
00251 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00252 #       pragma warning (push)
00253 #       pragma warning (disable : 4284)
00254 #endif
00255 
00256                 pointer operator->() const
00257                 {
00258                         return &**this;
00259                 }
00260 
00261 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00262 #       pragma warning (pop)
00263 #endif
00264 
00265                 iterator& operator++()
00266                 {
00267                         ++this->d_ptr;
00268                         return *this;
00269                 }
00270 
00271                 iterator operator++(int)
00272                 {
00273                         iterator temp = *this;
00274                         ++*this;
00275                         return temp;
00276                 }
00277 
00278                 iterator& operator--()
00279                 {
00280                         --this->d_ptr;
00281                         return *this;
00282                 }
00283 
00284                 iterator operator--(int)
00285                 {
00286                         iterator temp = *this;
00287                         --*this;
00288                         return temp;
00289                 }
00290 
00291                 iterator& operator+=(difference_type offset)
00292                 {
00293                         this->d_ptr += offset;
00294                         return *this;
00295                 }
00296 
00297                 iterator operator+(difference_type offset) const
00298                 {
00299                         iterator temp = *this;
00300                         return temp += offset;
00301                 }
00302 
00303                 iterator& operator-=(difference_type offset)
00304                 {
00305                         return *this += -offset;
00306                 }
00307 
00308                 iterator operator-(difference_type offset) const
00309                 {
00310                         iterator temp = *this;
00311                         return temp -= offset;
00312                 }
00313 
00314                 difference_type operator-(const const_iterator& iter) const
00315                 {
00316                         return ((const_iterator)*this - iter);
00317                 }
00318 
00319                 reference operator[](difference_type offset) const
00320                 {
00321                         return *(*this + offset);
00322                 }
00323 
00324                 friend iterator operator+(difference_type offset, const iterator& iter)
00325                 {
00326                         return iter + offset;
00327                 }
00328 
00329         };
00330 
00335 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
00336         typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type>  const_reverse_iterator;
00337 #else
00338         typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
00339 #endif
00340 
00345 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
00346         typedef std::reverse_iterator<iterator, pointer, reference, difference_type>                    reverse_iterator;
00347 #else
00348         typedef std::reverse_iterator<iterator>                 reverse_iterator;
00349 #endif
00350 
00351 public:
00357     struct FastLessCompare
00358     {
00359         bool operator() (const String& a, const String& b) const
00360         {
00361             const size_t la = a.length();
00362             const size_t lb = b.length();
00363             if (la == lb)
00364                 return (memcmp(a.ptr(), b.ptr(), la*sizeof(utf32)) < 0);
00365             return (la < lb);
00366         }
00367     };
00368 
00369 public:
00371         // Default Construction and Destructor
00373 
00377         String(void)
00378         {
00379                 init();
00380         }
00381 
00386         ~String(void);
00387 
00389         // Construction via CEGUI::String
00391 
00401         String(const String& str)
00402         {
00403                 init();
00404                 assign(str);
00405         }
00406 
00407 
00424         String(const String& str, size_type str_idx, size_type str_num = npos)
00425         {
00426                 init();
00427                 assign(str, str_idx, str_num);
00428         }
00429 
00431         // Construction via std::string
00433 
00449         String(const std::string& std_str)
00450         {
00451                 init();
00452                 assign(std_str);
00453         }
00454 
00477         String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
00478         {
00479                 init();
00480                 assign(std_str, str_idx, str_num);
00481         }
00482 
00483 
00485         // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
00487 
00505         String(const utf8* utf8_str)
00506         {
00507                 init();
00508                 assign(utf8_str);
00509         }
00510 
00537         String(const utf8* utf8_str, size_type chars_len)
00538         {
00539                 init();
00540                 assign(utf8_str, chars_len);
00541         }
00542 
00544         // Construction via code-point (using a UTF-32 code unit)
00546 
00561         String(size_type num, utf32 code_point)
00562         {
00563                 init();
00564                 assign(num, code_point);
00565         }
00566 
00568         // Construction via iterator
00570         // Create string with characters in the range [beg, end)
00584         String(const_iterator iter_beg, const_iterator iter_end)
00585         {
00586                 init();
00587                 append(iter_beg, iter_end);
00588         }
00589 
00590 
00592         // Construction via c-string
00594 
00606         String(const char* cstr)
00607         {
00608                 init();
00609                 assign(cstr);
00610         }
00611 
00627         String(const char* chars, size_type chars_len)
00628         {
00629                 init();
00630                 assign(chars, chars_len);
00631         }
00632 
00633 
00635         // Size operations
00637 
00644         size_type       size(void) const
00645         {
00646                 return d_cplength;
00647         }
00648 
00656         size_type       length(void) const
00657         {
00658                 return d_cplength;
00659         }
00660 
00668         bool    empty(void) const
00669         {
00670                 return  (d_cplength == 0);
00671         }
00672 
00682         static size_type        max_size(void)
00683         {
00684                 return (((size_type)-1) / sizeof(utf32));
00685         }
00686 
00688         // Capacity Operations
00690         // return the number of code points the string could hold without re-allocation
00691         // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
00700         size_type capacity(void) const
00701         {
00702                 return d_reserve - 1;
00703         }
00704 
00705         // reserve internal memory for at-least 'num' code-points (characters).  if num is 0, request is shrink-to-fit.
00720         void    reserve(size_type num = 0)
00721         {
00722                 if (num == 0)
00723                         trim();
00724                 else
00725                         grow(num);
00726         }
00727 
00729         // Comparisons
00731 
00746         int             compare(const String& str) const
00747         {
00748                 return compare(0, d_cplength, str);
00749         }
00750 
00780         int             compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
00781         {
00782                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
00783                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
00784 
00785                 if ((len == npos) || (idx + len > d_cplength))
00786                         len = d_cplength - idx;
00787 
00788                 if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
00789                         str_len = str.d_cplength - str_idx;
00790 
00791                 int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
00792 
00793                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
00794         }
00795 
00796 
00816         int             compare(const std::string& std_str) const
00817         {
00818                 return compare(0, d_cplength, std_str);
00819         }
00820 
00821 
00855         int             compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
00856         {
00857                 if (d_cplength < idx)
00858                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
00859 
00860                 if (std_str.size() < str_idx)
00861                         CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
00862 
00863                 if ((len == npos) || (idx + len > d_cplength))
00864                         len = d_cplength - idx;
00865 
00866                 if ((str_len == npos) || (str_idx + str_len > std_str.size()))
00867                         str_len = (size_type)std_str.size() - str_idx;
00868 
00869                 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
00870 
00871                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
00872         }
00873 
00874 
00896         int             compare(const utf8* utf8_str) const
00897         {
00898                 return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
00899         }
00900 
00901 
00931         int             compare(size_type idx, size_type len, const utf8* utf8_str) const
00932         {
00933                 return compare(idx, len, utf8_str, encoded_size(utf8_str));
00934         }
00935 
00969         int             compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
00970         {
00971                 if (d_cplength < idx)
00972                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
00973 
00974                 if (str_cplen == npos)
00975                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
00976 
00977                 if ((len == npos) || (idx + len > d_cplength))
00978                         len = d_cplength - idx;
00979 
00980                 int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
00981 
00982                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
00983         }
00984 
00985 
01001         int             compare(const char* cstr) const
01002         {
01003                 return compare(0, d_cplength, cstr, strlen(cstr));
01004         }
01005 
01006 
01030         int             compare(size_type idx, size_type len, const char* cstr) const
01031         {
01032                 return compare(idx, len, cstr, strlen(cstr));
01033         }
01034 
01035 
01063         int             compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
01064         {
01065                 if (d_cplength < idx)
01066                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
01067 
01068                 if (chars_len == npos)
01069                         CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
01070 
01071                 if ((len == npos) || (idx + len > d_cplength))
01072                         len = d_cplength - idx;
01073 
01074                 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
01075 
01076                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
01077         }
01078 
01079 
01081         // Character access
01083 
01097         reference       operator[](size_type idx)
01098         {
01099                 return (ptr()[idx]);
01100         }
01101 
01116         value_type      operator[](size_type idx) const
01117         {
01118                 return ptr()[idx];
01119         }
01120 
01133         reference       at(size_type idx)
01134         {
01135                 if (d_cplength <= idx)
01136                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
01137 
01138                 return ptr()[idx];
01139         }
01140 
01153         const_reference at(size_type idx) const
01154         {
01155                 if (d_cplength <= idx)
01156                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
01157 
01158                 return ptr()[idx];
01159         }
01160 
01161 
01163         // C-Strings and arrays
01165 
01178         const char* c_str(void) const
01179         {
01180                 return (const char*)build_utf8_buff();
01181         }
01182 
01196         const utf8* data(void) const
01197         {
01198                 return build_utf8_buff();
01199         }
01200 
01205         utf32*  ptr(void)
01206         {
01207                 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
01208         }
01209 
01214         const utf32*    ptr(void) const
01215         {
01216                 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
01217         }
01218 
01219         // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
01220         // return number of utf8 code units placed into the buffer
01241         size_type       copy(utf8* buf, size_type len = npos, size_type idx = 0) const
01242         {
01243                 if (d_cplength < idx)
01244                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
01245 
01246                 if (len == npos)
01247                         len = d_cplength;
01248 
01249                 return encode(&ptr()[idx], buf, npos, len);
01250         }
01251 
01253         // UTF8 Encoding length information
01255         // 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.
01271         size_type       utf8_stream_len(size_type num = npos, size_type idx = 0) const
01272         {
01273                 using namespace std;
01274 
01275                 if (d_cplength < idx)
01276                         CEGUI_THROW(out_of_range("Index was out of range for CEGUI::String object"));
01277 
01278                 size_type       maxlen = d_cplength - idx;
01279 
01280                 return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
01281         }
01282 
01284         // Assignment Functions
01286 
01296         String& operator=(const String& str)
01297         {
01298                 return assign(str);
01299         }
01300 
01319         String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
01320         {
01321                 if (str.d_cplength < str_idx)
01322                         CEGUI_THROW(std::out_of_range("Index was out of range for CEGUI::String object"));
01323 
01324                 if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
01325                         str_num = str.d_cplength - str_idx;
01326 
01327                 grow(str_num);
01328                 setlen(str_num);
01329                 memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
01330 
01331                 return *this;
01332         }
01333 
01350         String& operator=(const std::string& std_str)
01351         {
01352                 return assign(std_str);
01353         }
01354 
01378         String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
01379         {
01380                 if (std_str.size() < str_idx)
01381                         CEGUI_THROW(std::out_of_range("Index was out of range for std::string object"));
01382 
01383                 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
01384                         str_num = (size_type)std_str.size() - str_idx;
01385 
01386                 grow(str_num);
01387                 setlen(str_num);
01388 
01389                 while(str_num--)
01390                 {
01391                         ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
01392                 }
01393 
01394                 return *this;
01395         }
01396 
01415         String& operator=(const utf8* utf8_str)
01416         {
01417                 return assign(utf8_str, utf_length(utf8_str));
01418         }
01419 
01438         String& assign(const utf8* utf8_str)
01439         {
01440                 return assign(utf8_str, utf_length(utf8_str));
01441         }
01442 
01464         String& assign(const utf8* utf8_str, size_type str_num)
01465         {
01466                 if (str_num == npos)
01467                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
01468 
01469                 size_type enc_sze = encoded_size(utf8_str, str_num);
01470 
01471                 grow(enc_sze);
01472                 encode(utf8_str, ptr(), d_reserve, str_num);
01473                 setlen(enc_sze);
01474                 return *this;
01475         }
01476 
01487         String& operator=(utf32 code_point)
01488         {
01489                 return assign(1, code_point);
01490         }
01491 
01507         String& assign(size_type num, utf32 code_point)
01508         {
01509                 if (num == npos)
01510                         CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
01511 
01512                 grow(num);
01513                 setlen(num);
01514                 utf32* p = ptr();
01515 
01516                 while(num--)
01517                         *p++ = code_point;
01518 
01519                 return *this;
01520         }
01521 
01522 
01535         String& operator=(const char* cstr)
01536         {
01537                 return assign(cstr, strlen(cstr));
01538         }
01539 
01540 
01553         String& assign(const char* cstr)
01554         {
01555                 return assign(cstr, strlen(cstr));
01556         }
01557 
01558 
01574         String& assign(const char* chars, size_type chars_len)
01575         {
01576                 grow(chars_len);
01577                 utf32* pt = ptr();
01578 
01579                 for (size_type i = 0; i < chars_len; ++i)
01580                 {
01581                         *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
01582                 }
01583 
01584                 setlen(chars_len);
01585                 return *this;
01586         }
01587 
01588 
01599         void    swap(String& str)
01600         {
01601                 size_type       temp_len        = d_cplength;
01602                 d_cplength = str.d_cplength;
01603                 str.d_cplength = temp_len;
01604 
01605                 size_type       temp_res        = d_reserve;
01606                 d_reserve = str.d_reserve;
01607                 str.d_reserve = temp_res;
01608 
01609                 utf32*          temp_buf        = d_buffer;
01610                 d_buffer = str.d_buffer;
01611                 str.d_buffer = temp_buf;
01612 
01613                 // see if we need to swap 'quick buffer' data
01614                 if (temp_res <= STR_QUICKBUFF_SIZE)
01615                 {
01616                         utf32           temp_qbf[STR_QUICKBUFF_SIZE];
01617 
01618                         memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
01619                         memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
01620                         memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
01621                 }
01622 
01623         }
01624 
01626         // Appending Functions
01628 
01640         String& operator+=(const String& str)
01641         {
01642                 return append(str);
01643         }
01644 
01664         String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
01665         {
01666                 if (str.d_cplength < str_idx)
01667                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
01668 
01669                 if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
01670                         str_num = str.d_cplength - str_idx;
01671 
01672                 grow(d_cplength + str_num);
01673                 memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
01674                 setlen(d_cplength + str_num);
01675                 return *this;
01676         }
01677 
01678 
01695         String& operator+=(const std::string& std_str)
01696         {
01697                 return append(std_str);
01698         }
01699 
01723         String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
01724         {
01725                 if (std_str.size() < str_idx)
01726                         CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
01727 
01728                 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
01729                         str_num = (size_type)std_str.size() - str_idx;
01730 
01731                 size_type newsze = d_cplength + str_num;
01732 
01733                 grow(newsze);
01734                 utf32* pt = &ptr()[newsze-1];
01735 
01736                 while(str_num--)
01737                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
01738 
01739                 setlen(newsze);
01740                 return *this;
01741         }
01742 
01743 
01762         String& operator+=(const utf8* utf8_str)
01763         {
01764                 return append(utf8_str, utf_length(utf8_str));
01765         }
01766 
01785         String& append(const utf8* utf8_str)
01786         {
01787                 return append(utf8_str, utf_length(utf8_str));
01788         }
01789 
01790 
01812         String& append(const utf8* utf8_str, size_type len)
01813         {
01814                 if (len == npos)
01815                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
01816 
01817                 size_type encsz = encoded_size(utf8_str, len);
01818                 size_type newsz = d_cplength + encsz;
01819 
01820                 grow(newsz);
01821                 encode(utf8_str, &ptr()[d_cplength], encsz, len);
01822                 setlen(newsz);
01823 
01824                 return *this;
01825         }
01826 
01827 
01840         String& operator+=(utf32 code_point)
01841         {
01842                 return append(1, code_point);
01843         }
01844 
01860         String& append(size_type num, utf32 code_point)
01861         {
01862                 if (num == npos)
01863                         CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
01864 
01865                 size_type newsz = d_cplength + num;
01866                 grow(newsz);
01867 
01868                 utf32* p = &ptr()[d_cplength];
01869 
01870                 while(num--)
01871                         *p++ = code_point;
01872 
01873                 setlen(newsz);
01874 
01875                 return *this;
01876         }
01877 
01890         void    push_back(utf32 code_point)
01891         {
01892                 append(1, code_point);
01893         }
01894 
01910         String& append(const_iterator iter_beg, const_iterator iter_end)
01911         {
01912                 return replace(end(), end(), iter_beg, iter_end);
01913         }
01914 
01915 
01928         String& operator+=(const char* cstr)
01929         {
01930                 return append(cstr, strlen(cstr));
01931         }
01932 
01933 
01946         String& append(const char* cstr)
01947         {
01948                 return append(cstr, strlen(cstr));
01949         }
01950 
01951 
01967         String& append(const char* chars, size_type chars_len)
01968         {
01969                 if (chars_len == npos)
01970                         CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
01971 
01972                 size_type newsz = d_cplength + chars_len;
01973 
01974                 grow(newsz);
01975 
01976                 utf32* pt = &ptr()[newsz-1];
01977 
01978                 while(chars_len--)
01979                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
01980 
01981                 setlen(newsz);
01982 
01983                 return *this;
01984         }
01985 
01986 
01988         // Insertion Functions
01990 
02006         String& insert(size_type idx, const String& str)
02007         {
02008                 return insert(idx, str, 0, npos);
02009         }
02010 
02033         String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
02034         {
02035                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
02036                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02037 
02038                 if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
02039                         str_num = str.d_cplength - str_idx;
02040 
02041                 size_type newsz = d_cplength + str_num;
02042                 grow(newsz);
02043                 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02044                 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02045                 setlen(newsz);
02046 
02047                 return *this;
02048         }
02049 
02070         String& insert(size_type idx, const std::string& std_str)
02071         {
02072                 return insert(idx, std_str, 0, npos);
02073         }
02074 
02101         String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
02102         {
02103                 if (d_cplength < idx)
02104                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02105 
02106                 if (std_str.size() < str_idx)
02107                         CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
02108 
02109                 if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
02110                         str_num = (size_type)std_str.size() - str_idx;
02111 
02112                 size_type newsz = d_cplength + str_num;
02113                 grow(newsz);
02114 
02115                 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02116 
02117                 utf32* pt = &ptr()[idx + str_num - 1];
02118 
02119                 while(str_num--)
02120                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02121 
02122                 setlen(newsz);
02123 
02124                 return *this;
02125         }
02126 
02149         String& insert(size_type idx, const utf8* utf8_str)
02150         {
02151                 return insert(idx, utf8_str, utf_length(utf8_str));
02152         }
02153 
02179         String& insert(size_type idx, const utf8* utf8_str, size_type len)
02180         {
02181                 if (d_cplength < idx)
02182                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02183 
02184                 if (len == npos)
02185                         CEGUI_THROW(std::length_error("Length of utf8 encoded string can not be 'npos'"));
02186 
02187                 size_type encsz = encoded_size(utf8_str, len);
02188                 size_type newsz = d_cplength + encsz;
02189 
02190                 grow(newsz);
02191                 memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02192                 encode(utf8_str, &ptr()[idx], encsz, len);
02193                 setlen(newsz);
02194 
02195                 return *this;
02196         }
02197 
02217         String& insert(size_type idx, size_type num, utf32 code_point)
02218         {
02219                 if (d_cplength < idx)
02220                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02221 
02222                 if (num == npos)
02223                         CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
02224 
02225                 size_type newsz = d_cplength + num;
02226                 grow(newsz);
02227 
02228                 memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02229 
02230                 utf32* pt = &ptr()[idx + num - 1];
02231 
02232                 while(num--)
02233                         *pt-- = code_point;
02234 
02235                 setlen(newsz);
02236 
02237                 return *this;
02238         }
02239 
02258         void insert(iterator pos, size_type num, utf32 code_point)
02259         {
02260                 insert(safe_iter_dif(pos, begin()), num, code_point);
02261         }
02262 
02278         iterator insert(iterator pos, utf32 code_point)
02279         {
02280                 insert(pos, 1, code_point);
02281                 return pos;
02282         }
02283 
02302         void    insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
02303         {
02304                 replace(iter_pos, iter_pos, iter_beg, iter_end);
02305         }
02306 
02307 
02324         String& insert(size_type idx, const char* cstr)
02325         {
02326                 return insert(idx, cstr, strlen(cstr));
02327         }
02328 
02329 
02349         String& insert(size_type idx, const char* chars, size_type chars_len)
02350         {
02351                 if (d_cplength < idx)
02352                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02353 
02354                 if (chars_len == npos)
02355                         CEGUI_THROW(std::length_error("Length of char array can not be 'npos'"));
02356 
02357                 size_type newsz = d_cplength + chars_len;
02358 
02359                 grow(newsz);
02360                 memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02361 
02362                 utf32* pt = &ptr()[idx + chars_len - 1];
02363 
02364                 while(chars_len--)
02365                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
02366 
02367                 setlen(newsz);
02368 
02369                 return *this;
02370         }
02371 
02372 
02374         // Erasing characters
02376 
02383         void    clear(void)
02384         {
02385                 setlen(0);
02386                 trim();
02387         }
02388 
02396         String& erase(void)
02397         {
02398                 clear();
02399                 return *this;
02400         }
02401 
02414         String& erase(size_type idx)
02415         {
02416                 return erase(idx, 1);
02417         }
02418 
02434         String& erase(size_type idx, size_type len = npos)
02435         {
02436         // cover the no-op case.
02437         if (len == 0)
02438             return *this;
02439 
02440                 if (d_cplength <= idx)
02441                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02442 
02443                 if (len == npos)
02444                         len = d_cplength - idx;
02445 
02446                 size_type newsz = d_cplength - len;
02447 
02448                 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
02449                 setlen(newsz);
02450                 return  *this;
02451         }
02452 
02463         String& erase(iterator pos)
02464         {
02465                 return erase(safe_iter_dif(pos, begin()), 1);
02466         }
02467 
02481         String& erase(iterator iter_beg, iterator iter_end)
02482         {
02483                 return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
02484         }
02485 
02487         // Resizing
02489 
02501         void    resize(size_type num)
02502         {
02503                 resize(num, utf32());
02504         }
02505 
02521         void    resize(size_type num, utf32 code_point)
02522         {
02523                 if (num < d_cplength)
02524                 {
02525                         setlen(num);
02526                 }
02527                 else
02528                 {
02529                         append(num - d_cplength, code_point);
02530                 }
02531 
02532         }
02533 
02535         // Replacing Characters
02537 
02556         String& replace(size_type idx, size_type len, const String& str)
02557         {
02558                 return replace(idx, len, str, 0, npos);
02559         }
02560 
02582         String& replace(iterator iter_beg, iterator iter_end, const String& str)
02583         {
02584                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
02585         }
02586 
02612         String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
02613         {
02614                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
02615                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02616 
02617                 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
02618                         str_num = str.d_cplength - str_idx;
02619 
02620                 if (((len + idx) > d_cplength) || (len == npos))
02621                         len = d_cplength - idx;
02622 
02623                 size_type newsz = d_cplength + str_num - len;
02624 
02625                 grow(newsz);
02626 
02627                 if ((idx + len) < d_cplength)
02628                         memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02629 
02630                 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02631                 setlen(newsz);
02632 
02633                 return *this;
02634         }
02635 
02636 
02660         String& replace(size_type idx, size_type len, const std::string& std_str)
02661         {
02662                 return replace(idx, len, std_str, 0, npos);
02663         }
02664 
02690         String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
02691         {
02692                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
02693         }
02694 
02724         String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
02725         {
02726                 if (d_cplength < idx)
02727                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02728 
02729                 if (std_str.size() < str_idx)
02730                         CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
02731 
02732                 if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
02733                         str_num = (size_type)std_str.size() - str_idx;
02734 
02735                 if (((len + idx) > d_cplength) || (len == npos))
02736                         len = d_cplength - idx;
02737 
02738                 size_type newsz = d_cplength + str_num - len;
02739 
02740                 grow(newsz);
02741 
02742                 if ((idx + len) < d_cplength)
02743                         memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02744 
02745                 utf32* pt = &ptr()[idx + str_num - 1];
02746 
02747                 while (str_num--)
02748                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02749 
02750                 setlen(newsz);
02751 
02752                 return *this;
02753         }
02754 
02755 
02781         String& replace(size_type idx, size_type len, const utf8* utf8_str)
02782         {
02783                 return replace(idx, len, utf8_str, utf_length(utf8_str));
02784         }
02785 
02813         String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
02814         {
02815                 return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
02816         }
02817 
02846         String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
02847         {
02848                 if (d_cplength < idx)
02849                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02850 
02851                 if (str_len == npos)
02852                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
02853 
02854                 if (((len + idx) > d_cplength) || (len == npos))
02855                         len = d_cplength - idx;
02856 
02857                 size_type encsz = encoded_size(utf8_str, str_len);
02858                 size_type newsz = d_cplength + encsz - len;
02859 
02860                 grow(newsz);
02861 
02862                 if ((idx + len) < d_cplength)
02863                         memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02864 
02865                 encode(utf8_str, &ptr()[idx], encsz, str_len);
02866 
02867                 setlen(newsz);
02868                 return *this;
02869         }
02870 
02901         String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
02902         {
02903                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
02904         }
02905 
02928         String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
02929         {
02930                 if (d_cplength < idx)
02931                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
02932 
02933                 if (num == npos)
02934                         CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
02935 
02936                 if (((len + idx) > d_cplength) || (len == npos))
02937                         len = d_cplength - idx;
02938 
02939                 size_type newsz = d_cplength + num - len;
02940 
02941                 grow(newsz);
02942 
02943                 if ((idx + len) < d_cplength)
02944                         memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02945 
02946                 utf32* pt = &ptr()[idx + num - 1];
02947 
02948                 while (num--)
02949                         *pt-- = code_point;
02950 
02951                 setlen(newsz);
02952 
02953                 return *this;
02954         }
02955 
02980         String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
02981         {
02982                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
02983         }
02984 
02985 
03010         String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
03011         {
03012                 if (iter_newBeg == iter_newEnd)
03013                 {
03014                         erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
03015                 }
03016                 else
03017                 {
03018                         size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
03019                         size_type idx = safe_iter_dif(iter_beg, begin());
03020                         size_type len = safe_iter_dif(iter_end, iter_beg);
03021 
03022                         if ((len + idx) > d_cplength)
03023                                 len = d_cplength - idx;
03024 
03025                         size_type newsz = d_cplength + str_len - len;
03026 
03027                         grow(newsz);
03028 
03029                         if ((idx + len) < d_cplength)
03030                                 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
03031 
03032                         memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
03033                         setlen(newsz);
03034                 }
03035 
03036                 return *this;
03037         }
03038 
03039 
03059         String& replace(size_type idx, size_type len, const char* cstr)
03060         {
03061                 return replace(idx, len, cstr, strlen(cstr));
03062         }
03063 
03064 
03086         String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
03087         {
03088                 return replace(iter_beg, iter_end, cstr, strlen(cstr));
03089         }
03090 
03091 
03114         String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
03115         {
03116                 if (d_cplength < idx)
03117                         CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
03118 
03119                 if (chars_len == npos)
03120                         CEGUI_THROW(std::length_error("Length for the char array can not be 'npos'"));
03121 
03122                 if (((len + idx) > d_cplength) || (len == npos))
03123                         len = d_cplength - idx;
03124 
03125                 size_type newsz = d_cplength + chars_len - len;
03126 
03127                 grow(newsz);
03128 
03129                 if ((idx + len) < d_cplength)
03130                         memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
03131 
03132                 utf32* pt = &ptr()[idx + chars_len - 1];
03133 
03134                 while (chars_len--)
03135                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
03136 
03137                 setlen(newsz);
03138                 return *this;
03139         }
03140 
03141 
03166         String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
03167         {
03168                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
03169         }
03170 
03171 
03173         // Find a code point
03175 
03189         size_type       find(utf32 code_point, size_type idx = 0) const
03190         {
03191                 if (idx < d_cplength)
03192                 {
03193                         const utf32* pt = &ptr()[idx];
03194 
03195                         while (idx < d_cplength)
03196                         {
03197                                 if (*pt++ == code_point)
03198                                         return idx;
03199 
03200                                 ++idx;
03201                         }
03202 
03203                 }
03204 
03205                 return npos;
03206         }
03207 
03222         size_type       rfind(utf32 code_point, size_type idx = npos) const
03223         {
03224                 if (idx >= d_cplength)
03225                         idx = d_cplength - 1;
03226 
03227                 if (d_cplength > 0)
03228                 {
03229                         const utf32* pt = &ptr()[idx];
03230 
03231                         do
03232                         {
03233                                 if (*pt-- == code_point)
03234                                         return idx;
03235 
03236                         } while (idx-- != 0);
03237 
03238                 }
03239 
03240                 return npos;
03241         }
03242 
03244         // Find a substring
03246 
03260         size_type       find(const String& str, size_type idx = 0) const
03261         {
03262                 if ((str.d_cplength == 0) && (idx < d_cplength))
03263                         return idx;
03264 
03265                 if (idx < d_cplength)
03266                 {
03267                         // loop while search string could fit in to search area
03268                         while (d_cplength - idx >= str.d_cplength)
03269                         {
03270                                 if (0 == compare(idx, str.d_cplength, str))
03271                                         return idx;
03272 
03273                                 ++idx;
03274                         }
03275 
03276                 }
03277 
03278                 return npos;
03279         }
03280 
03295         size_type       rfind(const String& str, size_type idx = npos) const
03296         {
03297                 if (str.d_cplength == 0)
03298                         return (idx < d_cplength) ? idx : d_cplength;
03299 
03300                 if (str.d_cplength <= d_cplength)
03301                 {
03302                         if (idx > (d_cplength - str.d_cplength))
03303                                 idx = d_cplength - str.d_cplength;
03304 
03305                         do
03306                         {
03307                                 if (0 == compare(idx, str.d_cplength, str))
03308                                         return idx;
03309 
03310                         } while (idx-- != 0);
03311 
03312                 }
03313 
03314                 return npos;
03315         }
03316 
03335         size_type       find(const std::string& std_str, size_type idx = 0) const
03336         {
03337                 std::string::size_type sze = std_str.size();
03338 
03339                 if ((sze == 0) && (idx < d_cplength))
03340                         return idx;
03341 
03342                 if (idx < d_cplength)
03343                 {
03344                         // loop while search string could fit in to search area
03345                         while (d_cplength - idx >= sze)
03346                         {
03347                                 if (0 == compare(idx, (size_type)sze, std_str))
03348                                         return idx;
03349 
03350                                 ++idx;
03351                         }
03352 
03353                 }
03354 
03355                 return npos;
03356         }
03357 
03376         size_type       rfind(const std::string& std_str, size_type idx = npos) const
03377         {
03378                 std::string::size_type sze = std_str.size();
03379 
03380                 if (sze == 0)
03381                         return (idx < d_cplength) ? idx : d_cplength;
03382 
03383                 if (sze <= d_cplength)
03384                 {
03385                         if (idx > (d_cplength - sze))
03386                                 idx = d_cplength - sze;
03387 
03388                         do
03389                         {
03390                                 if (0 == compare(idx, (size_type)sze, std_str))
03391                                         return idx;
03392 
03393                         } while (idx-- != 0);
03394 
03395                 }
03396 
03397                 return npos;
03398         }
03399 
03422         size_type       find(const utf8* utf8_str, size_type idx = 0) const
03423         {
03424                 return find(utf8_str, idx, utf_length(utf8_str));
03425         }
03426 
03449         size_type       rfind(const utf8* utf8_str, size_type idx = npos) const
03450         {
03451                 return rfind(utf8_str, idx, utf_length(utf8_str));
03452         }
03453 
03479         size_type       find(const utf8* utf8_str, size_type idx, size_type str_len) const
03480         {
03481                 if (str_len == npos)
03482                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
03483 
03484                 size_type sze = encoded_size(utf8_str, str_len);
03485 
03486                 if ((sze == 0) && (idx < d_cplength))
03487                         return idx;
03488 
03489                 if (idx < d_cplength)
03490                 {
03491                         // loop while search string could fit in to search area
03492                         while (d_cplength - idx >= sze)
03493                         {
03494                                 if (0 == compare(idx, sze, utf8_str, sze))
03495                                         return idx;
03496 
03497                                 ++idx;
03498                         }
03499 
03500                 }
03501 
03502                 return npos;
03503         }
03504 
03530         size_type       rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
03531         {
03532                 if (str_len == npos)
03533                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
03534 
03535                 size_type sze = encoded_size(utf8_str, str_len);
03536 
03537                 if (sze == 0)
03538                         return (idx < d_cplength) ? idx : d_cplength;
03539 
03540                 if (sze <= d_cplength)
03541                 {
03542                         if (idx > (d_cplength - sze))
03543                                 idx = d_cplength - sze;
03544 
03545                         do
03546                         {
03547                                 if (0 == compare(idx, sze, utf8_str, sze))
03548                                         return idx;
03549 
03550                         } while (idx-- != 0);
03551 
03552                 }
03553 
03554                 return npos;
03555         }
03556 
03557 
03574         size_type       find(const char* cstr, size_type idx = 0) const
03575         {
03576                 return find(cstr, idx, strlen(cstr));
03577         }
03578 
03579 
03596         size_type       rfind(const char* cstr, size_type idx = npos) const
03597         {
03598                 return rfind(cstr, idx, strlen(cstr));
03599         }
03600 
03601 
03621         size_type       find(const char* chars, size_type idx, size_type chars_len) const
03622         {
03623                 if (chars_len == npos)
03624                         CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
03625 
03626                 if ((chars_len == 0) && (idx < d_cplength))
03627                         return idx;
03628 
03629                 if (idx < d_cplength)
03630                 {
03631                         // loop while search string could fit in to search area
03632                         while (d_cplength - idx >= chars_len)
03633                         {
03634                                 if (0 == compare(idx, chars_len, chars, chars_len))
03635                                         return idx;
03636 
03637                                 ++idx;
03638                         }
03639 
03640                 }
03641 
03642                 return npos;
03643         }
03644 
03645 
03665         size_type       rfind(const char* chars, size_type idx, size_type chars_len) const
03666         {
03667                 if (chars_len == npos)
03668                         CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
03669 
03670                 if (chars_len == 0)
03671                         return (idx < d_cplength) ? idx : d_cplength;
03672 
03673                 if (chars_len <= d_cplength)
03674                 {
03675                         if (idx > (d_cplength - chars_len))
03676                                 idx = d_cplength - chars_len;
03677 
03678                         do
03679                         {
03680                                 if (0 == compare(idx, chars_len, chars, chars_len))
03681                                         return idx;
03682 
03683                         } while (idx-- != 0);
03684 
03685                 }
03686 
03687                 return npos;
03688         }
03689 
03690 
03692         // Find first of different code-points
03694 
03708         size_type       find_first_of(const String& str, size_type idx = 0) const
03709         {
03710                 if (idx < d_cplength)
03711                 {
03712                         const utf32* pt = &ptr()[idx];
03713 
03714                         do
03715                         {
03716                                 if (npos != str.find(*pt++))
03717                                         return idx;
03718 
03719                         } while (++idx != d_cplength);
03720 
03721                 }
03722 
03723                 return npos;
03724         }
03725 
03740         size_type       find_first_not_of(const String& str, size_type idx = 0) const
03741         {
03742                 if (idx < d_cplength)
03743                 {
03744                         const utf32* pt = &ptr()[idx];
03745 
03746                         do
03747                         {
03748                                 if (npos == str.find(*pt++))
03749                                         return idx;
03750 
03751                         } while (++idx != d_cplength);
03752 
03753                 }
03754 
03755                 return npos;
03756         }
03757 
03758 
03777         size_type       find_first_of(const std::string& std_str, size_type idx = 0) const
03778         {
03779                 if (idx < d_cplength)
03780                 {
03781                         const utf32* pt = &ptr()[idx];
03782 
03783                         do
03784                         {
03785                                 if (npos != find_codepoint(std_str, *pt++))
03786                                         return idx;
03787 
03788                         } while (++idx != d_cplength);
03789 
03790                 }
03791 
03792                 return npos;
03793         }
03794 
03813         size_type       find_first_not_of(const std::string& std_str, size_type idx = 0) const
03814         {
03815                 if (idx < d_cplength)
03816                 {
03817                         const utf32* pt = &ptr()[idx];
03818 
03819                         do
03820                         {
03821                                 if (npos == find_codepoint(std_str, *pt++))
03822                                         return idx;
03823 
03824                         } while (++idx != d_cplength);
03825 
03826                 }
03827 
03828                 return npos;
03829         }
03830 
03831 
03854         size_type       find_first_of(const utf8* utf8_str, size_type idx = 0) const
03855         {
03856                 return find_first_of(utf8_str, idx, utf_length(utf8_str));
03857         }
03858 
03881         size_type       find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
03882         {
03883                 return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
03884         }
03885 
03911         size_type       find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03912         {
03913                 if (str_len == npos)
03914                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
03915 
03916                 if (idx < d_cplength)
03917                 {
03918                         size_type encsze = encoded_size(utf8_str, str_len);
03919 
03920                         const utf32* pt = &ptr()[idx];
03921 
03922                         do
03923                         {
03924                                 if (npos != find_codepoint(utf8_str, encsze, *pt++))
03925                                         return idx;
03926 
03927                         } while (++idx != d_cplength);
03928 
03929                 }
03930 
03931                 return npos;
03932         }
03933 
03959         size_type       find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03960         {
03961                 if (str_len == npos)
03962                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
03963 
03964                 if (idx < d_cplength)
03965                 {
03966                         size_type encsze = encoded_size(utf8_str, str_len);
03967 
03968                         const utf32* pt = &ptr()[idx];
03969 
03970                         do
03971                         {
03972                                 if (npos == find_codepoint(utf8_str, encsze, *pt++))
03973                                         return idx;
03974 
03975                         } while (++idx != d_cplength);
03976 
03977                 }
03978 
03979                 return npos;
03980         }
03981 
03982 
03997         size_type       find_first_of(utf32 code_point, size_type idx = 0) const
03998         {
03999                 return find(code_point, idx);
04000         }
04001 
04018         size_type       find_first_not_of(utf32 code_point, size_type idx = 0) const
04019         {
04020                 if (idx < d_cplength)
04021                 {
04022                         do
04023                         {
04024                                 if ((*this)[idx] != code_point)
04025                                         return idx;
04026 
04027                         } while(idx++ < d_cplength);
04028 
04029                 }
04030 
04031                 return npos;
04032         }
04033 
04034 
04051         size_type       find_first_of(const char* cstr, size_type idx = 0) const
04052         {
04053                 return find_first_of(cstr, idx, strlen(cstr));
04054         }
04055 
04056 
04073         size_type       find_first_not_of(const char* cstr, size_type idx = 0) const
04074         {
04075                 return find_first_not_of(cstr, idx, strlen(cstr));
04076         }
04077 
04078 
04098         size_type       find_first_of(const char* chars, size_type idx, size_type chars_len) const
04099         {
04100                 if (chars_len == npos)
04101                         CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
04102 
04103                 if (idx < d_cplength)
04104                 {
04105                         const utf32* pt = &ptr()[idx];
04106 
04107                         do
04108                         {
04109                                 if (npos != find_codepoint(chars, chars_len, *pt++))
04110                                         return idx;
04111 
04112                         } while (++idx != d_cplength);
04113 
04114                 }
04115 
04116                 return npos;
04117         }
04118 
04119 
04139         size_type       find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
04140         {
04141                 if (chars_len == npos)
04142                         CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
04143 
04144                 if (idx < d_cplength)
04145                 {
04146                         const utf32* pt = &ptr()[idx];
04147 
04148                         do
04149                         {
04150                                 if (npos == find_codepoint(chars, chars_len, *pt++))
04151                                         return idx;
04152 
04153                         } while (++idx != d_cplength);
04154 
04155                 }
04156 
04157                 return npos;
04158         }
04159 
04160 
04162         // Find last of different code-points
04164 
04178         size_type       find_last_of(const String& str, size_type idx = npos) const
04179         {
04180                 if (d_cplength > 0)
04181                 {
04182                         if (idx >= d_cplength)
04183                                 idx = d_cplength - 1;
04184 
04185                         const utf32* pt = &ptr()[idx];
04186 
04187                         do
04188                         {
04189                                 if (npos != str.find(*pt--))
04190                                         return idx;
04191 
04192                         } while (idx-- != 0);
04193 
04194                 }
04195 
04196                 return npos;
04197         }
04198 
04213         size_type       find_last_not_of(const String& str, size_type idx = npos) const
04214         {
04215                 if (d_cplength > 0)
04216                 {
04217                         if (idx >= d_cplength)
04218                                 idx = d_cplength - 1;
04219 
04220                         const utf32* pt = &ptr()[idx];
04221 
04222                         do
04223                         {
04224                                 if (npos == str.find(*pt--))
04225                                         return idx;
04226 
04227                         } while (idx-- != 0);
04228 
04229                 }
04230 
04231                 return npos;
04232         }
04233 
04234 
04253         size_type       find_last_of(const std::string& std_str, size_type idx = npos) const
04254         {
04255                 if (d_cplength > 0)
04256                 {
04257                         if (idx >= d_cplength)
04258                                 idx = d_cplength - 1;
04259 
04260                         const utf32* pt = &ptr()[idx];
04261 
04262                         do
04263                         {
04264                                 if (npos != find_codepoint(std_str, *pt--))
04265                                         return idx;
04266 
04267                         } while (idx-- != 0);
04268 
04269                 }
04270 
04271                 return npos;
04272         }
04273 
04292         size_type       find_last_not_of(const std::string& std_str, size_type idx = npos) const
04293         {
04294                 if (d_cplength > 0)
04295                 {
04296                         if (idx >= d_cplength)
04297                                 idx = d_cplength - 1;
04298 
04299                         const utf32* pt = &ptr()[idx];
04300 
04301                         do
04302                         {
04303                                 if (npos == find_codepoint(std_str, *pt--))
04304                                         return idx;
04305 
04306                         } while (idx-- != 0);
04307 
04308                 }
04309 
04310                 return npos;
04311         }
04312 
04313 
04336         size_type       find_last_of(const utf8* utf8_str, size_type idx = npos) const
04337         {
04338                 return find_last_of(utf8_str, idx, utf_length(utf8_str));
04339         }
04340 
04363         size_type       find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
04364         {
04365                 return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
04366         }
04367 
04393         size_type       find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04394         {
04395                 if (str_len == npos)
04396                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
04397 
04398                 if (d_cplength > 0)
04399                 {
04400                         if (idx >= d_cplength)
04401                                 idx = d_cplength - 1;
04402 
04403                         size_type encsze = encoded_size(utf8_str, str_len);
04404 
04405                         const utf32* pt = &ptr()[idx];
04406 
04407                         do
04408                         {
04409                                 if (npos != find_codepoint(utf8_str, encsze, *pt--))
04410                                         return idx;
04411 
04412                         } while (idx-- != 0);
04413 
04414                 }
04415 
04416                 return npos;
04417         }
04418 
04444         size_type       find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04445         {
04446                 if (str_len == npos)
04447                         CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
04448 
04449                 if (d_cplength > 0)
04450                 {
04451                         if (idx >= d_cplength)
04452                                 idx = d_cplength - 1;
04453 
04454                         size_type encsze = encoded_size(utf8_str, str_len);
04455 
04456                         const utf32* pt = &ptr()[idx];
04457 
04458                         do
04459                         {
04460                                 if (npos == find_codepoint(utf8_str, encsze, *pt--))
04461                                         return idx;
04462 
04463                         } while (idx-- != 0);
04464 
04465                 }
04466 
04467                 return npos;
04468         }
04469 
04470 
04485         size_type       find_last_of(utf32 code_point, size_type idx = npos) const
04486         {
04487                 return rfind(code_point, idx);
04488         }
04489 
04504         size_type       find_last_not_of(utf32 code_point, size_type idx = npos) const
04505         {
04506                 if (d_cplength > 0)
04507                 {
04508                         if (idx >= d_cplength)
04509                                 idx = d_cplength - 1;
04510 
04511                         do
04512                         {
04513                                 if ((*this)[idx] != code_point)
04514                                         return idx;
04515 
04516                         } while(idx-- != 0);
04517 
04518                 }
04519 
04520                 return npos;
04521         }
04522 
04523 
04540         size_type       find_last_of(const char* cstr, size_type idx = npos) const
04541         {
04542                 return find_last_of(cstr, idx, strlen(cstr));
04543         }
04544 
04545 
04562         size_type       find_last_not_of(const char* cstr, size_type idx = npos) const
04563         {
04564                 return find_last_not_of(cstr, idx, strlen(cstr));
04565         }
04566 
04567 
04587         size_type       find_last_of(const char* chars, size_type idx, size_type chars_len) const
04588         {
04589                 if (chars_len == npos)
04590                         CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
04591 
04592                 if (d_cplength > 0)
04593                 {
04594                         if (idx >= d_cplength)
04595                                 idx = d_cplength - 1;
04596 
04597                         const utf32* pt = &ptr()[idx];
04598 
04599                         do
04600                         {
04601                                 if (npos != find_codepoint(chars, chars_len, *pt--))
04602                                         return idx;
04603 
04604                         } while (idx-- != 0);
04605 
04606                 }
04607 
04608                 return npos;
04609         }
04610 
04611 
04631         size_type       find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
04632         {
04633                 if (chars_len == npos)
04634                         CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
04635 
04636                 if (d_cplength > 0)
04637                 {
04638                         if (idx >= d_cplength)
04639                                 idx = d_cplength - 1;
04640 
04641                         const utf32* pt = &ptr()[idx];
04642 
04643                         do
04644                         {
04645                                 if (npos == find_codepoint(chars, chars_len, *pt--))
04646                                         return idx;
04647 
04648                         } while (idx-- != 0);
04649 
04650                 }
04651 
04652                 return npos;
04653         }
04654 
04655 
04657         // Substring
04659 
04674         String  substr(size_type idx = 0, size_type len = npos) const
04675         {
04676                 if (d_cplength < idx)
04677                         CEGUI_THROW(std::out_of_range("Index is out of range for this CEGUI::String"));
04678 
04679                 return String(*this, idx, len);
04680         }
04681 
04683         // Iterator creation
04685 
04692         iterator                begin(void)
04693         {
04694                 return iterator(ptr());
04695         }
04696 
04704         const_iterator  begin(void) const
04705         {
04706                 return const_iterator(ptr());
04707         }
04708 
04716         iterator                end(void)
04717         {
04718                 return iterator(&ptr()[d_cplength]);
04719         }
04720 
04728         const_iterator  end(void) const
04729         {
04730                 return const_iterator(&ptr()[d_cplength]);
04731         }
04732 
04740         reverse_iterator                rbegin(void)
04741         {
04742                 return reverse_iterator(end());
04743         }
04744 
04752         const_reverse_iterator  rbegin(void) const
04753         {
04754                 return const_reverse_iterator(end());
04755         }
04756 
04764         reverse_iterator                rend(void)
04765         {
04766                 return reverse_iterator(begin());
04767         }
04768 
04776         const_reverse_iterator  rend(void) const
04777         {
04778                 return const_reverse_iterator(begin());
04779         }
04780 
04781 private:
04782         /*************************************************************************
04783                 Implementation Functions
04784         *************************************************************************/
04785         // string management
04786 
04787         // change size of allocated buffer so it is at least 'new_size'.
04788         // May or may not cause re-allocation and copy of buffer if size is larger
04789         // will never re-allocate to make size smaller.  (see trim())
04790     bool        grow(size_type new_size);
04791 
04792         // perform re-allocation to remove wasted space.
04793     void        trim(void);
04794 
04795         // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
04796         void    setlen(size_type len)
04797         {
04798                 d_cplength = len;
04799                 ptr()[len] = (utf32)(0);
04800         }
04801 
04802         // initialise string object
04803         void    init(void)
04804         {
04805                 d_reserve                       = STR_QUICKBUFF_SIZE;
04806                 d_encodedbuff           = 0;
04807                 d_encodedbufflen        = 0;
04808                 d_encodeddatlen         = 0;
04809         d_buffer            = 0;
04810                 setlen(0);
04811         }
04812 
04813         // return true if the given pointer is inside the string data
04814         bool    inside(utf32* inptr)
04815         {
04816                 if (inptr < ptr() || ptr() + d_cplength <= inptr)
04817                         return false;
04818                 else
04819                         return true;
04820         }
04821 
04822         // compute distance between two iterators, returning a 'safe' value
04823         size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
04824         {
04825                 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
04826         }
04827 
04828         // encoding functions
04829         // for all:
04830         //      src_len is in code units, or 0 for null terminated string.
04831         //      dest_len is in code units.
04832         //      returns number of code units put into dest buffer.
04833         size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
04834         {
04835                 // count length for null terminated source...
04836                 if (src_len == 0)
04837                 {
04838                         src_len = utf_length(src);
04839                 }
04840 
04841                 size_type destCapacity = dest_len;
04842 
04843                 // while there is data in the source buffer,
04844                 for (uint idx = 0; idx < src_len; ++idx)
04845                 {
04846                         utf32   cp = src[idx];
04847 
04848                         // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
04849                         if (destCapacity < encoded_size(cp))
04850                         {
04851                                 break;
04852                         }
04853 
04854                         if (cp < 0x80)
04855                         {
04856                                 *dest++ = (utf8)cp;
04857                                 --destCapacity;
04858                         }
04859                         else if (cp < 0x0800)
04860                         {
04861                                 *dest++ = (utf8)((cp >> 6) | 0xC0);
04862                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04863                                 destCapacity -= 2;
04864                         }
04865                         else if (cp < 0x10000)
04866                         {
04867                                 *dest++ = (utf8)((cp >> 12) | 0xE0);
04868                                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04869                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04870                                 destCapacity -= 3;
04871                         }
04872                         else
04873                         {
04874                                 *dest++ = (utf8)((cp >> 18) | 0xF0);
04875                                 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
04876                                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04877                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04878                                 destCapacity -= 4;
04879                         }
04880 
04881                 }
04882 
04883                 return dest_len - destCapacity;
04884         }
04885 
04886         size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
04887         {
04888                 // count length for null terminated source...
04889                 if (src_len == 0)
04890                 {
04891                         src_len = utf_length(src);
04892                 }
04893 
04894                 size_type destCapacity = dest_len;
04895 
04896                 // while there is data in the source buffer, and space in the dest buffer
04897                 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
04898                 {
04899                         utf32   cp;
04900                         utf8    cu = src[idx++];
04901 
04902                         if (cu < 0x80)
04903                         {
04904                                 cp = (utf32)(cu);
04905                         }
04906                         else if (cu < 0xE0)
04907                         {
04908                                 cp = ((cu & 0x1F) << 6);
04909                                 cp |= (src[idx++] & 0x3F);
04910                         }
04911                         else if (cu < 0xF0)
04912                         {
04913                                 cp = ((cu & 0x0F) << 12);
04914                                 cp |= ((src[idx++] & 0x3F) << 6);
04915                                 cp |= (src[idx++] & 0x3F);
04916                         }
04917                         else
04918                         {
04919                                 cp = ((cu & 0x07) << 18);
04920                                 cp |= ((src[idx++] & 0x3F) << 12);
04921                                 cp |= ((src[idx++] & 0x3F) << 6);
04922                                 cp |= (src[idx++] & 0x3F);
04923                         }
04924 
04925                         *dest++ = cp;
04926                         --destCapacity;
04927                 }
04928 
04929                 return dest_len - destCapacity;
04930         }
04931 
04932         // return the number of utf8 code units required to encode the given utf32 code point
04933         size_type encoded_size(utf32 code_point) const
04934         {
04935                 if (code_point < 0x80)
04936                         return 1;
04937                 else if (code_point < 0x0800)
04938                         return 2;
04939                 else if (code_point < 0x10000)
04940                         return 3;
04941                 else
04942                         return 4;
04943         }
04944 
04945         // return number of code units required to re-encode given null-terminated utf32 data as utf8.  return does not include terminating null.
04946         size_type encoded_size(const utf32* buf) const
04947         {
04948                 return encoded_size(buf, utf_length(buf));
04949         }
04950 
04951         // return number of code units required to re-encode given utf32 data as utf8.   len is number of code units in 'buf'.
04952         size_type encoded_size(const utf32* buf, size_type len) const
04953         {
04954                 size_type count = 0;
04955 
04956                 while (len--)
04957                 {
04958                         count += encoded_size(*buf++);
04959                 }
04960 
04961                 return count;
04962         }
04963 
04964         // return number of utf32 code units required to re-encode given utf8 data as utf32.  return does not include terminating null.
04965         size_type encoded_size(const utf8* buf) const
04966         {
04967                 return encoded_size(buf, utf_length(buf));
04968         }
04969 
04970         // return number of utf32 code units required to re-encode given utf8 data as utf32.  len is number of code units in 'buf'.
04971         size_type encoded_size(const utf8* buf, size_type len) const
04972         {
04973                 utf8 tcp;
04974                 size_type count = 0;
04975 
04976                 while (len--)
04977                 {
04978                         tcp = *buf++;
04979                         ++count;
04980                         size_type size = 0;
04981 
04982                         if (tcp < 0x80)
04983                         {
04984                         }
04985                         else if (tcp < 0xE0)
04986                         {
04987                                 size = 1;
04988                                 ++buf;
04989                         }
04990                         else if (tcp < 0xF0)
04991                         {
04992                                 size = 2;
04993                                 buf += 2;
04994                         }
04995                         else
04996                         {
04997                                 size = 3;
04998                                 buf += 3;
04999                         }
05000 
05001                         if (len >= size)
05002                                 len -= size;
05003                         else 
05004                                 break;
05005                 }
05006 
05007                 return count;
05008         }
05009 
05010         // return number of code units in a null terminated string
05011         size_type utf_length(const utf8* utf8_str) const
05012         {
05013                 size_type cnt = 0;
05014                 while (*utf8_str++)
05015                         cnt++;
05016 
05017                 return cnt;
05018         }
05019 
05020         // return number of code units in a null terminated string
05021         size_type utf_length(const utf32* utf32_str) const
05022         {
05023                 size_type cnt = 0;
05024                 while (*utf32_str++)
05025                         cnt++;
05026 
05027                 return cnt;
05028         }
05029 
05030         // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
05031     utf8* build_utf8_buff(void) const;
05032 
05033         // compare two utf32 buffers
05034         int     utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
05035         {
05036                 if (!cp_count)
05037                         return 0;
05038 
05039                 while ((--cp_count) && (*buf1 == *buf2))
05040                         buf1++, buf2++;
05041 
05042                 return *buf1 - *buf2;
05043         }
05044 
05045         // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
05046         int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
05047         {
05048                 if (!cp_count)
05049                         return 0;
05050 
05051                 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
05052                         buf1++, buf2++;
05053 
05054                 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
05055         }
05056 
05057         // compare utf32 buffer with encoded utf8 data
05058         int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
05059         {
05060                 if (!cp_count)
05061                         return 0;
05062 
05063                 utf32   cp;
05064                 utf8    cu;
05065 
05066                 do
05067                 {
05068                         cu = *buf2++;
05069 
05070                         if (cu < 0x80)
05071                         {
05072                                 cp = (utf32)(cu);
05073                         }
05074                         else if (cu < 0xE0)
05075                         {
05076                                 cp = ((cu & 0x1F) << 6);
05077                                 cp |= (*buf2++ & 0x3F);
05078                         }
05079                         else if (cu < 0xF0)
05080                         {
05081                                 cp = ((cu & 0x0F) << 12);
05082                                 cp |= ((*buf2++ & 0x3F) << 6);
05083                                 cp |= (*buf2++ & 0x3F);
05084                         }
05085                         else
05086                         {
05087                                 cp = ((cu & 0x07) << 18);
05088                                 cp |= ((*buf2++ & 0x3F) << 12);
05089                                 cp |= ((*buf2++ & 0x3F) << 6);
05090                                 cp |= (*buf2++ & 0x3F);
05091                         }
05092 
05093                 } while ((*buf1++ == cp) && (--cp_count));
05094 
05095                 return (*--buf1) - cp;
05096         }
05097 
05098         // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
05099         size_type find_codepoint(const std::string& str, utf32 code_point) const
05100         {
05101                 size_type idx = 0, sze = (size_type)str.size();
05102 
05103                 while (idx != sze)
05104                 {
05105                         if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
05106                                 return idx;
05107 
05108                         ++idx;
05109                 }
05110 
05111                 return npos;
05112         }
05113 
05114         // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none.  len is in code points.
05115         size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
05116         {
05117                 size_type idx = 0;
05118 
05119                 utf32   cp;
05120                 utf8    cu;
05121 
05122                 while (idx != len) {
05123                         cu = *str++;
05124 
05125                         if (cu < 0x80)
05126                         {
05127                                 cp = (utf32)(cu);
05128                         }
05129                         else if (cu < 0xE0)
05130                         {
05131                                 cp = ((cu & 0x1F) << 6);
05132                                 cp |= (*str++ & 0x3F);
05133                         }
05134                         else if (cu < 0xF0)
05135                         {
05136                                 cp = ((cu & 0x0F) << 12);
05137                                 cp |= ((*str++ & 0x3F) << 6);
05138                                 cp |= (*str++ & 0x3F);
05139                         }
05140                         else
05141                         {
05142                                 cp = ((cu & 0x07) << 18);
05143                                 cp |= ((*str++ & 0x3F) << 12);
05144                                 cp |= ((*str++ & 0x3F) << 6);
05145                                 cp |= (*str++ & 0x3F);
05146                         }
05147 
05148                         if (code_point == cp)
05149                                 return idx;
05150 
05151                         ++idx;
05152                 }
05153 
05154                 return npos;
05155         }
05156 
05157 
05158         // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
05159         size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
05160         {
05161                 for (size_type idx = 0; idx != chars_len; ++idx)
05162                 {
05163                         if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
05164                                 return idx;
05165                 }
05166 
05167                 return npos;
05168         }
05169 
05170 };
05171 
05172 
05174 // Comparison operators
05176 
05180 bool CEGUIEXPORT        operator==(const String& str1, const String& str2);
05181 
05186 bool CEGUIEXPORT        operator==(const String& str, const std::string& std_str);
05187 
05192 bool CEGUIEXPORT        operator==(const std::string& std_str, const String& str);
05193 
05198 bool CEGUIEXPORT        operator==(const String& str, const utf8* utf8_str);
05199 
05204 bool CEGUIEXPORT        operator==(const utf8* utf8_str, const String& str);
05205 
05210 bool CEGUIEXPORT        operator!=(const String& str1, const String& str2);
05211 
05216 bool CEGUIEXPORT        operator!=(const String& str, const std::string& std_str);
05217 
05222 bool CEGUIEXPORT        operator!=(const std::string& std_str, const String& str);
05223 
05228 bool CEGUIEXPORT        operator!=(const String& str, const utf8* utf8_str);
05229 
05234 bool CEGUIEXPORT        operator!=(const utf8* utf8_str, const String& str);
05235 
05240 bool CEGUIEXPORT        operator<(const String& str1, const String& str2);
05241 
05246 bool CEGUIEXPORT        operator<(const String& str, const std::string& std_str);
05247 
05252 bool CEGUIEXPORT        operator<(const std::string& std_str, const String& str);
05253 
05258 bool CEGUIEXPORT        operator<(const String& str, const utf8* utf8_str);
05259 
05264 bool CEGUIEXPORT        operator<(const utf8* utf8_str, const String& str);
05265 
05270 bool CEGUIEXPORT        operator>(const String& str1, const String& str2);
05271 
05276 bool CEGUIEXPORT        operator>(const String& str, const std::string& std_str);
05277 
05282 bool CEGUIEXPORT        operator>(const std::string& std_str, const String& str);
05283 
05288 bool CEGUIEXPORT        operator>(const String& str, const utf8* utf8_str);
05289 
05294 bool CEGUIEXPORT        operator>(const utf8* utf8_str, const String& str);
05295 
05300 bool CEGUIEXPORT        operator<=(const String& str1, const String& str2);
05301 
05306 bool CEGUIEXPORT        operator<=(const String& str, const std::string& std_str);
05307 
05312 bool CEGUIEXPORT        operator<=(const std::string& std_str, const String& str);
05313 
05318 bool CEGUIEXPORT        operator<=(const String& str, const utf8* utf8_str);
05319 
05324 bool CEGUIEXPORT        operator<=(const utf8* utf8_str, const String& str);
05325 
05330 bool CEGUIEXPORT        operator>=(const String& str1, const String& str2);
05331 
05336 bool CEGUIEXPORT        operator>=(const String& str, const std::string& std_str);
05337 
05342 bool CEGUIEXPORT        operator>=(const std::string& std_str, const String& str);
05343 
05348 bool CEGUIEXPORT        operator>=(const String& str, const utf8* utf8_str);
05349 
05354 bool CEGUIEXPORT        operator>=(const utf8* utf8_str, const String& str);
05355 
05360 bool CEGUIEXPORT        operator==(const String& str, const char* c_str);
05361 
05366 bool CEGUIEXPORT        operator==(const char* c_str, const String& str);
05367 
05372 bool CEGUIEXPORT        operator!=(const String& str, const char* c_str);
05373 
05378 bool CEGUIEXPORT        operator!=(const char* c_str, const String& str);
05379 
05384 bool CEGUIEXPORT        operator<(const String& str, const char* c_str);
05385 
05390 bool CEGUIEXPORT        operator<(const char* c_str, const String& str);
05391 
05396 bool CEGUIEXPORT        operator>(const String& str, const char* c_str);
05397 
05402 bool CEGUIEXPORT        operator>(const char* c_str, const String& str);
05403 
05408 bool CEGUIEXPORT        operator<=(const String& str, const char* c_str);
05409 
05414 bool CEGUIEXPORT        operator<=(const char* c_str, const String& str);
05415 
05420 bool CEGUIEXPORT        operator>=(const String& str, const char* c_str);
05421 
05426 bool CEGUIEXPORT        operator>=(const char* c_str, const String& str);
05427 
05429 // Concatenation operator functions
05431 
05446 String CEGUIEXPORT      operator+(const String& str1, const String& str2);
05447 
05463 String CEGUIEXPORT      operator+(const String& str, const std::string& std_str);
05464 
05480 String CEGUIEXPORT      operator+(const std::string& std_str, const String& str);
05481 
05497 String CEGUIEXPORT      operator+(const String& str, const utf8* utf8_str);
05498 
05514 String CEGUIEXPORT      operator+(const utf8* utf8_str, const String& str);
05515 
05531 String CEGUIEXPORT      operator+(const String& str, utf32 code_point);
05532 
05548 String CEGUIEXPORT      operator+(utf32 code_point, const String& str);
05549 
05565 String CEGUIEXPORT      operator+(const String& str, const char* c_str);
05566 
05582 String CEGUIEXPORT      operator+(const char* c_str, const String& str);
05583 
05584 
05586 // Output (stream) functions
05588 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
05589 
05590 
05592 // Modifying operations
05594 
05607 void CEGUIEXPORT swap(String& str1, String& str2);
05608 
05609 
05610 } // End of  CEGUI namespace section
05611 
05612 
05613 #endif  // end of guard _CEGUIString_h_

Generated on Sat Sep 25 2010 02:10:34 for Crazy Eddies GUI System by  doxygen 1.7.1