Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

CEGUIString.h

Go to the documentation of this file.
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     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00010     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00011 
00012     This library is free software; you can redistribute it and/or
00013     modify it under the terms of the GNU Lesser General Public
00014     License as published by the Free Software Foundation; either
00015     version 2.1 of the License, or (at your option) any later version.
00016 
00017     This library is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020     Lesser General Public License for more details.
00021 
00022     You should have received a copy of the GNU Lesser General Public
00023     License along with this library; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 *************************************************************************/
00026 #ifndef _CEGUIString_h_
00027 #define _CEGUIString_h_
00028 
00029 #include "CEGUIBase.h"
00030 #include <string>
00031 #include <string.h>
00032 #include <stdexcept>
00033 
00034 // Start of CEGUI namespace section
00035 namespace CEGUI
00036 {
00037 #define STR_QUICKBUFF_SIZE      32
00038         /*************************************************************************
00039                 Basic Types
00040         *************************************************************************/
00041         typedef         uchar   utf8;
00042         //typedef               ushort  utf16;  // removed typedef to prevent usage, as utf16 is not supported (yet)
00043         typedef         ulong   utf32;
00044 
00053 class CEGUIBASE_API String
00054 {
00055 public:
00056         /*************************************************************************
00057                 Integral Types
00058         *************************************************************************/
00059         typedef         utf32                   value_type;                                     
00060         typedef         uint                    size_type;                                      
00061         typedef         ptrdiff_t               difference_type;                        
00062         typedef         utf32&                  reference;                                      
00063         typedef         const utf32&    const_reference;                        
00064         typedef         utf32*                  pointer;                                        
00065         typedef         const utf32*    const_pointer;                          
00066 
00067         static const size_type          npos;                                           
00068 
00069 private:
00070         /*************************************************************************
00071                 Implementation data
00072         *************************************************************************/
00073         size_type       d_cplength;                     
00074         size_type       d_reserve;                      
00075 
00076         mutable utf8*           d_encodedbuff;          
00077         mutable size_type       d_encodeddatlen;        
00078         mutable size_type       d_encodedbufflen;       
00079 
00080         utf32           d_quickbuff[STR_QUICKBUFF_SIZE];        
00081         utf32*          d_buffer;                                                       
00082 
00083 public:
00084         /*************************************************************************
00085                 Iterator Classes
00086         *************************************************************************/
00091 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00092         class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32>
00093 #else
00094         class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32, std::ptrdiff_t, const utf32*, const utf32&>
00095 #endif
00096         {
00097 
00098         public:
00100                 // data
00102                 const utf32*    d_ptr;
00103 
00104 
00106                 // Methods
00108                 const_iterator(void)
00109                 {
00110                         d_ptr = 0;
00111                 }
00112                 const_iterator(const_pointer ptr)
00113                 {
00114                         d_ptr = ptr;
00115                 }
00116 
00117                 const_reference operator*() const
00118                 {
00119                         return *d_ptr;
00120                 }
00121 
00122 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00123 #       pragma warning (push)
00124 #       pragma warning (disable : 4284)
00125 #endif
00126                 const_pointer   operator->() const              
00127                 {
00128                         return &**this;
00129                 }
00130 
00131 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00132 #       pragma warning (pop)
00133 #endif
00134 
00135                 const_iterator& operator++()
00136                 {
00137                         ++d_ptr;
00138                         return *this;
00139                 }
00140 
00141                 const_iterator  operator++(int)         
00142                 {
00143                         const_iterator temp = *this;
00144                         ++*this;
00145                         return temp;
00146                 }
00147 
00148                 const_iterator& operator--()
00149                 {
00150                         --d_ptr;
00151                         return *this;
00152                 }
00153 
00154                 const_iterator  operator--(int)         
00155                 {
00156                         const_iterator temp = *this;
00157                         --*this;
00158                         return temp;
00159                 }
00160 
00161                 const_iterator& operator+=(difference_type offset)
00162                 {
00163                         d_ptr += offset;
00164                         return *this;
00165                 }
00166 
00167                 const_iterator operator+(difference_type offset) const
00168                 {
00169                         const_iterator temp = *this;
00170                         return temp += offset;
00171                 }
00172 
00173                 const_iterator& operator-=(difference_type offset)
00174                 {
00175                         return *this += -offset;
00176                 }
00177 
00178                 const_iterator operator-(difference_type offset) const
00179                 {
00180                         const_iterator temp = *this;
00181                         return temp -= offset;
00182                 }
00183 
00184                 difference_type operator-(const const_iterator& iter) const
00185                 {
00186                         return d_ptr - iter.d_ptr;
00187                 }
00188 
00189                 const_reference operator[](difference_type offset) const
00190                 {
00191                         return *(*this + offset);
00192                 }
00193 
00194                 bool operator==(const const_iterator& iter) const
00195                 {
00196                         return d_ptr == iter.d_ptr;
00197                 }
00198 
00199                 bool operator!=(const const_iterator& iter) const
00200                 {
00201                         return !(*this == iter);
00202                 }
00203 
00204                 bool operator<(const const_iterator& iter) const
00205                 {
00206                         return d_ptr < iter.d_ptr;
00207                 }
00208 
00209                 bool operator>(const const_iterator& iter) const
00210                 {
00211                         return (!(iter < *this));
00212                 }
00213 
00214                 bool operator<=(const const_iterator& iter) const
00215                 {
00216                         return (!(iter < *this));
00217                 }
00218 
00219                 bool operator>=(const const_iterator& iter) const
00220                 {
00221                         return (!(*this < iter));
00222                 }
00223 
00224                 friend const_iterator operator+(difference_type offset, const const_iterator& iter)
00225                 {
00226                         return iter + offset;
00227                 }
00228 
00229         };
00230 
00235         class iterator : public const_iterator
00236         {
00237         public:
00238                 iterator(void) {}
00239                 iterator(pointer ptr) : const_iterator(ptr) {}
00240 
00241 
00242                 reference operator*() const
00243                 {
00244                         return ((reference)**(const_iterator *)this);
00245                 }
00246 
00247 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00248 #       pragma warning (push)
00249 #       pragma warning (disable : 4284)
00250 #endif
00251 
00252                 pointer operator->() const
00253                 {
00254                         return &**this;
00255                 }
00256 
00257 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
00258 #       pragma warning (pop)
00259 #endif
00260 
00261                 iterator& operator++()
00262                 {
00263                         ++this->d_ptr;
00264                         return *this;
00265                 }
00266 
00267                 iterator operator++(int)
00268                 {
00269                         iterator temp = *this;
00270                         ++*this;
00271                         return temp;
00272                 }
00273 
00274                 iterator& operator--()
00275                 {
00276                         --this->d_ptr;
00277                         return *this;
00278                 }
00279 
00280                 iterator operator--(int)
00281                 {
00282                         iterator temp = *this;
00283                         --*this;
00284                         return temp;
00285                 }
00286 
00287                 iterator& operator+=(difference_type offset)
00288                 {
00289                         this->d_ptr += offset;
00290                         return *this;
00291                 }
00292 
00293                 iterator operator+(difference_type offset) const
00294                 {
00295                         iterator temp = *this;
00296                         return temp + offset;
00297                 }
00298 
00299                 iterator& operator-=(difference_type offset)
00300                 {
00301                         return *this += -offset;
00302                 }
00303 
00304                 iterator operator-(difference_type offset) const
00305                 {
00306                         iterator temp = *this;
00307                         return temp -= offset;
00308                 }
00309 
00310                 difference_type operator-(const const_iterator& iter) const
00311                 {
00312                         return ((const_iterator)*this - iter);
00313                 }
00314 
00315                 reference operator[](difference_type offset) const
00316                 {
00317                         return *(*this + offset);
00318                 }
00319 
00320                 friend iterator operator+(difference_type offset, const iterator& iter)
00321                 {
00322                         return iter + offset;
00323                 }
00324 
00325         };
00326 
00331 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
00332         typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type>  const_reverse_iterator;
00333 #else
00334         typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
00335 #endif
00336 
00341 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
00342         typedef std::reverse_iterator<iterator, pointer, reference, difference_type>                    reverse_iterator;
00343 #else
00344         typedef std::reverse_iterator<iterator>                 reverse_iterator;
00345 #endif
00346 
00347 public:
00349         // Default Construction and Destructor
00351 
00355         String(void)
00356         {
00357                 init();
00358         }
00359 
00364         ~String(void)
00365         {
00366                 if (d_reserve > STR_QUICKBUFF_SIZE)
00367                 {
00368                         delete[] d_buffer;
00369                 }
00370 
00371                 if (d_encodedbufflen > 0)
00372                 {
00373                         delete[] d_encodedbuff;
00374                 }
00375 
00376         }
00377 
00379         // Construction via CEGUI::String
00381 
00391         String(const String& str)
00392         {
00393                 init();
00394                 assign(str);
00395         }
00396         
00397 
00414         String(const String& str, size_type str_idx, size_type str_num = npos)
00415         {
00416                 init();
00417                 assign(str, str_idx, str_num);
00418         }
00419 
00421         // Construction via std::string
00423 
00439         String(const std::string& std_str)
00440         {
00441                 init();
00442                 assign(std_str);
00443         }
00444                 
00467         String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
00468         {
00469                 init();
00470                 assign(std_str, str_idx, str_num);
00471         }
00472 
00473 
00475         // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
00477 
00495         String(const utf8* utf8_str)
00496         {
00497                 init();
00498                 assign(utf8_str);
00499         }
00500 
00527         String(const utf8* utf8_str, size_type chars_len)
00528         {
00529                 init();
00530                 assign(utf8_str, chars_len);
00531         }
00532 
00534         // Construction via code-point (using a UTF-32 code unit)
00536 
00551         String(size_type num, utf32 code_point)
00552         {
00553                 init();
00554                 assign(num, code_point);
00555         }
00556 
00558         // Construction via iterator
00560         // Create string with characters in the range [beg, end)
00574         String(const_iterator beg, const_iterator end)
00575         {
00576                 init();
00577                 append(beg, end);
00578         }
00579 
00580 
00582         // Construction via c-string
00584 
00596         String(const char* c_str)
00597         {
00598                 init();
00599                 assign(c_str);
00600         }
00601 
00617         String(const char* chars, size_type chars_len)
00618         {
00619                 init();
00620                 assign(chars, chars_len);
00621         }
00622 
00623 
00625         // Size operations
00627 
00634         size_type       size(void) const
00635         {
00636                 return d_cplength;
00637         }
00638 
00646         size_type       length(void) const
00647         {
00648                 return d_cplength;
00649         }
00650 
00658         bool    empty(void) const
00659         {
00660                 return  (d_cplength == 0);
00661         }
00662 
00672         static size_type        max_size(void)
00673         {
00674                 return (((size_type)-1) / sizeof(utf32));
00675         }
00676 
00678         // Capacity Operations
00680         // return the number of code points the string could hold without re-allocation
00681         // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
00690         size_type capacity(void) const
00691         {
00692                 return d_reserve - 1;
00693         }
00694 
00695         // reserve internal memory for at-least 'num' code-points (characters).  if num is 0, request is shrink-to-fit.
00710         void    reserve(size_type num = 0)
00711         {
00712                 if (num == 0)
00713                         trim();
00714                 else
00715                         grow(num);
00716         }
00717 
00719         // Comparisons
00721 
00736         int             compare(const String& str) const
00737         {
00738                 return compare(0, d_cplength, str);
00739         }
00740 
00770         int             compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
00771         {
00772                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
00773                         throw std::out_of_range("Index is out of range for CEGUI::String");
00774 
00775                 if ((len == npos) || (idx + len > d_cplength))
00776                         len = d_cplength - idx;
00777 
00778                 if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
00779                         str_len = str.d_cplength - str_idx;
00780 
00781                 int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
00782 
00783                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
00784         }
00785 
00786 
00806         int             compare(const std::string& std_str) const
00807         {
00808                 return compare(0, d_cplength, std_str);
00809         }
00810 
00811 
00845         int             compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
00846         {
00847                 if (d_cplength < idx)
00848                         throw std::out_of_range("Index is out of range for CEGUI::String");
00849 
00850                 if (std_str.size() < str_idx)
00851                         throw std::out_of_range("Index is out of range for std::string");
00852 
00853                 if ((len == npos) || (idx + len > d_cplength))
00854                         len = d_cplength - idx;
00855 
00856                 if ((str_len == npos) || (str_idx + str_len > std_str.size()))
00857                         str_len = (size_type)std_str.size() - str_idx;
00858 
00859                 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
00860 
00861                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
00862         }
00863 
00864 
00886         int             compare(const utf8* utf8_str) const
00887         {
00888                 return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
00889         }
00890 
00891 
00921         int             compare(size_type idx, size_type len, const utf8* utf8_str) const
00922         {
00923                 return compare(idx, len, utf8_str, encoded_size(utf8_str));
00924         }
00925 
00959         int             compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
00960         {
00961                 if (d_cplength < idx)
00962                         throw std::out_of_range("Index is out of range for CEGUI::String");
00963 
00964                 if (str_cplen == npos)
00965                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
00966 
00967                 if ((len == npos) || (idx + len > d_cplength))
00968                         len = d_cplength - idx;
00969 
00970                 int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
00971 
00972                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
00973         }
00974 
00975 
00991         int             compare(const char* c_str) const
00992         {
00993                 return compare(0, d_cplength, c_str, strlen(c_str));
00994         }
00995 
00996 
01020         int             compare(size_type idx, size_type len, const char* c_str) const
01021         {
01022                 return compare(idx, len, c_str, strlen(c_str));
01023         }
01024 
01025 
01053         int             compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
01054         {
01055                 if (d_cplength < idx)
01056                         throw std::out_of_range("Index is out of range for CEGUI::String");
01057 
01058                 if (chars_len == npos)
01059                         throw std::length_error("Length for char array can not be 'npos'");
01060 
01061                 if ((len == npos) || (idx + len > d_cplength))
01062                         len = d_cplength - idx;
01063 
01064                 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
01065 
01066                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
01067         }
01068 
01069 
01071         // Character access
01073 
01087         reference       operator[](size_type idx)
01088         {
01089                 return (ptr()[idx]);
01090         }
01091 
01106         value_type      operator[](size_type idx) const
01107         {
01108                 return ptr()[idx];
01109         }
01110 
01123         reference       at(size_type idx)
01124         {
01125                 if (d_cplength <= idx)
01126                         throw std::out_of_range("Index is out of range for CEGUI::String");
01127 
01128                 return ptr()[idx];
01129         }
01130 
01143         const_reference at(size_type idx) const
01144         {
01145                 if (d_cplength <= idx)
01146                         throw std::out_of_range("Index is out of range for CEGUI::String");
01147 
01148                 return ptr()[idx];
01149         }
01150 
01151 
01153         // C-Strings and arrays
01155 
01168         const char* c_str(void) const
01169         {
01170                 return (const char*)build_utf8_buff();
01171         }
01172 
01186         const utf8* data(void) const
01187         {
01188                 return build_utf8_buff();
01189         }
01190 
01191         // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
01192         // return number of utf8 code units placed into the buffer
01213         size_type       copy(utf8* buf, size_type len = npos, size_type idx = 0) const
01214         {
01215                 if (d_cplength < idx)
01216                         throw std::out_of_range("Index is out of range for CEGUI::String");
01217 
01218                 if (len == npos)
01219                         len = d_cplength;
01220 
01221                 return encode(&ptr()[idx], buf, npos, len);
01222         }
01223 
01225         // UTF8 Encoding length information
01227         // 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.
01243         size_type       utf8_stream_len(size_type num = npos, size_type idx = 0)
01244         {
01245                 using namespace std;
01246 
01247                 if (d_cplength < idx)
01248                         throw out_of_range("Index was out of range for CEGUI::String object");
01249 
01250                 size_type       maxlen = d_cplength - idx;
01251 
01252                 return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
01253         }
01254 
01256         // Assignment Functions
01258 
01268         String& operator=(const String& str)
01269         {
01270                 return assign(str);
01271         }
01272 
01291         String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
01292         {
01293                 if (str.d_cplength < str_idx)
01294                         throw std::out_of_range("Index was out of range for CEGUI::String object");
01295 
01296                 if (str_num == npos)
01297                         str_num = str.d_cplength - str_idx;
01298 
01299                 grow(str_num);
01300                 setlen(str_num);
01301                 memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
01302                 return *this;
01303         }
01304 
01321         String& operator=(const std::string& std_str)
01322         {
01323                 return assign(std_str);
01324         }
01325 
01349         String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
01350         {
01351                 if (std_str.size() < str_idx)
01352                         throw std::out_of_range("Index was out of range for std::string object");
01353 
01354                 if (str_num == npos)
01355                         str_num = (size_type)std_str.size() - str_idx;
01356 
01357                 grow(str_num);
01358                 setlen(str_num);
01359 
01360                 while(str_num--)
01361                 {
01362                         ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
01363                 }
01364 
01365                 return *this;
01366         }
01367 
01386         String& operator=(const utf8* utf8_str)
01387         {
01388                 return assign(utf8_str, utf_length(utf8_str));
01389         }
01390 
01409         String& assign(const utf8* utf8_str)
01410         {
01411                 return assign(utf8_str, utf_length(utf8_str));
01412         }
01413 
01435         String& assign(const utf8* utf8_str, size_type str_num)
01436         {
01437                 if (str_num == npos)
01438                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
01439 
01440                 size_type enc_sze = encoded_size(utf8_str, str_num);
01441 
01442                 grow(enc_sze);
01443                 encode(utf8_str, ptr(), d_reserve, str_num);
01444                 setlen(enc_sze);
01445                 return *this;
01446         }
01447 
01458         String& operator=(utf32 code_point)
01459         {
01460                 return assign(1, code_point);
01461         }
01462 
01478         String& assign(size_type num, utf32 code_point)
01479         {
01480                 if (num == npos)
01481                         throw std::length_error("Code point count can not be 'npos'");
01482 
01483                 grow(num);
01484                 setlen(num);
01485                 utf32* p = ptr();
01486 
01487                 while(num--)
01488                         *p = code_point;
01489 
01490                 return *this;
01491         }
01492 
01493 
01506         String& operator=(const char* c_str)
01507         {
01508                 return assign(c_str, strlen(c_str));
01509         }
01510 
01511 
01524         String& assign(const char* c_str)
01525         {
01526                 return assign(c_str, strlen(c_str));
01527         }
01528 
01529 
01545         String& assign(const char* chars, size_type chars_len)
01546         {
01547                 grow(chars_len);
01548                 utf32* pt = ptr();
01549 
01550                 for (size_type i = 0; i < chars_len; ++i)
01551                 {
01552                         *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
01553                 }
01554 
01555                 setlen(chars_len);
01556                 return *this;
01557         }
01558 
01559 
01570         void    swap(String& str)
01571         {
01572                 size_type       temp_len        = d_cplength;
01573                 d_cplength = str.d_cplength;
01574                 str.d_cplength = temp_len;
01575 
01576                 size_type       temp_res        = d_reserve;
01577                 d_reserve = str.d_reserve;
01578                 str.d_reserve = temp_res;
01579 
01580                 utf32*          temp_buf        = d_buffer;
01581                 d_buffer = str.d_buffer;
01582                 str.d_buffer = temp_buf;
01583 
01584                 // see if we need to swap 'quick buffer' data
01585                 if (temp_res <= STR_QUICKBUFF_SIZE)
01586                 {
01587                         utf32           temp_qbf[STR_QUICKBUFF_SIZE];
01588 
01589                         memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
01590                         memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
01591                         memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
01592                 }
01593 
01594         }
01595 
01597         // Appending Functions
01599 
01611         String& operator+=(const String& str)
01612         {
01613                 return append(str);
01614         }
01615 
01635         String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
01636         {
01637                 if (str.d_cplength < str_idx)
01638                         throw std::out_of_range("Index is out of range for CEGUI::String");
01639 
01640                 if (str_num == npos)
01641                         str_num = str.d_cplength - str_idx;
01642 
01643                 grow(d_cplength + str_num);
01644                 memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
01645                 setlen(d_cplength + str_num);
01646                 return *this;
01647         }
01648 
01649 
01666         String& operator+=(const std::string& std_str)
01667         {
01668                 return append(std_str);
01669         }
01670 
01694         String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
01695         {
01696                 if (std_str.size() < str_idx)
01697                         throw std::out_of_range("Index is out of range for std::string");
01698 
01699                 if (str_num == npos)
01700                         str_num = (size_type)std_str.size() - str_idx;
01701 
01702                 size_type newsze = d_cplength + str_num;
01703 
01704                 grow(newsze);
01705                 utf32* pt = &ptr()[newsze-1];
01706 
01707                 while(str_num--)
01708                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
01709 
01710                 setlen(newsze);
01711                 return *this;
01712         }
01713 
01714 
01733         String& operator+=(const utf8* utf8_str)
01734         {
01735                 return append(utf8_str, utf_length(utf8_str));
01736         }
01737 
01756         String& append(const utf8* utf8_str)
01757         {
01758                 return append(utf8_str, utf_length(utf8_str));
01759         }
01760 
01761 
01783         String& append(const utf8* utf8_str, size_type len)
01784         {
01785                 if (len == npos)
01786                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
01787 
01788                 size_type encsz = encoded_size(utf8_str, len);
01789                 size_type newsz = d_cplength + encsz;
01790 
01791                 grow(newsz);
01792                 encode(utf8_str, &ptr()[d_cplength], encsz, len);
01793                 setlen(newsz);
01794 
01795                 return *this;
01796         }
01797 
01798 
01811         String& operator+=(utf32 code_point)
01812         {
01813                 return append(1, code_point);
01814         }
01815 
01831         String& append(size_type num, utf32 code_point)
01832         {
01833                 if (num == npos)
01834                         throw std::length_error("Code point count can not be 'npos'");
01835 
01836                 size_type newsz = d_cplength + num;
01837                 grow(newsz);
01838 
01839                 utf32* p = &ptr()[d_cplength];
01840 
01841                 while(num--)
01842                         *p++ = code_point;
01843 
01844                 setlen(newsz);
01845 
01846                 return *this;
01847         }
01848 
01861         void    push_back(utf32 code_point)
01862         {
01863                 append(1, code_point);
01864         }
01865 
01881         String& append(const_iterator beg, const_iterator end)
01882         {
01883                 return replace(this->end(), this->end(), beg, end);
01884         }
01885 
01886 
01899         String& operator+=(const char* c_str)
01900         {
01901                 return append(c_str, strlen(c_str));
01902         }
01903 
01904 
01917         String& append(const char* c_str)
01918         {
01919                 return append(c_str, strlen(c_str));
01920         }
01921 
01922 
01938         String& append(const char* chars, size_type chars_len)
01939         {
01940                 if (chars_len == npos)
01941                         throw std::length_error("Length for char array can not be 'npos'");
01942 
01943                 size_type newsz = d_cplength + chars_len;
01944 
01945                 grow(newsz);
01946 
01947                 utf32* pt = &ptr()[newsz-1];
01948 
01949                 while(chars_len--)
01950                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
01951 
01952                 setlen(newsz);
01953 
01954                 return *this;
01955         }
01956 
01957 
01959         // Insertion Functions
01961 
01977         String& insert(size_type idx, const String& str)
01978         {
01979                 return insert(idx, str, 0, npos);
01980         }
01981 
02004         String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
02005         {
02006                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
02007                         throw std::out_of_range("Index is out of range for CEGUI::String");
02008 
02009                 if (str_num == npos)
02010                         str_num = str.d_cplength - str_idx;
02011 
02012                 size_type newsz = d_cplength + str_num;
02013                 grow(newsz);
02014                 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02015                 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02016                 setlen(newsz);
02017 
02018                 return *this;
02019         }
02020 
02041         String& insert(size_type idx, const std::string& std_str)
02042         {
02043                 return insert(idx, std_str, 0, npos);
02044         }
02045 
02072         String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
02073         {
02074                 if (d_cplength < idx)
02075                         throw std::out_of_range("Index is out of range for CEGUI::String");
02076 
02077                 if (std_str.size() < str_idx)
02078                         throw std::out_of_range("Index is out of range for std::string");
02079 
02080                 if (str_num == npos)
02081                         str_num = (size_type)std_str.size() - str_idx;
02082 
02083                 size_type newsz = d_cplength + str_num;
02084                 grow(newsz);
02085 
02086                 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02087 
02088                 utf32* pt = &ptr()[idx + str_num - 1];
02089                 
02090                 while(str_num--)
02091                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02092 
02093                 setlen(newsz);
02094 
02095                 return *this;
02096         }
02097 
02120         String& insert(size_type idx, const utf8* utf8_str)
02121         {
02122                 return insert(idx, utf8_str, utf_length(utf8_str));
02123         }
02124 
02150         String& insert(size_type idx, const utf8* utf8_str, size_type len)
02151         {
02152                 if (d_cplength < idx)
02153                         throw std::out_of_range("Index is out of range for CEGUI::String");
02154 
02155                 if (len == npos)
02156                         throw std::length_error("Length of utf8 encoded string can not be 'npos'");
02157 
02158                 size_type encsz = encoded_size(utf8_str, len);
02159                 size_type newsz = d_cplength + encsz;
02160 
02161                 grow(newsz);
02162                 memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02163                 encode(utf8_str, &ptr()[idx], encsz, len);
02164                 setlen(newsz);
02165 
02166                 return *this;
02167         }
02168 
02188         String& insert(size_type idx, size_type num, utf32 code_point)
02189         {
02190                 if (d_cplength < idx)
02191                         throw std::out_of_range("Index is out of range for CEGUI::String");
02192 
02193                 if (num == npos)
02194                         throw std::length_error("Code point count can not be 'npos'");
02195 
02196                 size_type newsz = d_cplength + num;
02197                 grow(newsz);
02198 
02199                 memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02200 
02201                 utf32* pt = &ptr()[idx + num - 1];
02202 
02203                 while(num--)
02204                         *pt-- = code_point;
02205 
02206                 setlen(newsz);
02207 
02208                 return *this;
02209         }
02210 
02229         void insert(iterator pos, size_type num, utf32 code_point)
02230         {
02231                 insert(safe_iter_dif(pos, begin()), num, code_point);
02232         }
02233 
02249         iterator insert(iterator pos, utf32 code_point)
02250         {
02251                 insert(pos, 1, code_point);
02252                 return pos;
02253         }
02254 
02273         void    insert(iterator pos, const_iterator beg, const_iterator end)
02274         {
02275                 replace(pos, pos, beg, end);
02276         }
02277 
02278 
02295         String& insert(size_type idx, const char* c_str)
02296         {
02297                 return insert(idx, c_str, strlen(c_str));
02298         }
02299 
02300 
02320         String& insert(size_type idx, const char* chars, size_type chars_len)
02321         {
02322                 if (d_cplength < idx)
02323                         throw std::out_of_range("Index is out of range for CEGUI::String");
02324 
02325                 if (chars_len == npos)
02326                         throw std::length_error("Length of char array can not be 'npos'");
02327 
02328                 size_type newsz = d_cplength + chars_len;
02329 
02330                 grow(newsz);
02331                 memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
02332 
02333                 utf32* pt = &ptr()[idx + chars_len - 1];
02334 
02335                 while(chars_len--)
02336                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
02337 
02338                 setlen(newsz);
02339 
02340                 return *this;
02341         }
02342 
02343 
02345         // Erasing characters
02347 
02354         void    clear(void)
02355         {
02356                 setlen(0);
02357                 trim();
02358         }
02359 
02367         String& erase(void)
02368         {
02369                 clear();
02370                 return *this;
02371         }
02372 
02385         String& erase(size_type idx)
02386         {
02387                 return erase(idx, 1);
02388         }
02389 
02405         String& erase(size_type idx, size_type len = npos)
02406         {
02407                 if (d_cplength < idx)
02408                         throw std::out_of_range("Index is out of range foe CEGUI::String");
02409 
02410                 if (len == npos)
02411                         len = d_cplength - idx;
02412 
02413                 size_type newsz = d_cplength - len;
02414 
02415                 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
02416                 setlen(newsz);
02417                 return  *this;
02418         }
02419 
02430         String& erase(iterator pos)
02431         {
02432                 return erase(safe_iter_dif(pos, begin()), 1);
02433         }
02434 
02448         String& erase(iterator beg, iterator end)
02449         {
02450                 return erase(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg));
02451         }
02452 
02454         // Resizing
02456 
02468         void    resize(size_type num)
02469         {
02470                 resize(num, utf32());
02471         }
02472 
02488         void    resize(size_type num, utf32 code_point)
02489         {
02490                 if (num < d_cplength)
02491                 {
02492                         setlen(num);
02493                 }
02494                 else
02495                 {
02496                         append(num - d_cplength, code_point);
02497                 }
02498 
02499         }
02500 
02502         // Replacing Characters
02504 
02523         String& replace(size_type idx, size_type len, const String& str)
02524         {
02525                 return replace(idx, len, str, 0, npos);
02526         }
02527 
02549         String& replace(iterator beg, iterator end, const String& str)
02550         {
02551                 return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), str, 0, npos);
02552         }
02553 
02579         String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
02580         {
02581                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
02582                         throw std::out_of_range("Index is out of range for CEGUI::String");
02583 
02584                 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
02585                         str_num = str.d_cplength - str_idx;
02586 
02587                 if (((len + idx) > d_cplength) || (len == npos))
02588                         len = d_cplength - idx;
02589 
02590                 size_type newsz = d_cplength + str_num - len;
02591 
02592                 grow(newsz);
02593 
02594                 if ((idx + len) < d_cplength)
02595                         memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02596 
02597                 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
02598                 setlen(newsz);
02599 
02600                 return *this;
02601         }
02602 
02603 
02627         String& replace(size_type idx, size_type len, const std::string& std_str)
02628         {
02629                 return replace(idx, len, std_str, 0, npos);
02630         }
02631 
02657         String& replace(iterator beg, iterator end, const std::string& std_str)
02658         {
02659                 return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), std_str, 0, npos);
02660         }
02661 
02691         String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
02692         {
02693                 if (d_cplength < idx)
02694                         throw std::out_of_range("Index is out of range for CEGUI::String");
02695 
02696                 if (std_str.size() < str_idx)
02697                         throw std::out_of_range("Index is out of range for std::string");
02698 
02699                 if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
02700                         str_num = (size_type)std_str.size() - str_idx;
02701 
02702                 if (((len + idx) > d_cplength) || (len == npos))
02703                         len = d_cplength - idx;
02704 
02705                 size_type newsz = d_cplength + str_num - len;
02706 
02707                 grow(newsz);
02708 
02709                 if ((idx + len) < d_cplength)
02710                         memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02711 
02712                 utf32* pt = &ptr()[idx + str_num - 1];
02713 
02714                 while (str_num--)
02715                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
02716 
02717                 setlen(newsz);
02718 
02719                 return *this;
02720         }
02721 
02722 
02748         String& replace(size_type idx, size_type len, const utf8* utf8_str)
02749         {
02750                 return replace(idx, len, utf8_str, utf_length(utf8_str));
02751         }
02752 
02780         String& replace(iterator beg, iterator end, const utf8* utf8_str)
02781         {
02782                 return replace(beg, end, utf8_str, utf_length(utf8_str));
02783         }
02784 
02813         String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
02814         {
02815                 if (d_cplength < idx)
02816                         throw std::out_of_range("Index is out of range for CEGUI::String");
02817 
02818                 if (str_len == npos)
02819                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
02820 
02821                 if (((len + idx) > d_cplength) || (len == npos))
02822                         len = d_cplength - idx;
02823 
02824                 size_type encsz = encoded_size(utf8_str, str_len);
02825                 size_type newsz = d_cplength + encsz - len;
02826 
02827                 grow(newsz);
02828 
02829                 if ((idx + len) < d_cplength)
02830                         memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02831 
02832                 encode(utf8_str, &ptr()[idx], encsz, str_len);
02833 
02834                 setlen(newsz);
02835                 return *this;
02836         }
02837 
02868         String& replace(iterator beg, iterator end, const utf8* utf8_str, size_type str_len)
02869         {
02870                 return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), utf8_str, str_len);
02871         }
02872 
02895         String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
02896         {
02897                 if (d_cplength < idx)
02898                         throw std::out_of_range("Index is out of range for CEGUI::String");
02899 
02900                 if (num == npos)
02901                         throw std::length_error("Code point count can not be 'npos'");
02902 
02903                 if (((len + idx) > d_cplength) || (len == npos))
02904                         len = d_cplength - idx;
02905 
02906                 size_type newsz = d_cplength + num - len;
02907 
02908                 grow(newsz);
02909 
02910                 if ((idx + len) < d_cplength)
02911                         memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02912 
02913                 utf32* pt = &ptr()[idx + num - 1];
02914 
02915                 while (num--)
02916                         *pt-- = code_point;
02917 
02918                 setlen(newsz);
02919 
02920                 return *this;
02921         }
02922 
02947         String& replace(iterator beg, iterator end, size_type num, utf32 code_point)
02948         {
02949                 return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), num, code_point);
02950         }
02951 
02952 
02977         String& replace(iterator beg, iterator end, const_iterator newBeg, const_iterator newEnd)
02978         {
02979                 if (beg == end)
02980                 {
02981                         erase(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg));
02982                 }
02983                 else
02984                 {
02985                         size_type str_len = safe_iter_dif(newEnd, newBeg);
02986                         size_type idx = safe_iter_dif(beg, begin());
02987                         size_type len = safe_iter_dif(end, beg);
02988 
02989                         if ((len + idx) > d_cplength)
02990                                 len = d_cplength - idx;
02991 
02992                         size_type newsz = d_cplength + str_len - len;
02993 
02994                         grow(newsz);
02995 
02996                         if ((idx + len) < d_cplength)
02997                                 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
02998 
02999                         memcpy(&ptr()[idx], newBeg.d_ptr, str_len * sizeof(utf32));
03000                         setlen(newsz);
03001                 }
03002 
03003                 return *this;
03004         }
03005 
03006 
03026         String& replace(size_type idx, size_type len, const char* c_str)
03027         {
03028                 return replace(idx, len, c_str, strlen(c_str));
03029         }
03030 
03031 
03053         String& replace(iterator beg, iterator end, const char* c_str)
03054         {
03055                 return replace(beg, end, c_str, strlen(c_str));
03056         }
03057 
03058 
03081         String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
03082         {
03083                 if (d_cplength < idx)
03084                         throw std::out_of_range("Index is out of range for CEGUI::String");
03085 
03086                 if (chars_len == npos)
03087                         throw std::length_error("Length for the char array can not be 'npos'");
03088 
03089                 if (((len + idx) > d_cplength) || (len == npos))
03090                         len = d_cplength - idx;
03091 
03092                 size_type newsz = d_cplength + chars_len - len;
03093 
03094                 grow(newsz);
03095 
03096                 if ((idx + len) < d_cplength)
03097                         memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
03098 
03099                 utf32* pt = &ptr()[idx + chars_len - 1];
03100 
03101                 while (chars_len--)
03102                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
03103 
03104                 setlen(newsz);
03105                 return *this;
03106         }
03107 
03108 
03133         String& replace(iterator beg, iterator end, const char* chars, size_type chars_len)
03134         {
03135                 return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), chars, chars_len);
03136         }
03137 
03138 
03140         // Find a code point
03142 
03156         size_type       find(utf32 code_point, size_type idx = 0) const
03157         {
03158                 if (idx < d_cplength)
03159                 {
03160                         const utf32* pt = &ptr()[idx];
03161 
03162                         while (idx < d_cplength)
03163                         {
03164                                 if (*pt++ == code_point)
03165                                         return idx;
03166 
03167                                 ++idx;
03168                         }
03169 
03170                 }
03171 
03172                 return npos;
03173         }
03174 
03189         size_type       rfind(utf32 code_point, size_type idx = npos) const
03190         {
03191                 if (idx >= d_cplength)
03192                         idx = d_cplength - 1;
03193 
03194                 if (d_cplength > 0)
03195                 {
03196                         const utf32* pt = &ptr()[idx];
03197 
03198                         do
03199                         {
03200                                 if (*pt-- == code_point)
03201                                         return idx;
03202 
03203                         } while (idx-- != 0);
03204 
03205                 }
03206 
03207                 return npos;
03208         }
03209 
03211         // Find a substring
03213 
03227         size_type       find(const String& str, size_type idx = 0) const
03228         {
03229                 if ((str.d_cplength == 0) && (idx < d_cplength))
03230                         return idx;
03231 
03232                 if (idx < d_cplength)
03233                 {
03234                         // loop while search string could fit in to search area
03235                         while (d_cplength - idx >= str.d_cplength)
03236                         {
03237                                 if (0 == compare(idx, str.d_cplength, str))
03238                                         return idx;
03239 
03240                                 ++idx;
03241                         }
03242 
03243                 }
03244 
03245                 return npos;
03246         }
03247 
03262         size_type       rfind(const String& str, size_type idx = npos) const
03263         {
03264                 if (str.d_cplength == 0)
03265                         return (idx < d_cplength) ? idx : d_cplength;
03266 
03267                 if (str.d_cplength <= d_cplength)
03268                 {
03269                         if (idx > (d_cplength - str.d_cplength))
03270                                 idx = d_cplength - str.d_cplength;
03271 
03272                         do
03273                         {
03274                                 if (0 == compare(idx, str.d_cplength, str))
03275                                         return idx;
03276 
03277                         } while (idx-- != 0);
03278 
03279                 }
03280 
03281                 return npos;
03282         }
03283 
03302         size_type       find(const std::string& std_str, size_type idx = 0) const
03303         {
03304                 std::string::size_type sze = std_str.size();
03305 
03306                 if ((sze == 0) && (idx < d_cplength))
03307                         return idx;
03308 
03309                 if (idx < d_cplength)
03310                 {
03311                         // loop while search string could fit in to search area
03312                         while (d_cplength - idx >= sze)
03313                         {
03314                                 if (0 == compare(idx, (size_type)sze, std_str))
03315                                         return idx;
03316 
03317                                 ++idx;
03318                         }
03319 
03320                 }
03321 
03322                 return npos;
03323         }
03324 
03343         size_type       rfind(const std::string& std_str, size_type idx = npos) const
03344         {
03345                 std::string::size_type sze = std_str.size();
03346 
03347                 if (sze == 0)
03348                         return (idx < d_cplength) ? idx : d_cplength;
03349 
03350                 if (sze <= d_cplength)
03351                 {
03352                         if (idx > (d_cplength - sze))
03353                                 idx = d_cplength - sze;
03354 
03355                         do
03356                         {
03357                                 if (0 == compare(idx, (size_type)sze, std_str))
03358                                         return idx;
03359 
03360                         } while (idx-- != 0);
03361 
03362                 }
03363 
03364                 return npos;
03365         }
03366 
03389         size_type       find(const utf8* utf8_str, size_type idx = 0) const
03390         {
03391                 return find(utf8_str, idx, utf_length(utf8_str));
03392         }
03393 
03416         size_type       rfind(const utf8* utf8_str, size_type idx = npos) const
03417         {
03418                 return rfind(utf8_str, idx, utf_length(utf8_str));
03419         }
03420 
03446         size_type       find(const utf8* utf8_str, size_type idx, size_type str_len) const
03447         {
03448                 if (str_len == npos)
03449                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03450 
03451                 size_type sze = encoded_size(utf8_str, str_len);
03452 
03453                 if ((sze == 0) && (idx < d_cplength))
03454                         return idx;
03455 
03456                 if (idx < d_cplength)
03457                 {
03458                         // loop while search string could fit in to search area
03459                         while (d_cplength - idx >= sze)
03460                         {
03461                                 if (0 == compare(idx, sze, utf8_str, sze))
03462                                         return idx;
03463 
03464                                 ++idx;
03465                         }
03466 
03467                 }
03468 
03469                 return npos;
03470         }
03471 
03497         size_type       rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
03498         {
03499                 if (str_len == npos)
03500                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03501 
03502                 size_type sze = encoded_size(utf8_str, str_len);
03503 
03504                 if (sze == 0)
03505                         return (idx < d_cplength) ? idx : d_cplength;
03506 
03507                 if (sze <= d_cplength)
03508                 {
03509                         if (idx > (d_cplength - sze))
03510                                 idx = d_cplength - sze;
03511 
03512                         do
03513                         {
03514                                 if (0 == compare(idx, sze, utf8_str, sze))
03515                                         return idx;
03516 
03517                         } while (idx-- != 0);
03518 
03519                 }
03520 
03521                 return npos;
03522         }
03523 
03524 
03541         size_type       find(const char* c_str, size_type idx = 0) const
03542         {
03543                 return find(c_str, idx, strlen(c_str));
03544         }
03545 
03546 
03563         size_type       rfind(const char* c_str, size_type idx = npos) const
03564         {
03565                 return rfind(c_str, idx, strlen(c_str));
03566         }
03567 
03568 
03588         size_type       find(const char* chars, size_type idx, size_type chars_len) const
03589         {
03590                 if (chars_len == npos)
03591                         throw std::length_error("Length for char array can not be 'npos'");
03592 
03593                 if ((chars_len == 0) && (idx < d_cplength))
03594                         return idx;
03595 
03596                 if (idx < d_cplength)
03597                 {
03598                         // loop while search string could fit in to search area
03599                         while (d_cplength - idx >= chars_len)
03600                         {
03601                                 if (0 == compare(idx, chars_len, chars, chars_len))
03602                                         return idx;
03603 
03604                                 ++idx;
03605                         }
03606 
03607                 }
03608 
03609                 return npos;
03610         }
03611 
03612 
03632         size_type       rfind(const char* chars, size_type idx, size_type chars_len) const
03633         {
03634                 if (chars_len == npos)
03635                         throw std::length_error("Length for char array can not be 'npos'");
03636 
03637                 if (chars_len == 0)
03638                         return (idx < d_cplength) ? idx : d_cplength;
03639 
03640                 if (chars_len <= d_cplength)
03641                 {
03642                         if (idx > (d_cplength - chars_len))
03643                                 idx = d_cplength - chars_len;
03644 
03645                         do
03646                         {
03647                                 if (0 == compare(idx, chars_len, chars, chars_len))
03648                                         return idx;
03649 
03650                         } while (idx-- != 0);
03651 
03652                 }
03653 
03654                 return npos;
03655         }
03656 
03657 
03659         // Find first of different code-points
03661 
03675         size_type       find_first_of(const String& str, size_type idx = 0) const
03676         {
03677                 if (idx < d_cplength)
03678                 {
03679                         const utf32* pt = &ptr()[idx];
03680 
03681                         do
03682                         {
03683                                 if (npos != str.find(*pt++))
03684                                         return idx;
03685 
03686                         } while (++idx != d_cplength);
03687 
03688                 }
03689 
03690                 return npos;
03691         }
03692 
03707         size_type       find_first_not_of(const String& str, size_type idx = 0) const
03708         {
03709                 if (idx < d_cplength)
03710                 {
03711                         const utf32* pt = &ptr()[idx];
03712 
03713                         do
03714                         {
03715                                 if (npos == str.find(*pt++))
03716                                         return idx;
03717 
03718                         } while (++idx != d_cplength);
03719 
03720                 }
03721 
03722                 return npos;
03723         }
03724 
03725 
03744         size_type       find_first_of(const std::string& std_str, size_type idx = 0) const
03745         {
03746                 if (idx < d_cplength)
03747                 {
03748                         const utf32* pt = &ptr()[idx];
03749 
03750                         do
03751                         {
03752                                 if (npos != find_codepoint(std_str, *pt++))
03753                                         return idx;
03754 
03755                         } while (++idx != d_cplength);
03756 
03757                 }
03758 
03759                 return npos;
03760         }
03761 
03780         size_type       find_first_not_of(const std::string& std_str, size_type idx = 0) const
03781         {
03782                 if (idx < d_cplength)
03783                 {
03784                         const utf32* pt = &ptr()[idx];
03785 
03786                         do
03787                         {
03788                                 if (npos == find_codepoint(std_str, *pt++))
03789                                         return idx;
03790 
03791                         } while (++idx != d_cplength);
03792 
03793                 }
03794 
03795                 return npos;
03796         }
03797 
03798 
03821         size_type       find_first_of(const utf8* utf8_str, size_type idx = 0) const
03822         {
03823                 return find_first_of(utf8_str, idx, utf_length(utf8_str));
03824         }
03825 
03848         size_type       find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
03849         {
03850                 return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
03851         }
03852 
03878         size_type       find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03879         {
03880                 if (str_len == npos)
03881                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03882 
03883                 if (idx < d_cplength)
03884                 {
03885                         size_type encsze = encoded_size(utf8_str, str_len);
03886 
03887                         const utf32* pt = &ptr()[idx];
03888 
03889                         do
03890                         {
03891                                 if (npos != find_codepoint(utf8_str, encsze, *pt++))
03892                                         return idx;
03893 
03894                         } while (++idx != d_cplength);
03895 
03896                 }
03897 
03898                 return npos;
03899         }
03900 
03926         size_type       find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
03927         {
03928                 if (str_len == npos)
03929                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
03930 
03931                 if (idx < d_cplength)
03932                 {
03933                         size_type encsze = encoded_size(utf8_str, str_len);
03934 
03935                         const utf32* pt = &ptr()[idx];
03936 
03937                         do
03938                         {
03939                                 if (npos == find_codepoint(utf8_str, encsze, *pt++))
03940                                         return idx;
03941 
03942                         } while (++idx != d_cplength);
03943 
03944                 }
03945 
03946                 return npos;
03947         }
03948 
03949 
03964         size_type       find_first_of(utf32 code_point, size_type idx = 0) const
03965         {
03966                 return find(code_point, idx);
03967         }
03968 
03985         size_type       find_first_not_of(utf32 code_point, size_type idx = 0) const
03986         {
03987                 if (idx < d_cplength)
03988                 {
03989                         do
03990                         {
03991                                 if ((*this)[idx] != code_point)
03992                                         return idx;
03993 
03994                         } while(idx++ < d_cplength);
03995 
03996                 }
03997 
03998                 return npos;
03999         }
04000 
04001 
04018         size_type       find_first_of(const char* c_str, size_type idx = 0) const
04019         {
04020                 return find_first_of(c_str, idx, strlen(c_str));
04021         }
04022 
04023 
04040         size_type       find_first_not_of(const char* c_str, size_type idx = 0) const
04041         {
04042                 return find_first_not_of(c_str, idx, strlen(c_str));
04043         }
04044 
04045 
04065         size_type       find_first_of(const char* chars, size_type idx, size_type chars_len) const
04066         {
04067                 if (chars_len == npos)
04068                         throw std::length_error("Length for char array can not be 'npos'");
04069 
04070                 if (idx < d_cplength)
04071                 {
04072                         const utf32* pt = &ptr()[idx];
04073 
04074                         do
04075                         {
04076                                 if (npos != find_codepoint(chars, chars_len, *pt++))
04077                                         return idx;
04078 
04079                         } while (++idx != d_cplength);
04080 
04081                 }
04082 
04083                 return npos;
04084         }
04085 
04086 
04106         size_type       find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
04107         {
04108                 if (chars_len == npos)
04109                         throw std::length_error("Length for char array can not be 'npos'");
04110 
04111                 if (idx < d_cplength)
04112                 {
04113                         const utf32* pt = &ptr()[idx];
04114 
04115                         do
04116                         {
04117                                 if (npos == find_codepoint(chars, chars_len, *pt++))
04118                                         return idx;
04119 
04120                         } while (++idx != d_cplength);
04121 
04122                 }
04123 
04124                 return npos;
04125         }
04126 
04127 
04129         // Find last of different code-points
04131 
04145         size_type       find_last_of(const String& str, size_type idx = npos) const
04146         {
04147                 if (d_cplength > 0)
04148                 {
04149                         if (idx >= d_cplength)
04150                                 idx = d_cplength - 1;
04151 
04152                         const utf32* pt = &ptr()[idx];
04153 
04154                         do
04155                         {
04156                                 if (npos != str.find(*pt--))
04157                                         return idx;
04158 
04159                         } while (idx-- != 0);
04160 
04161                 }
04162 
04163                 return npos;
04164         }
04165 
04180         size_type       find_last_not_of(const String& str, size_type idx = npos) const
04181         {
04182                 if (d_cplength > 0)
04183                 {
04184                         if (idx >= d_cplength)
04185                                 idx = d_cplength - 1;
04186 
04187                         const utf32* pt = &ptr()[idx];
04188 
04189                         do
04190                         {
04191                                 if (npos == str.find(*pt--))
04192                                         return idx;
04193 
04194                         } while (idx-- != 0);
04195 
04196                 }
04197 
04198                 return npos;
04199         }
04200 
04201 
04220         size_type       find_last_of(const std::string& std_str, size_type idx = npos) const
04221         {
04222                 if (d_cplength > 0)
04223                 {
04224                         if (idx >= d_cplength)
04225                                 idx = d_cplength - 1;
04226 
04227                         const utf32* pt = &ptr()[idx];
04228 
04229                         do
04230                         {
04231                                 if (npos != find_codepoint(std_str, *pt--))
04232                                         return idx;
04233 
04234                         } while (idx-- != 0);
04235 
04236                 }
04237 
04238                 return npos;
04239         }
04240 
04259         size_type       find_last_not_of(const std::string& std_str, size_type idx = npos) const
04260         {
04261                 if (d_cplength > 0)
04262                 {
04263                         if (idx >= d_cplength)
04264                                 idx = d_cplength - 1;
04265 
04266                         const utf32* pt = &ptr()[idx];
04267 
04268                         do
04269                         {
04270                                 if (npos == find_codepoint(std_str, *pt--))
04271                                         return idx;
04272 
04273                         } while (idx-- != 0);
04274 
04275                 }
04276 
04277                 return npos;
04278         }
04279 
04280 
04303         size_type       find_last_of(const utf8* utf8_str, size_type idx = npos) const
04304         {
04305                 return find_last_of(utf8_str, idx, utf_length(utf8_str));
04306         }
04307 
04330         size_type       find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
04331         {
04332                 return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
04333         }
04334 
04360         size_type       find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04361         {
04362                 if (str_len == npos)
04363                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
04364 
04365                 if (d_cplength > 0)
04366                 {
04367                         if (idx >= d_cplength)
04368                                 idx = d_cplength - 1;
04369 
04370                         size_type encsze = encoded_size(utf8_str, str_len);
04371 
04372                         const utf32* pt = &ptr()[idx];
04373 
04374                         do
04375                         {
04376                                 if (npos != find_codepoint(utf8_str, encsze, *pt--))
04377                                         return idx;
04378 
04379                         } while (idx-- != 0);
04380 
04381                 }
04382 
04383                 return npos;
04384         }
04385 
04411         size_type       find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
04412         {
04413                 if (str_len == npos)
04414                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
04415 
04416                 if (d_cplength > 0)
04417                 {
04418                         if (idx >= d_cplength)
04419                                 idx = d_cplength - 1;
04420 
04421                         size_type encsze = encoded_size(utf8_str, str_len);
04422 
04423                         const utf32* pt = &ptr()[idx];
04424 
04425                         do
04426                         {
04427                                 if (npos == find_codepoint(utf8_str, encsze, *pt--))
04428                                         return idx;
04429 
04430                         } while (idx-- != 0);
04431 
04432                 }
04433 
04434                 return npos;
04435         }
04436 
04437 
04452         size_type       find_last_of(utf32 code_point, size_type idx = npos) const
04453         {
04454                 return rfind(code_point, idx);
04455         }
04456 
04471         size_type       find_last_not_of(utf32 code_point, size_type idx = npos) const
04472         {
04473                 if (d_cplength > 0)
04474                 {
04475                         if (idx >= d_cplength)
04476                                 idx = d_cplength - 1;
04477 
04478                         do
04479                         {
04480                                 if ((*this)[idx] != code_point)
04481                                         return idx;
04482 
04483                         } while(idx-- != 0);
04484 
04485                 }
04486 
04487                 return npos;
04488         }
04489 
04490 
04507         size_type       find_last_of(const char* c_str, size_type idx = npos) const
04508         {
04509                 return find_last_of(c_str, idx, strlen(c_str));
04510         }
04511 
04512 
04529         size_type       find_last_not_of(const char* c_str, size_type idx = npos) const
04530         {
04531                 return find_last_not_of(c_str, idx, strlen(c_str));
04532         }
04533 
04534 
04554         size_type       find_last_of(const char* chars, size_type idx, size_type chars_len) const
04555         {
04556                 if (chars_len == npos)
04557                         throw std::length_error("Length for char array can not be 'npos'");
04558 
04559                 if (d_cplength > 0)
04560                 {
04561                         if (idx >= d_cplength)
04562                                 idx = d_cplength - 1;
04563 
04564                         const utf32* pt = &ptr()[idx];
04565 
04566                         do
04567                         {
04568                                 if (npos != find_codepoint(chars, chars_len, *pt--))
04569                                         return idx;
04570 
04571                         } while (idx-- != 0);
04572 
04573                 }
04574 
04575                 return npos;
04576         }
04577 
04578 
04598         size_type       find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
04599         {
04600                 if (chars_len == npos)
04601                         throw std::length_error("Length for char array can not be 'npos'");
04602 
04603                 if (d_cplength > 0)
04604                 {
04605                         if (idx >= d_cplength)
04606                                 idx = d_cplength - 1;
04607 
04608                         const utf32* pt = &ptr()[idx];
04609 
04610                         do
04611                         {
04612                                 if (npos == find_codepoint(chars, chars_len, *pt--))
04613                                         return idx;
04614 
04615                         } while (idx-- != 0);
04616 
04617                 }
04618 
04619                 return npos;
04620         }
04621 
04622 
04624         // Substring
04626 
04641         String  substr(size_type idx = 0, size_type len = npos) const
04642         {
04643                 if (d_cplength < idx)
04644                         throw std::out_of_range("Index is out of range for this CEGUI::String");
04645 
04646                 return String(*this, idx, len);
04647         }
04648 
04650         // Iterator creation
04652 
04659         iterator                begin(void)
04660         {
04661                 return iterator(ptr());
04662         }
04663 
04671         const_iterator  begin(void) const
04672         {
04673                 return const_iterator(ptr());
04674         }
04675 
04683         iterator                end(void)
04684         {
04685                 return iterator(&ptr()[d_cplength]);
04686         }
04687 
04695         const_iterator  end(void) const
04696         {
04697                 return const_iterator(&ptr()[d_cplength]);
04698         }
04699 
04707         reverse_iterator                rbegin(void)
04708         {
04709                 return reverse_iterator(end());
04710         }
04711 
04719         const_reverse_iterator  rbegin(void) const
04720         {
04721                 return const_reverse_iterator(end());
04722         }
04723 
04731         reverse_iterator                rend(void)
04732         {
04733                 return reverse_iterator(begin());
04734         }
04735 
04743         const_reverse_iterator  rend(void) const
04744         {
04745                 return const_reverse_iterator(begin());
04746         }
04747 
04748 private:
04749         /*************************************************************************
04750                 Implementation Functions
04751         *************************************************************************/
04752         // string management
04753 
04754         // change size of allocated buffer so it is at least 'new_size'.
04755         // May or may not cause re-allocation and copy of buffer if size is larger
04756         // will never re-allocate to make size smaller.  (see trim())
04757         bool    grow(size_type new_size)
04758         {
04759                 // check for too big
04760                 if (max_size() <= new_size)
04761                         std::length_error("Resulting CEGUI::String would be too big");
04762 
04763                 // increase, as we always null-terminate the buffer.
04764                 ++new_size;
04765 
04766                 if (new_size > d_reserve)
04767                 {
04768                         utf32* temp = new utf32[new_size];
04769 
04770                         if (d_reserve > STR_QUICKBUFF_SIZE)
04771                         {
04772                                 memcpy(temp, d_buffer, (d_cplength + 1) * sizeof(utf32));
04773                                 delete[] d_buffer;
04774                         }
04775                         else
04776                         {
04777                                 memcpy(temp, d_quickbuff, (d_cplength + 1) * sizeof(utf32));
04778                         }
04779 
04780                         d_buffer = temp;
04781                         d_reserve = new_size;
04782 
04783                         return true;
04784                 }
04785 
04786                 return false;
04787         }
04788 
04789         // perform re-allocation to remove wasted space.
04790         void    trim(void)
04791         {
04792                 size_type min_size = d_cplength + 1;
04793 
04794                 // only re-allocate when not using quick-buffer, and when size can be trimmed
04795                 if ((d_reserve > STR_QUICKBUFF_SIZE) && (d_reserve > min_size))
04796                 {
04797                         // see if we can trim to quick-buffer
04798                         if (min_size <= STR_QUICKBUFF_SIZE)
04799                         {
04800                                 memcpy(d_quickbuff, d_buffer, min_size * sizeof(utf32));
04801                                 delete d_buffer;
04802                                 d_reserve = STR_QUICKBUFF_SIZE;
04803                         }
04804                         // re-allocate buffer
04805                         else
04806                         {
04807                                 utf32* temp = new utf32[min_size];
04808                                 memcpy(temp, d_buffer, min_size * sizeof(utf32));
04809                                 delete d_buffer;
04810                                 d_buffer = temp;
04811                                 d_reserve = min_size;
04812                         }
04813 
04814                 }
04815 
04816         }
04817 
04818         // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
04819         void    setlen(size_type len)
04820         {
04821                 d_cplength = len;
04822                 ptr()[len] = (utf32)(0);
04823         }
04824 
04825         // return a ptr to the buffer in use.
04826         utf32*  ptr(void)
04827         {
04828                 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
04829         }
04830 
04831         // return a ptr tot he buffer in use (const version)
04832         const utf32*    ptr(void) const
04833         {
04834                 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
04835         }
04836 
04837         // initialise string object
04838         void    init(void)
04839         {
04840                 d_reserve                       = STR_QUICKBUFF_SIZE;
04841                 d_encodedbuff           = NULL;
04842                 d_encodedbufflen        = 0;
04843                 d_encodeddatlen         = 0;
04844                 setlen(0);
04845         }
04846 
04847         // return true if the given pointer is inside the string data
04848         bool    inside(utf32* inptr)
04849         {
04850                 if (inptr < ptr() || ptr() + d_cplength <= inptr)
04851                         return false;
04852                 else
04853                         return true;
04854         }
04855 
04856         // compute distance between two iterators, returning a 'safe' value
04857         size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
04858         {
04859                 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
04860         }
04861         
04862         // encoding functions
04863         // for all:
04864         //      src_len is in code units, or 0 for null terminated string.
04865         //      dest_len is in code units.
04866         //      returns number of code units put into dest buffer.
04867         size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
04868         {
04869                 // count length for null terminated source...
04870                 if (src_len == 0)
04871                 {
04872                         src_len = utf_length(src);
04873                 }
04874 
04875                 size_type destCapacity = dest_len;
04876 
04877                 // while there is data in the source buffer,
04878                 for (uint idx = 0; idx < src_len; ++idx)
04879                 {
04880                         utf32   cp = src[idx];
04881 
04882                         // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
04883                         if (destCapacity < encoded_size(cp))
04884                         {
04885                                 break;
04886                         }
04887 
04888                         if (cp < 0x80)
04889                         {
04890                                 *dest++ = (utf8)cp;
04891                                 --destCapacity;
04892                         }
04893                         else if (cp < 0x0800)
04894                         {
04895                                 *dest++ = (utf8)((cp >> 6) | 0xC0);
04896                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04897                                 destCapacity -= 2;
04898                         }
04899                         else if (cp < 0x10000)
04900                         {
04901                                 *dest++ = (utf8)((cp >> 12) | 0xE0);
04902                                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04903                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04904                                 destCapacity -= 3;
04905                         }
04906                         else
04907                         {
04908                                 *dest++ = (utf8)((cp >> 18) | 0xF0);
04909                                 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
04910                                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
04911                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
04912                                 destCapacity -= 4;
04913                         }
04914 
04915                 }
04916 
04917                 return dest_len - destCapacity;
04918         }
04919 
04920         size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
04921         {
04922                 // count length for null terminated source...
04923                 if (src_len == 0)
04924                 {
04925                         src_len = utf_length(src);
04926                 }
04927 
04928                 size_type destCapacity = dest_len;
04929 
04930                 // while there is data in the source buffer, and space in the dest buffer
04931                 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
04932                 {
04933                         utf32   cp;
04934                         utf8    cu = src[idx++];
04935 
04936                         if (cu < 0x80)
04937                         {
04938                                 cp = (utf32)(cu);
04939                         }
04940                         else if (cu < 0xE0)
04941                         {
04942                                 cp = ((cu & 0x1F) << 6);
04943                                 cp |= (src[idx++] & 0x3F);
04944                         }
04945                         else if (cu < 0xF0)
04946                         {
04947                                 cp = ((cu & 0x0F) << 12);
04948                                 cp |= ((src[idx++] & 0x3F) << 6);
04949                                 cp |= (src[idx++] & 0x3F);
04950                         }
04951                         else
04952                         {
04953                                 cp = ((cu & 0x07) << 18);
04954                                 cp |= ((src[idx++] & 0x3F) << 12);
04955                                 cp |= ((src[idx++] & 0x3F) << 6);
04956                                 cp |= (src[idx++] & 0x3F);
04957                         }
04958 
04959                         *dest++ = cp;
04960                         --destCapacity;
04961                 }
04962 
04963                 return dest_len - destCapacity;
04964         }
04965 
04966         // return the number of utf8 code units required to encode the given utf32 code point
04967         size_type encoded_size(utf32 code_point) const
04968         {
04969                 if (code_point < 0x80)
04970                         return 1;
04971                 else if (code_point < 0x0800)
04972                         return 2;
04973                 else if (code_point < 0x10000)
04974                         return 3;
04975                 else
04976                         return 4;
04977         }
04978 
04979         // return number of code units required to re-encode given null-terminated utf32 data as utf8.  return does not include terminating null.
04980         size_type encoded_size(const utf32* buf) const
04981         {
04982                 return encoded_size(buf, utf_length(buf));
04983         }
04984 
04985         // return number of code units required to re-encode given utf32 data as utf8.   len is number of code units in 'buf'.
04986         size_type encoded_size(const utf32* buf, size_type len) const
04987         {
04988                 size_type count = 0;
04989 
04990                 while (len--)
04991                 {
04992                         count += encoded_size(*buf++);
04993                 }
04994 
04995                 return count;
04996         }
04997 
04998         // return number of utf32 code units required to re-encode given utf8 data as utf32.  return does not include terminating null.
04999         size_type encoded_size(const utf8* buf) const
05000         {
05001                 return encoded_size(buf, utf_length(buf));
05002         }
05003 
05004         // return number of utf32 code units required to re-encode given utf8 data as utf32.  len is number of code units in 'buf'.
05005         size_type encoded_size(const utf8* buf, size_type len) const
05006         {
05007                 utf8 tcp;
05008                 size_type count = 0;
05009 
05010                 while (len--)
05011                 {
05012                         tcp = *buf++;
05013                         ++count;
05014 
05015                         if (tcp < 0x80)
05016                         {
05017                         }
05018                         else if (tcp < 0xE0)
05019                         {
05020                                 --len;
05021                                 ++buf;
05022                         }
05023                         else if (tcp < 0xF0)
05024                         {
05025                                 len -= 2;
05026                                 buf += 2;
05027                         }
05028                         else
05029                         {
05030                                 len -= 2;
05031                                 buf += 3;
05032                         }
05033 
05034                 }
05035 
05036                 return count;
05037         }
05038 
05039         // return number of code units in a null terminated string
05040         size_type utf_length(const utf8* utf8_str) const
05041         {
05042                 size_type cnt = 0;
05043                 while (*utf8_str++)
05044                         cnt++;
05045 
05046                 return cnt;
05047         }
05048 
05049         // return number of code units in a null terminated string
05050         size_type utf_length(const utf32* utf32_str) const
05051         {
05052                 size_type cnt = 0;
05053                 while (*utf32_str++)
05054                         cnt++;
05055 
05056                 return cnt;
05057         }
05058 
05059         // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
05060         utf8* build_utf8_buff(void) const
05061         {
05062                 size_type buffsize = encoded_size(ptr(), d_cplength) + 1;
05063 
05064                 if (buffsize > d_encodedbufflen) {
05065 
05066                         if (d_encodedbufflen > 0)
05067                         {
05068                                 delete[] d_encodedbuff;
05069                         }
05070 
05071                         d_encodedbuff = new utf8[buffsize];
05072                         d_encodedbufflen = buffsize;
05073                 }
05074 
05075                 encode(ptr(), d_encodedbuff, buffsize, d_cplength);
05076 
05077                 // always add a null at end
05078                 d_encodedbuff[buffsize-1] = ((utf8)0);
05079 
05080                 d_encodeddatlen = buffsize;
05081 
05082                 return d_encodedbuff;
05083         }
05084 
05085         // compare two utf32 buffers
05086         int     utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
05087         {
05088                 if (!cp_count)
05089                         return 0;
05090 
05091                 while ((--cp_count) && (*buf1 == *buf2))
05092                         buf1++, buf2++;
05093                 
05094                 return *buf1 - *buf2;
05095         }
05096 
05097         // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
05098         int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
05099         {
05100                 if (!cp_count)
05101                         return 0;
05102 
05103                 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
05104                         buf1++, buf2++;
05105 
05106                 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
05107         }
05108 
05109         // compare utf32 buffer with encoded utf8 data
05110         int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
05111         {
05112                 if (!cp_count)
05113                         return 0;
05114 
05115                 utf32   cp;
05116                 utf8    cu;
05117 
05118                 do
05119                 {
05120                         cu = *buf2++;
05121 
05122                         if (cu < 0x80)
05123                         {
05124                                 cp = (utf32)(cu);
05125                         }
05126                         else if (cu < 0xE0)
05127                         {
05128                                 cp = ((cu & 0x1F) << 6);
05129                                 cp |= (*buf2++ & 0x3F);
05130                         }
05131                         else if (cu < 0xF0)
05132                         {
05133                                 cp = ((cu & 0x0F) << 12);
05134                                 cp |= ((*buf2++ & 0x3F) << 6);
05135                                 cp |= (*buf2++ & 0x3F);
05136                         }
05137                         else
05138                         {
05139                                 cp = ((cu & 0x07) << 18);
05140                                 cp |= ((*buf2++ & 0x3F) << 12);
05141                                 cp |= ((*buf2++ & 0x3F) << 6);
05142                                 cp |= (*buf2++ & 0x3F);
05143                         }
05144 
05145                 } while ((*buf1++ == cp) && (--cp_count));
05146 
05147                 return (*--buf1) - cp;
05148         }
05149 
05150         // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
05151         size_type find_codepoint(const std::string& str, utf32 code_point) const
05152         {
05153                 size_type idx = 0, sze = (size_type)str.size();
05154 
05155                 while (idx != sze)
05156                 {
05157                         if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
05158                                 return idx;
05159 
05160                         ++idx;
05161                 }
05162 
05163                 return npos;
05164         }
05165 
05166         // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none.  len is in code points.
05167         size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const 
05168         {
05169                 size_type idx = 0;
05170 
05171                 utf32   cp;
05172                 utf8    cu;
05173 
05174                 while (idx != len) {
05175                         cu = *str++;
05176 
05177                         if (cu < 0x80)
05178                         {
05179                                 cp = (utf32)(cu);
05180                         }
05181                         else if (cu < 0xE0)
05182                         {
05183                                 cp = ((cu & 0x1F) << 6);
05184                                 cp |= (*str++ & 0x3F);
05185                         }
05186                         else if (cu < 0xF0)
05187                         {
05188                                 cp = ((cu & 0x0F) << 12);
05189                                 cp |= ((*str++ & 0x3F) << 6);
05190                                 cp |= (*str++ & 0x3F);
05191                         }
05192                         else
05193                         {
05194                                 cp = ((cu & 0x07) << 18);
05195                                 cp |= ((*str++ & 0x3F) << 12);
05196                                 cp |= ((*str++ & 0x3F) << 6);
05197                                 cp |= (*str++ & 0x3F);
05198                         }
05199 
05200                         if (code_point == cp)
05201                                 return idx;
05202 
05203                         ++idx;
05204                 }
05205 
05206                 return npos;
05207         }
05208 
05209 
05210         // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
05211         size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
05212         {
05213                 for (size_type idx = 0; idx != chars_len; ++idx)
05214                 {
05215                         if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
05216                                 return idx;
05217                 }
05218 
05219                 return npos;
05220         }
05221 
05222 };
05223 
05224 
05226 // Comparison operators
05228 
05232 bool CEGUIBASE_API      operator==(const String& str1, const String& str2);
05233 
05238 bool CEGUIBASE_API      operator==(const String& str, const std::string& std_str);
05239 
05244 bool CEGUIBASE_API      operator==(const std::string& std_str, const String& str);
05245 
05250 bool CEGUIBASE_API      operator==(const String& str, const utf8* utf8_str);
05251 
05256 bool CEGUIBASE_API      operator==(const utf8* utf8_str, const String& str);
05257 
05262 bool CEGUIBASE_API      operator!=(const String& str1, const String& str2);
05263 
05268 bool CEGUIBASE_API      operator!=(const String& str, const std::string& std_str);
05269 
05274 bool CEGUIBASE_API      operator!=(const std::string& std_str, const String& str);
05275 
05280 bool CEGUIBASE_API      operator!=(const String& str, const utf8* utf8_str);
05281 
05286 bool CEGUIBASE_API      operator!=(const utf8* utf8_str, const String& str);
05287 
05292 bool CEGUIBASE_API      operator<(const String& str1, const String& str2);
05293 
05298 bool CEGUIBASE_API      operator<(const String& str, const std::string& std_str);
05299 
05304 bool CEGUIBASE_API      operator<(const std::string& std_str, const String& str);
05305 
05310 bool CEGUIBASE_API      operator<(const String& str, const utf8* utf8_str);
05311 
05316 bool CEGUIBASE_API      operator<(const utf8* utf8_str, const String& str);
05317 
05322 bool CEGUIBASE_API      operator>(const String& str1, const String& str2);
05323 
05328 bool CEGUIBASE_API      operator>(const String& str, const std::string& std_str);
05329 
05334 bool CEGUIBASE_API      operator>(const std::string& std_str, const String& str);
05335 
05340 bool CEGUIBASE_API      operator>(const String& str, const utf8* utf8_str);
05341 
05346 bool CEGUIBASE_API      operator>(const utf8* utf8_str, const String& str);
05347 
05352 bool CEGUIBASE_API      operator<=(const String& str1, const String& str2);
05353 
05358 bool CEGUIBASE_API      operator<=(const String& str, const std::string& std_str);
05359 
05364 bool CEGUIBASE_API      operator<=(const std::string& std_str, const String& str);
05365 
05370 bool CEGUIBASE_API      operator<=(const String& str, const utf8* utf8_str);
05371 
05376 bool CEGUIBASE_API      operator<=(const utf8* utf8_str, const String& str);
05377 
05382 bool CEGUIBASE_API      operator>=(const String& str1, const String& str2);
05383 
05388 bool CEGUIBASE_API      operator>=(const String& str, const std::string& std_str);
05389 
05394 bool CEGUIBASE_API      operator>=(const std::string& std_str, const String& str);
05395 
05400 bool CEGUIBASE_API      operator>=(const String& str, const utf8* utf8_str);
05401 
05406 bool CEGUIBASE_API      operator>=(const utf8* utf8_str, const String& str);
05407 
05412 bool CEGUIBASE_API      operator==(const String& str, const char* c_str);
05413 
05418 bool CEGUIBASE_API      operator==(const char* c_str, const String& str);
05419 
05424 bool CEGUIBASE_API      operator!=(const String& str, const char* c_str);
05425 
05430 bool CEGUIBASE_API      operator!=(const char* c_str, const String& str);
05431 
05436 bool CEGUIBASE_API      operator<(const String& str, const char* c_str);
05437 
05442 bool CEGUIBASE_API      operator<(const char* c_str, const String& str);
05443 
05448 bool CEGUIBASE_API      operator>(const String& str, const char* c_str);
05449 
05454 bool CEGUIBASE_API      operator>(const char* c_str, const String& str);
05455 
05460 bool CEGUIBASE_API      operator<=(const String& str, const char* c_str);
05461 
05466 bool CEGUIBASE_API      operator<=(const char* c_str, const String& str);
05467 
05472 bool CEGUIBASE_API      operator>=(const String& str, const char* c_str);
05473 
05478 bool CEGUIBASE_API      operator>=(const char* c_str, const String& str);
05479 
05481 // Concatenation operator functions
05483 
05498 String CEGUIBASE_API    operator+(const String str1, const String& str2);
05499 
05515 String CEGUIBASE_API    operator+(const String str, const std::string& std_str);
05516 
05532 String CEGUIBASE_API    operator+(const std::string& std_str, const String& str);
05533 
05549 String CEGUIBASE_API    operator+(const String str, const utf8* utf8_str);
05550 
05566 String CEGUIBASE_API    operator+(const utf8* utf8_str, const String& str);
05567 
05583 String CEGUIBASE_API    operator+(const String str, utf32 code_point);
05584 
05600 String CEGUIBASE_API    operator+(utf32 code_point, const String& str);
05601 
05617 String CEGUIBASE_API    operator+(const String str, const char* c_str);
05618 
05634 String CEGUIBASE_API    operator+(const char* c_str, const String& str);
05635 
05636 
05638 // Output (stream) functions
05640 std::ostream& operator<<(std::ostream& s, const String& str);
05641 
05642 
05644 // Modifying operations
05646 
05659 void CEGUIBASE_API swap(String& str1, String& str2);
05660 
05661 
05662 } // End of  CEGUI namespace section
05663 
05664 
05665 #endif  // end of guard _CEGUIString_h_

Generated on Wed Feb 16 12:41:07 2005 for Crazy Eddies GUI System by  doxygen 1.3.9.1