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                         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                         throw std::out_of_range("Index is out of range for CEGUI::String");
00859 
00860                 if (std_str.size() < str_idx)
00861                         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                         throw std::out_of_range("Index is out of range for CEGUI::String");
00973 
00974                 if (str_cplen == npos)
00975                         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                         throw std::out_of_range("Index is out of range for CEGUI::String");
01067 
01068                 if (chars_len == npos)
01069                         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                         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                         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                         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                         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                         throw std::out_of_range("Index was out of range for CEGUI::String object");
01323 
01324                 if (str_num == npos)
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                         throw std::out_of_range("Index was out of range for std::string object");
01382 
01383                 if (str_num == npos)
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                         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                         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                         throw std::out_of_range("Index is out of range for CEGUI::String");
01668 
01669                 if (str_num == npos)
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                         throw std::out_of_range("Index is out of range for std::string");
01727 
01728                 if (str_num == npos)
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                         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                         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                         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                         throw std::out_of_range("Index is out of range for CEGUI::String");
02037 
02038                 if (str_num == npos)
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                         throw std::out_of_range("Index is out of range for CEGUI::String");
02105 
02106                 if (std_str.size() < str_idx)
02107                         throw std::out_of_range("Index is out of range for std::string");
02108 
02109                 if (str_num == npos)
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                         throw std::out_of_range("Index is out of range for CEGUI::String");
02183 
02184                 if (len == npos)
02185                         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                         throw std::out_of_range("Index is out of range for CEGUI::String");
02221 
02222                 if (num == npos)
02223                         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                         throw std::out_of_range("Index is out of range for CEGUI::String");
02353 
02354                 if (chars_len == npos)
02355                         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                 if (d_cplength < idx)
02437                         throw std::out_of_range("Index is out of range foe CEGUI::String");
02438 
02439                 if (len == npos)
02440                         len = d_cplength - idx;
02441 
02442                 size_type newsz = d_cplength - len;
02443 
02444                 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
02445                 setlen(newsz);
02446                 return  *this;
02447         }
02448 
02459         String& erase(iterator pos)
02460         {
02461                 return erase(safe_iter_dif(pos, begin()), 1);
02462         }
02463 
02477         String& erase(iterator iter_beg, iterator iter_end)
02478         {
02479                 return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
02480         }
02481 
02483         // Resizing
02485 
02497         void    resize(size_type num)
02498         {
02499                 resize(num, utf32());
02500         }
02501 
02517         void    resize(size_type num, utf32 code_point)
02518         {
02519                 if (num < d_cplength)
02520                 {
02521                         setlen(num);
02522                 }
02523                 else
02524                 {
02525                         append(num - d_cplength, code_point);
02526                 }
02527 
02528         }
02529 
02531         // Replacing Characters
02533 
02552         String& replace(size_type idx, size_type len, const String& str)
02553         {
02554                 return replace(idx, len, str, 0, npos);
02555         }
02556 
02578         String& replace(iterator iter_beg, iterator iter_end, const String& str)
02579         {
02580                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
02581         }
02582 
02608         String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
02609         {
02610                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
02611                         throw std::out_of_range("Index is out of range for CEGUI::String");
02612 
02613                 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
02614                         str_num = str.d_cplength - str_idx;
02615 
02616                 if (((len + idx) > d_cplength) || (len == npos))
02617                         len = d_cplength - idx;
02618 
02619                 size_type newsz = d_cplength + str_num - len;
02620 
02621                 grow(newsz);
02622 
02623                 if ((idx + len) < d_cplength)
02624                         memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02625 
02626                 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02627                 setlen(newsz);
02628 
02629                 return *this;
02630         }
02631 
02632 
02656         String& replace(size_type idx, size_type len, const std::string& std_str)
02657         {
02658                 return replace(idx, len, std_str, 0, npos);
02659         }
02660 
02686         String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
02687         {
02688                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
02689         }
02690 
02720         String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
02721         {
02722                 if (d_cplength < idx)
02723                         throw std::out_of_range("Index is out of range for CEGUI::String");
02724 
02725                 if (std_str.size() < str_idx)
02726                         throw std::out_of_range("Index is out of range for std::string");
02727 
02728                 if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
02729                         str_num = (size_type)std_str.size() - str_idx;
02730 
02731                 if (((len + idx) > d_cplength) || (len == npos))
02732                         len = d_cplength - idx;
02733 
02734                 size_type newsz = d_cplength + str_num - len;
02735 
02736                 grow(newsz);
02737 
02738                 if ((idx + len) < d_cplength)
02739                         memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02740 
02741                 utf32* pt = &ptr()[idx + str_num - 1];
02742 
02743                 while (str_num--)
02744                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02745 
02746                 setlen(newsz);
02747 
02748                 return *this;
02749         }
02750 
02751 
02777         String& replace(size_type idx, size_type len, const utf8* utf8_str)
02778         {
02779                 return replace(idx, len, utf8_str, utf_length(utf8_str));
02780         }
02781 
02809         String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
02810         {
02811                 return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
02812         }
02813 
02842         String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
02843         {
02844                 if (d_cplength < idx)
02845                         throw std::out_of_range("Index is out of range for CEGUI::String");
02846 
02847                 if (str_len == npos)
02848                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
02849 
02850                 if (((len + idx) > d_cplength) || (len == npos))
02851                         len = d_cplength - idx;
02852 
02853                 size_type encsz = encoded_size(utf8_str, str_len);
02854                 size_type newsz = d_cplength + encsz - len;
02855 
02856                 grow(newsz);
02857 
02858                 if ((idx + len) < d_cplength)
02859                         memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02860 
02861                 encode(utf8_str, &ptr()[idx], encsz, str_len);
02862 
02863                 setlen(newsz);
02864                 return *this;
02865         }
02866 
02897         String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
02898         {
02899                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
02900         }
02901 
02924         String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
02925         {
02926                 if (d_cplength < idx)
02927                         throw std::out_of_range("Index is out of range for CEGUI::String");
02928 
02929                 if (num == npos)
02930                         throw std::length_error("Code point count can not be 'npos'");
02931 
02932                 if (((len + idx) > d_cplength) || (len == npos))
02933                         len = d_cplength - idx;
02934 
02935                 size_type newsz = d_cplength + num - len;
02936 
02937                 grow(newsz);
02938 
02939                 if ((idx + len) < d_cplength)
02940                         memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02941 
02942                 utf32* pt = &ptr()[idx + num - 1];
02943 
02944                 while (num--)
02945                         *pt-- = code_point;
02946 
02947                 setlen(newsz);
02948 
02949                 return *this;
02950         }
02951 
02976         String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
02977         {
02978                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
02979         }
02980 
02981 
03006         String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
03007         {
03008                 if (iter_beg == iter_end)
03009                 {
03010                         erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
03011                 }
03012                 else
03013                 {
03014                         size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
03015                         size_type idx = safe_iter_dif(iter_beg, begin());
03016                         size_type len = safe_iter_dif(iter_end, iter_beg);
03017 
03018                         if ((len + idx) > d_cplength)
03019                                 len = d_cplength - idx;
03020 
03021                         size_type newsz = d_cplength + str_len - len;
03022 
03023                         grow(newsz);
03024 
03025                         if ((idx + len) < d_cplength)
03026                                 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
03027 
03028                         memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
03029                         setlen(newsz);
03030                 }
03031 
03032                 return *this;
03033         }
03034 
03035 
03055         String& replace(size_type idx, size_type len, const char* cstr)
03056         {
03057                 return replace(idx, len, cstr, strlen(cstr));
03058         }
03059 
03060 
03082         String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
03083         {
03084                 return replace(iter_beg, iter_end, cstr, strlen(cstr));
03085         }
03086 
03087 
03110         String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
03111         {
03112                 if (d_cplength < idx)
03113                         throw std::out_of_range("Index is out of range for CEGUI::String");
03114 
03115                 if (chars_len == npos)
03116                         throw std::length_error("Length for the char array can not be 'npos'");
03117 
03118                 if (((len + idx) > d_cplength) || (len == npos))
03119                         len = d_cplength - idx;
03120 
03121                 size_type newsz = d_cplength + chars_len - len;
03122 
03123                 grow(newsz);
03124 
03125                 if ((idx + len) < d_cplength)
03126                         memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
03127 
03128                 utf32* pt = &ptr()[idx + chars_len - 1];
03129 
03130                 while (chars_len--)
03131                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
03132 
03133                 setlen(newsz);
03134                 return *this;
03135         }
03136 
03137 
03162         String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
03163         {
03164                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
03165         }
03166 
03167 
03169         // Find a code point
03171 
03185         size_type       find(utf32 code_point, size_type idx = 0) const
03186         {
03187                 if (idx < d_cplength)
03188                 {
03189                         const utf32* pt = &ptr()[idx];
03190 
03191                         while (idx < d_cplength)
03192                         {
03193                                 if (*pt++ == code_point)
03194                                         return idx;
03195 
03196                                 ++idx;
03197                         }
03198 
03199                 }
03200 
03201                 return npos;
03202         }
03203 
03218         size_type       rfind(utf32 code_point, size_type idx = npos) const
03219         {
03220                 if (idx >= d_cplength)
03221                         idx = d_cplength - 1;
03222 
03223                 if (d_cplength > 0)
03224                 {
03225                         const utf32* pt = &ptr()[idx];
03226 
03227                         do
03228                         {
03229                                 if (*pt-- == code_point)
03230                                         return idx;
03231 
03232                         } while (idx-- != 0);
03233 
03234                 }
03235 
03236                 return npos;
03237         }
03238 
03240         // Find a substring
03242 
03256         size_type       find(const String& str, size_type idx = 0) const
03257         {
03258                 if ((str.d_cplength == 0) && (idx < d_cplength))
03259                         return idx;
03260 
03261                 if (idx < d_cplength)
03262                 {
03263                         // loop while search string could fit in to search area
03264                         while (d_cplength - idx >= str.d_cplength)
03265                         {
03266                                 if (0 == compare(idx, str.d_cplength, str))
03267                                         return idx;
03268 
03269                                 ++idx;
03270                         }
03271 
03272                 }
03273 
03274                 return npos;
03275         }
03276 
03291         size_type       rfind(const String& str, size_type idx = npos) const
03292         {
03293                 if (str.d_cplength == 0)
03294                         return (idx < d_cplength) ? idx : d_cplength;
03295 
03296                 if (str.d_cplength <= d_cplength)
03297                 {
03298                         if (idx > (d_cplength - str.d_cplength))
03299                                 idx = d_cplength - str.d_cplength;
03300 
03301                         do
03302                         {
03303                                 if (0 == compare(idx, str.d_cplength, str))
03304                                         return idx;
03305 
03306                         } while (idx-- != 0);
03307 
03308                 }
03309 
03310                 return npos;
03311         }
03312 
03331         size_type       find(const std::string& std_str, size_type idx = 0) const
03332         {
03333                 std::string::size_type sze = std_str.size();
03334 
03335                 if ((sze == 0) && (idx < d_cplength))
03336                         return idx;
03337 
03338                 if (idx < d_cplength)
03339                 {
03340                         // loop while search string could fit in to search area
03341                         while (d_cplength - idx >= sze)
03342                         {
03343                                 if (0 == compare(idx, (size_type)sze, std_str))
03344                                         return idx;
03345 
03346                                 ++idx;
03347                         }
03348 
03349                 }
03350 
03351                 return npos;
03352         }
03353 
03372         size_type       rfind(const std::string& std_str, size_type idx = npos) const
03373         {
03374                 std::string::size_type sze = std_str.size();
03375 
03376                 if (sze == 0)
03377                         return (idx < d_cplength) ? idx : d_cplength;
03378 
03379                 if (sze <= d_cplength)
03380                 {
03381                         if (idx > (d_cplength - sze))
03382                                 idx = d_cplength - sze;
03383 
03384                         do
03385                         {
03386                                 if (0 == compare(idx, (size_type)sze, std_str))
03387                                         return idx;
03388 
03389                         } while (idx-- != 0);
03390 
03391                 }
03392 
03393                 return npos;
03394         }
03395 
03418         size_type       find(const utf8* utf8_str, size_type idx = 0) const
03419         {
03420                 return find(utf8_str, idx, utf_length(utf8_str));
03421         }
03422 
03445         size_type       rfind(const utf8* utf8_str, size_type idx = npos) const
03446         {
03447                 return rfind(utf8_str, idx, utf_length(utf8_str));
03448         }
03449 
03475         size_type       find(const utf8* utf8_str, size_type idx, size_type str_len) const
03476         {
03477                 if (str_len == npos)
03478                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03479 
03480                 size_type sze = encoded_size(utf8_str, str_len);
03481 
03482                 if ((sze == 0) && (idx < d_cplength))
03483                         return idx;
03484 
03485                 if (idx < d_cplength)
03486                 {
03487                         // loop while search string could fit in to search area
03488                         while (d_cplength - idx >= sze)
03489                         {
03490                                 if (0 == compare(idx, sze, utf8_str, sze))
03491                                         return idx;
03492 
03493                                 ++idx;
03494                         }
03495 
03496                 }
03497 
03498                 return npos;
03499         }
03500 
03526         size_type       rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
03527         {
03528                 if (str_len == npos)
03529                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03530 
03531                 size_type sze = encoded_size(utf8_str, str_len);
03532 
03533                 if (sze == 0)
03534                         return (idx < d_cplength) ? idx : d_cplength;
03535 
03536                 if (sze <= d_cplength)
03537                 {
03538                         if (idx > (d_cplength - sze))
03539                                 idx = d_cplength - sze;
03540 
03541                         do
03542                         {
03543                                 if (0 == compare(idx, sze, utf8_str, sze))
03544                                         return idx;
03545 
03546                         } while (idx-- != 0);
03547 
03548                 }
03549 
03550                 return npos;
03551         }
03552 
03553 
03570         size_type       find(const char* cstr, size_type idx = 0) const
03571         {
03572                 return find(cstr, idx, strlen(cstr));
03573         }
03574 
03575 
03592         size_type       rfind(const char* cstr, size_type idx = npos) const
03593         {
03594                 return rfind(cstr, idx, strlen(cstr));
03595         }
03596 
03597 
03617         size_type       find(const char* chars, size_type idx, size_type chars_len) const
03618         {
03619                 if (chars_len == npos)
03620                         throw std::length_error("Length for char array can not be 'npos'");
03621 
03622                 if ((chars_len == 0) && (idx < d_cplength))
03623                         return idx;
03624 
03625                 if (idx < d_cplength)
03626                 {
03627                         // loop while search string could fit in to search area
03628                         while (d_cplength - idx >= chars_len)
03629                         {
03630                                 if (0 == compare(idx, chars_len, chars, chars_len))
03631                                         return idx;
03632 
03633                                 ++idx;
03634                         }
03635 
03636                 }
03637 
03638                 return npos;
03639         }
03640 
03641 
03661         size_type       rfind(const char* chars, size_type idx, size_type chars_len) const
03662         {
03663                 if (chars_len == npos)
03664                         throw std::length_error("Length for char array can not be 'npos'");
03665 
03666                 if (chars_len == 0)
03667                         return (idx < d_cplength) ? idx : d_cplength;
03668 
03669                 if (chars_len <= d_cplength)
03670                 {
03671                         if (idx > (d_cplength - chars_len))
03672                                 idx = d_cplength - chars_len;
03673 
03674                         do
03675                         {
03676                                 if (0 == compare(idx, chars_len, chars, chars_len))
03677                                         return idx;
03678 
03679                         } while (idx-- != 0);
03680 
03681                 }
03682 
03683                 return npos;
03684         }
03685 
03686 
03688         // Find first of different code-points
03690 
03704         size_type       find_first_of(const String& str, size_type idx = 0) const
03705         {
03706                 if (idx < d_cplength)
03707                 {
03708                         const utf32* pt = &ptr()[idx];
03709 
03710                         do
03711                         {
03712                                 if (npos != str.find(*pt++))
03713                                         return idx;
03714 
03715                         } while (++idx != d_cplength);
03716 
03717                 }
03718 
03719                 return npos;
03720         }
03721 
03736         size_type       find_first_not_of(const String& str, size_type idx = 0) const
03737         {
03738                 if (idx < d_cplength)
03739                 {
03740                         const utf32* pt = &ptr()[idx];
03741 
03742                         do
03743                         {
03744                                 if (npos == str.find(*pt++))
03745                                         return idx;
03746 
03747                         } while (++idx != d_cplength);
03748 
03749                 }
03750 
03751                 return npos;
03752         }
03753 
03754 
03773         size_type       find_first_of(const std::string& std_str, size_type idx = 0) const
03774         {
03775                 if (idx < d_cplength)
03776                 {
03777                         const utf32* pt = &ptr()[idx];
03778 
03779                         do
03780                         {
03781                                 if (npos != find_codepoint(std_str, *pt++))
03782                                         return idx;
03783 
03784                         } while (++idx != d_cplength);
03785 
03786                 }
03787 
03788                 return npos;
03789         }
03790 
03809         size_type       find_first_not_of(const std::string& std_str, size_type idx = 0) const
03810         {
03811                 if (idx < d_cplength)
03812                 {
03813                         const utf32* pt = &ptr()[idx];
03814 
03815                         do
03816                         {
03817                                 if (npos == find_codepoint(std_str, *pt++))
03818                                         return idx;
03819 
03820                         } while (++idx != d_cplength);
03821 
03822                 }
03823 
03824                 return npos;
03825         }
03826 
03827 
03850         size_type       find_first_of(const utf8* utf8_str, size_type idx = 0) const
03851         {
03852                 return find_first_of(utf8_str, idx, utf_length(utf8_str));
03853         }
03854 
03877         size_type       find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
03878         {
03879                 return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
03880         }
03881 
03907         size_type       find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03908         {
03909                 if (str_len == npos)
03910                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03911 
03912                 if (idx < d_cplength)
03913                 {
03914                         size_type encsze = encoded_size(utf8_str, str_len);
03915 
03916                         const utf32* pt = &ptr()[idx];
03917 
03918                         do
03919                         {
03920                                 if (npos != find_codepoint(utf8_str, encsze, *pt++))
03921                                         return idx;
03922 
03923                         } while (++idx != d_cplength);
03924 
03925                 }
03926 
03927                 return npos;
03928         }
03929 
03955         size_type       find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03956         {
03957                 if (str_len == npos)
03958                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03959 
03960                 if (idx < d_cplength)
03961                 {
03962                         size_type encsze = encoded_size(utf8_str, str_len);
03963 
03964                         const utf32* pt = &ptr()[idx];
03965 
03966                         do
03967                         {
03968                                 if (npos == find_codepoint(utf8_str, encsze, *pt++))
03969                                         return idx;
03970 
03971                         } while (++idx != d_cplength);
03972 
03973                 }
03974 
03975                 return npos;
03976         }
03977 
03978 
03993         size_type       find_first_of(utf32 code_point, size_type idx = 0) const
03994         {
03995                 return find(code_point, idx);
03996         }
03997 
04014         size_type       find_first_not_of(utf32 code_point, size_type idx = 0) const
04015         {
04016                 if (idx < d_cplength)
04017                 {
04018                         do
04019                         {
04020                                 if ((*this)[idx] != code_point)
04021                                         return idx;
04022 
04023                         } while(idx++ < d_cplength);
04024 
04025                 }
04026 
04027                 return npos;
04028         }
04029 
04030 
04047         size_type       find_first_of(const char* cstr, size_type idx = 0) const
04048         {
04049                 return find_first_of(cstr, idx, strlen(cstr));
04050         }
04051 
04052 
04069         size_type       find_first_not_of(const char* cstr, size_type idx = 0) const
04070         {
04071                 return find_first_not_of(cstr, idx, strlen(cstr));
04072         }
04073 
04074 
04094         size_type       find_first_of(const char* chars, size_type idx, size_type chars_len) const
04095         {
04096                 if (chars_len == npos)
04097                         throw std::length_error("Length for char array can not be 'npos'");
04098 
04099                 if (idx < d_cplength)
04100                 {
04101                         const utf32* pt = &ptr()[idx];
04102 
04103                         do
04104                         {
04105                                 if (npos != find_codepoint(chars, chars_len, *pt++))
04106                                         return idx;
04107 
04108                         } while (++idx != d_cplength);
04109 
04110                 }
04111 
04112                 return npos;
04113         }
04114 
04115 
04135         size_type       find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
04136         {
04137                 if (chars_len == npos)
04138                         throw std::length_error("Length for char array can not be 'npos'");
04139 
04140                 if (idx < d_cplength)
04141                 {
04142                         const utf32* pt = &ptr()[idx];
04143 
04144                         do
04145                         {
04146                                 if (npos == find_codepoint(chars, chars_len, *pt++))
04147                                         return idx;
04148 
04149                         } while (++idx != d_cplength);
04150 
04151                 }
04152 
04153                 return npos;
04154         }
04155 
04156 
04158         // Find last of different code-points
04160 
04174         size_type       find_last_of(const String& str, size_type idx = npos) const
04175         {
04176                 if (d_cplength > 0)
04177                 {
04178                         if (idx >= d_cplength)
04179                                 idx = d_cplength - 1;
04180 
04181                         const utf32* pt = &ptr()[idx];
04182 
04183                         do
04184                         {
04185                                 if (npos != str.find(*pt--))
04186                                         return idx;
04187 
04188                         } while (idx-- != 0);
04189 
04190                 }
04191 
04192                 return npos;
04193         }
04194 
04209         size_type       find_last_not_of(const String& str, size_type idx = npos) const
04210         {
04211                 if (d_cplength > 0)
04212                 {
04213                         if (idx >= d_cplength)
04214                                 idx = d_cplength - 1;
04215 
04216                         const utf32* pt = &ptr()[idx];
04217 
04218                         do
04219                         {
04220                                 if (npos == str.find(*pt--))
04221                                         return idx;
04222 
04223                         } while (idx-- != 0);
04224 
04225                 }
04226 
04227                 return npos;
04228         }
04229 
04230 
04249         size_type       find_last_of(const std::string& std_str, size_type idx = npos) const
04250         {
04251                 if (d_cplength > 0)
04252                 {
04253                         if (idx >= d_cplength)
04254                                 idx = d_cplength - 1;
04255 
04256                         const utf32* pt = &ptr()[idx];
04257 
04258                         do
04259                         {
04260                                 if (npos != find_codepoint(std_str, *pt--))
04261                                         return idx;
04262 
04263                         } while (idx-- != 0);
04264 
04265                 }
04266 
04267                 return npos;
04268         }
04269 
04288         size_type       find_last_not_of(const std::string& std_str, size_type idx = npos) const
04289         {
04290                 if (d_cplength > 0)
04291                 {
04292                         if (idx >= d_cplength)
04293                                 idx = d_cplength - 1;
04294 
04295                         const utf32* pt = &ptr()[idx];
04296 
04297                         do
04298                         {
04299                                 if (npos == find_codepoint(std_str, *pt--))
04300                                         return idx;
04301 
04302                         } while (idx-- != 0);
04303 
04304                 }
04305 
04306                 return npos;
04307         }
04308 
04309 
04332         size_type       find_last_of(const utf8* utf8_str, size_type idx = npos) const
04333         {
04334                 return find_last_of(utf8_str, idx, utf_length(utf8_str));
04335         }
04336 
04359         size_type       find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
04360         {
04361                 return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
04362         }
04363 
04389         size_type       find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04390         {
04391                 if (str_len == npos)
04392                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
04393 
04394                 if (d_cplength > 0)
04395                 {
04396                         if (idx >= d_cplength)
04397                                 idx = d_cplength - 1;
04398 
04399                         size_type encsze = encoded_size(utf8_str, str_len);
04400 
04401                         const utf32* pt = &ptr()[idx];
04402 
04403                         do
04404                         {
04405                                 if (npos != find_codepoint(utf8_str, encsze, *pt--))
04406                                         return idx;
04407 
04408                         } while (idx-- != 0);
04409 
04410                 }
04411 
04412                 return npos;
04413         }
04414 
04440         size_type       find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04441         {
04442                 if (str_len == npos)
04443                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
04444 
04445                 if (d_cplength > 0)
04446                 {
04447                         if (idx >= d_cplength)
04448                                 idx = d_cplength - 1;
04449 
04450                         size_type encsze = encoded_size(utf8_str, str_len);
04451 
04452                         const utf32* pt = &ptr()[idx];
04453 
04454                         do
04455                         {
04456                                 if (npos == find_codepoint(utf8_str, encsze, *pt--))
04457                                         return idx;
04458 
04459                         } while (idx-- != 0);
04460 
04461                 }
04462 
04463                 return npos;
04464         }
04465 
04466 
04481         size_type       find_last_of(utf32 code_point, size_type idx = npos) const
04482         {
04483                 return rfind(code_point, idx);
04484         }
04485 
04500         size_type       find_last_not_of(utf32 code_point, size_type idx = npos) const
04501         {
04502                 if (d_cplength > 0)
04503                 {
04504                         if (idx >= d_cplength)
04505                                 idx = d_cplength - 1;
04506 
04507                         do
04508                         {
04509                                 if ((*this)[idx] != code_point)
04510                                         return idx;
04511 
04512                         } while(idx-- != 0);
04513 
04514                 }
04515 
04516                 return npos;
04517         }
04518 
04519 
04536         size_type       find_last_of(const char* cstr, size_type idx = npos) const
04537         {
04538                 return find_last_of(cstr, idx, strlen(cstr));
04539         }
04540 
04541 
04558         size_type       find_last_not_of(const char* cstr, size_type idx = npos) const
04559         {
04560                 return find_last_not_of(cstr, idx, strlen(cstr));
04561         }
04562 
04563 
04583         size_type       find_last_of(const char* chars, size_type idx, size_type chars_len) const
04584         {
04585                 if (chars_len == npos)
04586                         throw std::length_error("Length for char array can not be 'npos'");
04587 
04588                 if (d_cplength > 0)
04589                 {
04590                         if (idx >= d_cplength)
04591                                 idx = d_cplength - 1;
04592 
04593                         const utf32* pt = &ptr()[idx];
04594 
04595                         do
04596                         {
04597                                 if (npos != find_codepoint(chars, chars_len, *pt--))
04598                                         return idx;
04599 
04600                         } while (idx-- != 0);
04601 
04602                 }
04603 
04604                 return npos;
04605         }
04606 
04607 
04627         size_type       find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
04628         {
04629                 if (chars_len == npos)
04630                         throw std::length_error("Length for char array can not be 'npos'");
04631 
04632                 if (d_cplength > 0)
04633                 {
04634                         if (idx >= d_cplength)
04635                                 idx = d_cplength - 1;
04636 
04637                         const utf32* pt = &ptr()[idx];
04638 
04639                         do
04640                         {
04641                                 if (npos == find_codepoint(chars, chars_len, *pt--))
04642                                         return idx;
04643 
04644                         } while (idx-- != 0);
04645 
04646                 }
04647 
04648                 return npos;
04649         }
04650 
04651 
04653         // Substring
04655 
04670         String  substr(size_type idx = 0, size_type len = npos) const
04671         {
04672                 if (d_cplength < idx)
04673                         throw std::out_of_range("Index is out of range for this CEGUI::String");
04674 
04675                 return String(*this, idx, len);
04676         }
04677 
04679         // Iterator creation
04681 
04688         iterator                begin(void)
04689         {
04690                 return iterator(ptr());
04691         }
04692 
04700         const_iterator  begin(void) const
04701         {
04702                 return const_iterator(ptr());
04703         }
04704 
04712         iterator                end(void)
04713         {
04714                 return iterator(&ptr()[d_cplength]);
04715         }
04716 
04724         const_iterator  end(void) const
04725         {
04726                 return const_iterator(&ptr()[d_cplength]);
04727         }
04728 
04736         reverse_iterator                rbegin(void)
04737         {
04738                 return reverse_iterator(end());
04739         }
04740 
04748         const_reverse_iterator  rbegin(void) const
04749         {
04750                 return const_reverse_iterator(end());
04751         }
04752 
04760         reverse_iterator                rend(void)
04761         {
04762                 return reverse_iterator(begin());
04763         }
04764 
04772         const_reverse_iterator  rend(void) const
04773         {
04774                 return const_reverse_iterator(begin());
04775         }
04776 
04777 private:
04778         /*************************************************************************
04779                 Implementation Functions
04780         *************************************************************************/
04781         // string management
04782 
04783         // change size of allocated buffer so it is at least 'new_size'.
04784         // May or may not cause re-allocation and copy of buffer if size is larger
04785         // will never re-allocate to make size smaller.  (see trim())
04786     bool        grow(size_type new_size);
04787 
04788         // perform re-allocation to remove wasted space.
04789     void        trim(void);
04790 
04791         // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
04792         void    setlen(size_type len)
04793         {
04794                 d_cplength = len;
04795                 ptr()[len] = (utf32)(0);
04796         }
04797 
04798         // initialise string object
04799         void    init(void)
04800         {
04801                 d_reserve                       = STR_QUICKBUFF_SIZE;
04802                 d_encodedbuff           = 0;
04803                 d_encodedbufflen        = 0;
04804                 d_encodeddatlen         = 0;
04805                 setlen(0);
04806         }
04807 
04808         // return true if the given pointer is inside the string data
04809         bool    inside(utf32* inptr)
04810         {
04811                 if (inptr < ptr() || ptr() + d_cplength <= inptr)
04812                         return false;
04813                 else
04814                         return true;
04815         }
04816 
04817         // compute distance between two iterators, returning a 'safe' value
04818         size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
04819         {
04820                 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
04821         }
04822         
04823         // encoding functions
04824         // for all:
04825         //      src_len is in code units, or 0 for null terminated string.
04826         //      dest_len is in code units.
04827         //      returns number of code units put into dest buffer.
04828         size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
04829         {
04830                 // count length for null terminated source...
04831                 if (src_len == 0)
04832                 {
04833                         src_len = utf_length(src);
04834                 }
04835 
04836                 size_type destCapacity = dest_len;
04837 
04838                 // while there is data in the source buffer,
04839                 for (uint idx = 0; idx < src_len; ++idx)
04840                 {
04841                         utf32   cp = src[idx];
04842 
04843                         // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
04844                         if (destCapacity < encoded_size(cp))
04845                         {
04846                                 break;
04847                         }
04848 
04849                         if (cp < 0x80)
04850                         {
04851                                 *dest++ = (utf8)cp;
04852                                 --destCapacity;
04853                         }
04854                         else if (cp < 0x0800)
04855                         {
04856                                 *dest++ = (utf8)((cp >> 6) | 0xC0);
04857                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04858                                 destCapacity -= 2;
04859                         }
04860                         else if (cp < 0x10000)
04861                         {
04862                                 *dest++ = (utf8)((cp >> 12) | 0xE0);
04863                                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04864                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04865                                 destCapacity -= 3;
04866                         }
04867                         else
04868                         {
04869                                 *dest++ = (utf8)((cp >> 18) | 0xF0);
04870                                 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
04871                                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04872                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04873                                 destCapacity -= 4;
04874                         }
04875 
04876                 }
04877 
04878                 return dest_len - destCapacity;
04879         }
04880 
04881         size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
04882         {
04883                 // count length for null terminated source...
04884                 if (src_len == 0)
04885                 {
04886                         src_len = utf_length(src);
04887                 }
04888 
04889                 size_type destCapacity = dest_len;
04890 
04891                 // while there is data in the source buffer, and space in the dest buffer
04892                 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
04893                 {
04894                         utf32   cp;
04895                         utf8    cu = src[idx++];
04896 
04897                         if (cu < 0x80)
04898                         {
04899                                 cp = (utf32)(cu);
04900                         }
04901                         else if (cu < 0xE0)
04902                         {
04903                                 cp = ((cu & 0x1F) << 6);
04904                                 cp |= (src[idx++] & 0x3F);
04905                         }
04906                         else if (cu < 0xF0)
04907                         {
04908                                 cp = ((cu & 0x0F) << 12);
04909                                 cp |= ((src[idx++] & 0x3F) << 6);
04910                                 cp |= (src[idx++] & 0x3F);
04911                         }
04912                         else
04913                         {
04914                                 cp = ((cu & 0x07) << 18);
04915                                 cp |= ((src[idx++] & 0x3F) << 12);
04916                                 cp |= ((src[idx++] & 0x3F) << 6);
04917                                 cp |= (src[idx++] & 0x3F);
04918                         }
04919 
04920                         *dest++ = cp;
04921                         --destCapacity;
04922                 }
04923 
04924                 return dest_len - destCapacity;
04925         }
04926 
04927         // return the number of utf8 code units required to encode the given utf32 code point
04928         size_type encoded_size(utf32 code_point) const
04929         {
04930                 if (code_point < 0x80)
04931                         return 1;
04932                 else if (code_point < 0x0800)
04933                         return 2;
04934                 else if (code_point < 0x10000)
04935                         return 3;
04936                 else
04937                         return 4;
04938         }
04939 
04940         // return number of code units required to re-encode given null-terminated utf32 data as utf8.  return does not include terminating null.
04941         size_type encoded_size(const utf32* buf) const
04942         {
04943                 return encoded_size(buf, utf_length(buf));
04944         }
04945 
04946         // return number of code units required to re-encode given utf32 data as utf8.   len is number of code units in 'buf'.
04947         size_type encoded_size(const utf32* buf, size_type len) const
04948         {
04949                 size_type count = 0;
04950 
04951                 while (len--)
04952                 {
04953                         count += encoded_size(*buf++);
04954                 }
04955 
04956                 return count;
04957         }
04958 
04959         // return number of utf32 code units required to re-encode given utf8 data as utf32.  return does not include terminating null.
04960         size_type encoded_size(const utf8* buf) const
04961         {
04962                 return encoded_size(buf, utf_length(buf));
04963         }
04964 
04965         // return number of utf32 code units required to re-encode given utf8 data as utf32.  len is number of code units in 'buf'.
04966         size_type encoded_size(const utf8* buf, size_type len) const
04967         {
04968                 utf8 tcp;
04969                 size_type count = 0;
04970 
04971                 while (len--)
04972                 {
04973                         tcp = *buf++;
04974                         ++count;
04975 
04976                         if (tcp < 0x80)
04977                         {
04978                         }
04979                         else if (tcp < 0xE0)
04980                         {
04981                                 --len;
04982                                 ++buf;
04983                         }
04984                         else if (tcp < 0xF0)
04985                         {
04986                                 len -= 2;
04987                                 buf += 2;
04988                         }
04989                         else
04990                         {
04991                                 len -= 2;
04992                                 buf += 3;
04993                         }
04994 
04995                 }
04996 
04997                 return count;
04998         }
04999 
05000         // return number of code units in a null terminated string
05001         size_type utf_length(const utf8* utf8_str) const
05002         {
05003                 size_type cnt = 0;
05004                 while (*utf8_str++)
05005                         cnt++;
05006 
05007                 return cnt;
05008         }
05009 
05010         // return number of code units in a null terminated string
05011         size_type utf_length(const utf32* utf32_str) const
05012         {
05013                 size_type cnt = 0;
05014                 while (*utf32_str++)
05015                         cnt++;
05016 
05017                 return cnt;
05018         }
05019 
05020         // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
05021     utf8* build_utf8_buff(void) const;
05022 
05023         // compare two utf32 buffers
05024         int     utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
05025         {
05026                 if (!cp_count)
05027                         return 0;
05028 
05029                 while ((--cp_count) && (*buf1 == *buf2))
05030                         buf1++, buf2++;
05031                 
05032                 return *buf1 - *buf2;
05033         }
05034 
05035         // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
05036         int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
05037         {
05038                 if (!cp_count)
05039                         return 0;
05040 
05041                 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
05042                         buf1++, buf2++;
05043 
05044                 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
05045         }
05046 
05047         // compare utf32 buffer with encoded utf8 data
05048         int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
05049         {
05050                 if (!cp_count)
05051                         return 0;
05052 
05053                 utf32   cp;
05054                 utf8    cu;
05055 
05056                 do
05057                 {
05058                         cu = *buf2++;
05059 
05060                         if (cu < 0x80)
05061                         {
05062                                 cp = (utf32)(cu);
05063                         }
05064                         else if (cu < 0xE0)
05065                         {
05066                                 cp = ((cu & 0x1F) << 6);
05067                                 cp |= (*buf2++ & 0x3F);
05068                         }
05069                         else if (cu < 0xF0)
05070                         {
05071                                 cp = ((cu & 0x0F) << 12);
05072                                 cp |= ((*buf2++ & 0x3F) << 6);
05073                                 cp |= (*buf2++ & 0x3F);
05074                         }
05075                         else
05076                         {
05077                                 cp = ((cu & 0x07) << 18);
05078                                 cp |= ((*buf2++ & 0x3F) << 12);
05079                                 cp |= ((*buf2++ & 0x3F) << 6);
05080                                 cp |= (*buf2++ & 0x3F);
05081                         }
05082 
05083                 } while ((*buf1++ == cp) && (--cp_count));
05084 
05085                 return (*--buf1) - cp;
05086         }
05087 
05088         // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
05089         size_type find_codepoint(const std::string& str, utf32 code_point) const
05090         {
05091                 size_type idx = 0, sze = (size_type)str.size();
05092 
05093                 while (idx != sze)
05094                 {
05095                         if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
05096                                 return idx;
05097 
05098                         ++idx;
05099                 }
05100 
05101                 return npos;
05102         }
05103 
05104         // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none.  len is in code points.
05105         size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const 
05106         {
05107                 size_type idx = 0;
05108 
05109                 utf32   cp;
05110                 utf8    cu;
05111 
05112                 while (idx != len) {
05113                         cu = *str++;
05114 
05115                         if (cu < 0x80)
05116                         {
05117                                 cp = (utf32)(cu);
05118                         }
05119                         else if (cu < 0xE0)
05120                         {
05121                                 cp = ((cu & 0x1F) << 6);
05122                                 cp |= (*str++ & 0x3F);
05123                         }
05124                         else if (cu < 0xF0)
05125                         {
05126                                 cp = ((cu & 0x0F) << 12);
05127                                 cp |= ((*str++ & 0x3F) << 6);
05128                                 cp |= (*str++ & 0x3F);
05129                         }
05130                         else
05131                         {
05132                                 cp = ((cu & 0x07) << 18);
05133                                 cp |= ((*str++ & 0x3F) << 12);
05134                                 cp |= ((*str++ & 0x3F) << 6);
05135                                 cp |= (*str++ & 0x3F);
05136                         }
05137 
05138                         if (code_point == cp)
05139                                 return idx;
05140 
05141                         ++idx;
05142                 }
05143 
05144                 return npos;
05145         }
05146 
05147 
05148         // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
05149         size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
05150         {
05151                 for (size_type idx = 0; idx != chars_len; ++idx)
05152                 {
05153                         if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
05154                                 return idx;
05155                 }
05156 
05157                 return npos;
05158         }
05159 
05160 };
05161 
05162 
05164 // Comparison operators
05166 
05170 bool CEGUIEXPORT        operator==(const String& str1, const String& str2);
05171 
05176 bool CEGUIEXPORT        operator==(const String& str, const std::string& std_str);
05177 
05182 bool CEGUIEXPORT        operator==(const std::string& std_str, const String& str);
05183 
05188 bool CEGUIEXPORT        operator==(const String& str, const utf8* utf8_str);
05189 
05194 bool CEGUIEXPORT        operator==(const utf8* utf8_str, const String& str);
05195 
05200 bool CEGUIEXPORT        operator!=(const String& str1, const String& str2);
05201 
05206 bool CEGUIEXPORT        operator!=(const String& str, const std::string& std_str);
05207 
05212 bool CEGUIEXPORT        operator!=(const std::string& std_str, const String& str);
05213 
05218 bool CEGUIEXPORT        operator!=(const String& str, const utf8* utf8_str);
05219 
05224 bool CEGUIEXPORT        operator!=(const utf8* utf8_str, const String& str);
05225 
05230 bool CEGUIEXPORT        operator<(const String& str1, const String& str2);
05231 
05236 bool CEGUIEXPORT        operator<(const String& str, const std::string& std_str);
05237 
05242 bool CEGUIEXPORT        operator<(const std::string& std_str, const String& str);
05243 
05248 bool CEGUIEXPORT        operator<(const String& str, const utf8* utf8_str);
05249 
05254 bool CEGUIEXPORT        operator<(const utf8* utf8_str, const String& str);
05255 
05260 bool CEGUIEXPORT        operator>(const String& str1, const String& str2);
05261 
05266 bool CEGUIEXPORT        operator>(const String& str, const std::string& std_str);
05267 
05272 bool CEGUIEXPORT        operator>(const std::string& std_str, const String& str);
05273 
05278 bool CEGUIEXPORT        operator>(const String& str, const utf8* utf8_str);
05279 
05284 bool CEGUIEXPORT        operator>(const utf8* utf8_str, const String& str);
05285 
05290 bool CEGUIEXPORT        operator<=(const String& str1, const String& str2);
05291 
05296 bool CEGUIEXPORT        operator<=(const String& str, const std::string& std_str);
05297 
05302 bool CEGUIEXPORT        operator<=(const std::string& std_str, const String& str);
05303 
05308 bool CEGUIEXPORT        operator<=(const String& str, const utf8* utf8_str);
05309 
05314 bool CEGUIEXPORT        operator<=(const utf8* utf8_str, const String& str);
05315 
05320 bool CEGUIEXPORT        operator>=(const String& str1, const String& str2);
05321 
05326 bool CEGUIEXPORT        operator>=(const String& str, const std::string& std_str);
05327 
05332 bool CEGUIEXPORT        operator>=(const std::string& std_str, const String& str);
05333 
05338 bool CEGUIEXPORT        operator>=(const String& str, const utf8* utf8_str);
05339 
05344 bool CEGUIEXPORT        operator>=(const utf8* utf8_str, const String& str);
05345 
05350 bool CEGUIEXPORT        operator==(const String& str, const char* c_str);
05351 
05356 bool CEGUIEXPORT        operator==(const char* c_str, const String& str);
05357 
05362 bool CEGUIEXPORT        operator!=(const String& str, const char* c_str);
05363 
05368 bool CEGUIEXPORT        operator!=(const char* c_str, const String& str);
05369 
05374 bool CEGUIEXPORT        operator<(const String& str, const char* c_str);
05375 
05380 bool CEGUIEXPORT        operator<(const char* c_str, const String& str);
05381 
05386 bool CEGUIEXPORT        operator>(const String& str, const char* c_str);
05387 
05392 bool CEGUIEXPORT        operator>(const char* c_str, const String& str);
05393 
05398 bool CEGUIEXPORT        operator<=(const String& str, const char* c_str);
05399 
05404 bool CEGUIEXPORT        operator<=(const char* c_str, const String& str);
05405 
05410 bool CEGUIEXPORT        operator>=(const String& str, const char* c_str);
05411 
05416 bool CEGUIEXPORT        operator>=(const char* c_str, const String& str);
05417 
05419 // Concatenation operator functions
05421 
05436 String CEGUIEXPORT      operator+(const String& str1, const String& str2);
05437 
05453 String CEGUIEXPORT      operator+(const String& str, const std::string& std_str);
05454 
05470 String CEGUIEXPORT      operator+(const std::string& std_str, const String& str);
05471 
05487 String CEGUIEXPORT      operator+(const String& str, const utf8* utf8_str);
05488 
05504 String CEGUIEXPORT      operator+(const utf8* utf8_str, const String& str);
05505 
05521 String CEGUIEXPORT      operator+(const String& str, utf32 code_point);
05522 
05538 String CEGUIEXPORT      operator+(utf32 code_point, const String& str);
05539 
05555 String CEGUIEXPORT      operator+(const String& str, const char* c_str);
05556 
05572 String CEGUIEXPORT      operator+(const char* c_str, const String& str);
05573 
05574 
05576 // Output (stream) functions
05578 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
05579 
05580 
05582 // Modifying operations
05584 
05597 void CEGUIEXPORT swap(String& str1, String& str2);
05598 
05599 
05600 } // End of  CEGUI namespace section
05601 
05602 
05603 #endif  // end of guard _CEGUIString_h_

Generated on Sun Nov 5 14:35:28 2006 for Crazy Eddies GUI System by  doxygen 1.4.7