# CEGUIString.h

    00001 /************************************************************************
    00002         filename:       CEGUIString.h
    00003         created:        26/2/2004
    00004         author:         Paul D Turner
    00005
    00006         purpose:        Defines string class used within the GUI system.
    00007 *************************************************************************/
    00008 /*************************************************************************
    00009     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         uint8   utf8;
    00042         //typedef               uint16  utf16;  // removed typedef to prevent usage, as utf16 is not supported (yet)
    00043         typedef         uint32  utf32;
    00044
    00053 class CEGUIEXPORT String
    00054 {
    00055 public:
    00056         /*************************************************************************
    00057                 Integral Types
    00058         *************************************************************************/
    00059         typedef         utf32                   value_type;
    00060         typedef         size_t                  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
    00367         // Construction via CEGUI::String
    00369
    00379         String(const String& str)
    00380         {
    00381                 init();
    00382                 assign(str);
    00383         }
    00384
    00385
    00402         String(const String& str, size_type str_idx, size_type str_num = npos)
    00403         {
    00404                 init();
    00405                 assign(str, str_idx, str_num);
    00406         }
    00407
    00409         // Construction via std::string
    00411
    00427         String(const std::string& std_str)
    00428         {
    00429                 init();
    00430                 assign(std_str);
    00431         }
    00432
    00455         String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
    00456         {
    00457                 init();
    00458                 assign(std_str, str_idx, str_num);
    00459         }
    00460
    00461
    00463         // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
    00465
    00483         String(const utf8* utf8_str)
    00484         {
    00485                 init();
    00486                 assign(utf8_str);
    00487         }
    00488
    00515         String(const utf8* utf8_str, size_type chars_len)
    00516         {
    00517                 init();
    00518                 assign(utf8_str, chars_len);
    00519         }
    00520
    00522         // Construction via code-point (using a UTF-32 code unit)
    00524
    00539         String(size_type num, utf32 code_point)
    00540         {
    00541                 init();
    00542                 assign(num, code_point);
    00543         }
    00544
    00546         // Construction via iterator
    00548         // Create string with characters in the range [beg, end)
    00562         String(const_iterator iter_beg, const_iterator iter_end)
    00563         {
    00564                 init();
    00565                 append(iter_beg, iter_end);
    00566         }
    00567
    00568
    00570         // Construction via c-string
    00572
    00584         String(const char* cstr)
    00585         {
    00586                 init();
    00587                 assign(cstr);
    00588         }
    00589
    00605         String(const char* chars, size_type chars_len)
    00606         {
    00607                 init();
    00608                 assign(chars, chars_len);
    00609         }
    00610
    00611
    00613         // Size operations
    00615
    00622         size_type       size(void) const
    00623         {
    00624                 return d_cplength;
    00625         }
    00626
    00634         size_type       length(void) const
    00635         {
    00636                 return d_cplength;
    00637         }
    00638
    00646         bool    empty(void) const
    00647         {
    00648                 return  (d_cplength == 0);
    00649         }
    00650
    00660         static size_type        max_size(void)
    00661         {
    00662                 return (((size_type)-1) / sizeof(utf32));
    00663         }
    00664
    00666         // Capacity Operations
    00668         // return the number of code points the string could hold without re-allocation
    00669         // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
    00678         size_type capacity(void) const
    00679         {
    00680                 return d_reserve - 1;
    00681         }
    00682
    00683         // reserve internal memory for at-least 'num' code-points (characters).  if num is 0, request is shrink-to-fit.
    00698         void    reserve(size_type num = 0)
    00699         {
    00700                 if (num == 0)
    00701                         trim();
    00702                 else
    00703                         grow(num);
    00704         }
    00705
    00707         // Comparisons
    00709
    00724         int             compare(const String& str) const
    00725         {
    00726                 return compare(0, d_cplength, str);
    00727         }
    00728
    00758         int             compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
    00759         {
    00760                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
    00761                         throw std::out_of_range("Index is out of range for CEGUI::String");
    00762
    00763                 if ((len == npos) || (idx + len > d_cplength))
    00764                         len = d_cplength - idx;
    00765
    00766                 if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
    00767                         str_len = str.d_cplength - str_idx;
    00768
    00769                 int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
    00770
    00771                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
    00772         }
    00773
    00774
    00794         int             compare(const std::string& std_str) const
    00795         {
    00796                 return compare(0, d_cplength, std_str);
    00797         }
    00798
    00799
    00833         int             compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
    00834         {
    00835                 if (d_cplength < idx)
    00836                         throw std::out_of_range("Index is out of range for CEGUI::String");
    00837
    00838                 if (std_str.size() < str_idx)
    00839                         throw std::out_of_range("Index is out of range for std::string");
    00840
    00841                 if ((len == npos) || (idx + len > d_cplength))
    00842                         len = d_cplength - idx;
    00843
    00844                 if ((str_len == npos) || (str_idx + str_len > std_str.size()))
    00845                         str_len = (size_type)std_str.size() - str_idx;
    00846
    00847                 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
    00848
    00849                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
    00850         }
    00851
    00852
    00874         int             compare(const utf8* utf8_str) const
    00875         {
    00876                 return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
    00877         }
    00878
    00879
    00909         int             compare(size_type idx, size_type len, const utf8* utf8_str) const
    00910         {
    00911                 return compare(idx, len, utf8_str, encoded_size(utf8_str));
    00912         }
    00913
    00947         int             compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
    00948         {
    00949                 if (d_cplength < idx)
    00950                         throw std::out_of_range("Index is out of range for CEGUI::String");
    00951
    00952                 if (str_cplen == npos)
    00953                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    00954
    00955                 if ((len == npos) || (idx + len > d_cplength))
    00956                         len = d_cplength - idx;
    00957
    00958                 int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
    00959
    00960                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
    00961         }
    00962
    00963
    00979         int             compare(const char* cstr) const
    00980         {
    00981                 return compare(0, d_cplength, cstr, strlen(cstr));
    00982         }
    00983
    00984
    01008         int             compare(size_type idx, size_type len, const char* cstr) const
    01009         {
    01010                 return compare(idx, len, cstr, strlen(cstr));
    01011         }
    01012
    01013
    01041         int             compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
    01042         {
    01043                 if (d_cplength < idx)
    01044                         throw std::out_of_range("Index is out of range for CEGUI::String");
    01045
    01046                 if (chars_len == npos)
    01047                         throw std::length_error("Length for char array can not be 'npos'");
    01048
    01049                 if ((len == npos) || (idx + len > d_cplength))
    01050                         len = d_cplength - idx;
    01051
    01052                 int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
    01053
    01054                 return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
    01055         }
    01056
    01057
    01059         // Character access
    01061
    01075         reference       operator[](size_type idx)
    01076         {
    01077                 return (ptr()[idx]);
    01078         }
    01079
    01094         value_type      operator[](size_type idx) const
    01095         {
    01096                 return ptr()[idx];
    01097         }
    01098
    01111         reference       at(size_type idx)
    01112         {
    01113                 if (d_cplength <= idx)
    01114                         throw std::out_of_range("Index is out of range for CEGUI::String");
    01115
    01116                 return ptr()[idx];
    01117         }
    01118
    01131         const_reference at(size_type idx) const
    01132         {
    01133                 if (d_cplength <= idx)
    01134                         throw std::out_of_range("Index is out of range for CEGUI::String");
    01135
    01136                 return ptr()[idx];
    01137         }
    01138
    01139
    01141         // C-Strings and arrays
    01143
    01156         const char* c_str(void) const
    01157         {
    01158                 return (const char*)build_utf8_buff();
    01159         }
    01160
    01174         const utf8* data(void) const
    01175         {
    01176                 return build_utf8_buff();
    01177         }
    01178
    01179         // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
    01180         // return number of utf8 code units placed into the buffer
    01201         size_type       copy(utf8* buf, size_type len = npos, size_type idx = 0) const
    01202         {
    01203                 if (d_cplength < idx)
    01204                         throw std::out_of_range("Index is out of range for CEGUI::String");
    01205
    01206                 if (len == npos)
    01207                         len = d_cplength;
    01208
    01209                 return encode(&ptr()[idx], buf, npos, len);
    01210         }
    01211
    01213         // UTF8 Encoding length information
    01215         // 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.
    01231         size_type       utf8_stream_len(size_type num = npos, size_type idx = 0)
    01232         {
    01233                 using namespace std;
    01234
    01235                 if (d_cplength < idx)
    01236                         throw out_of_range("Index was out of range for CEGUI::String object");
    01237
    01238                 size_type       maxlen = d_cplength - idx;
    01239
    01240                 return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
    01241         }
    01242
    01244         // Assignment Functions
    01246
    01256         String& operator=(const String& str)
    01257         {
    01258                 return assign(str);
    01259         }
    01260
    01279         String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
    01280         {
    01281                 if (str.d_cplength < str_idx)
    01282                         throw std::out_of_range("Index was out of range for CEGUI::String object");
    01283
    01284                 if (str_num == npos)
    01285                         str_num = str.d_cplength - str_idx;
    01286
    01287                 grow(str_num);
    01288                 setlen(str_num);
    01289                 memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
    01290
    01291                 return *this;
    01292         }
    01293
    01310         String& operator=(const std::string& std_str)
    01311         {
    01312                 return assign(std_str);
    01313         }
    01314
    01338         String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
    01339         {
    01340                 if (std_str.size() < str_idx)
    01341                         throw std::out_of_range("Index was out of range for std::string object");
    01342
    01343                 if (str_num == npos)
    01344                         str_num = (size_type)std_str.size() - str_idx;
    01345
    01346                 grow(str_num);
    01347                 setlen(str_num);
    01348
    01349                 while(str_num--)
    01350                 {
    01351                         ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
    01352                 }
    01353
    01354                 return *this;
    01355         }
    01356
    01375         String& operator=(const utf8* utf8_str)
    01376         {
    01377                 return assign(utf8_str, utf_length(utf8_str));
    01378         }
    01379
    01398         String& assign(const utf8* utf8_str)
    01399         {
    01400                 return assign(utf8_str, utf_length(utf8_str));
    01401         }
    01402
    01424         String& assign(const utf8* utf8_str, size_type str_num)
    01425         {
    01426                 if (str_num == npos)
    01427                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    01428
    01429                 size_type enc_sze = encoded_size(utf8_str, str_num);
    01430
    01431                 grow(enc_sze);
    01432                 encode(utf8_str, ptr(), d_reserve, str_num);
    01433                 setlen(enc_sze);
    01434                 return *this;
    01435         }
    01436
    01447         String& operator=(utf32 code_point)
    01448         {
    01449                 return assign(1, code_point);
    01450         }
    01451
    01467         String& assign(size_type num, utf32 code_point)
    01468         {
    01469                 if (num == npos)
    01470                         throw std::length_error("Code point count can not be 'npos'");
    01471
    01472                 grow(num);
    01473                 setlen(num);
    01474                 utf32* p = ptr();
    01475
    01476                 while(num--)
    01477                         *p++ = code_point;
    01478
    01479                 return *this;
    01480         }
    01481
    01482
    01495         String& operator=(const char* cstr)
    01496         {
    01497                 return assign(cstr, strlen(cstr));
    01498         }
    01499
    01500
    01513         String& assign(const char* cstr)
    01514         {
    01515                 return assign(cstr, strlen(cstr));
    01516         }
    01517
    01518
    01534         String& assign(const char* chars, size_type chars_len)
    01535         {
    01536                 grow(chars_len);
    01537                 utf32* pt = ptr();
    01538
    01539                 for (size_type i = 0; i < chars_len; ++i)
    01540                 {
    01541                         *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
    01542                 }
    01543
    01544                 setlen(chars_len);
    01545                 return *this;
    01546         }
    01547
    01548
    01559         void    swap(String& str)
    01560         {
    01561                 size_type       temp_len        = d_cplength;
    01562                 d_cplength = str.d_cplength;
    01563                 str.d_cplength = temp_len;
    01564
    01565                 size_type       temp_res        = d_reserve;
    01566                 d_reserve = str.d_reserve;
    01567                 str.d_reserve = temp_res;
    01568
    01569                 utf32*          temp_buf        = d_buffer;
    01570                 d_buffer = str.d_buffer;
    01571                 str.d_buffer = temp_buf;
    01572
    01573                 // see if we need to swap 'quick buffer' data
    01574                 if (temp_res <= STR_QUICKBUFF_SIZE)
    01575                 {
    01576                         utf32           temp_qbf[STR_QUICKBUFF_SIZE];
    01577
    01578                         memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
    01579                         memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
    01580                         memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
    01581                 }
    01582
    01583         }
    01584
    01586         // Appending Functions
    01588
    01600         String& operator+=(const String& str)
    01601         {
    01602                 return append(str);
    01603         }
    01604
    01624         String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
    01625         {
    01626                 if (str.d_cplength < str_idx)
    01627                         throw std::out_of_range("Index is out of range for CEGUI::String");
    01628
    01629                 if (str_num == npos)
    01630                         str_num = str.d_cplength - str_idx;
    01631
    01632                 grow(d_cplength + str_num);
    01633                 memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
    01634                 setlen(d_cplength + str_num);
    01635                 return *this;
    01636         }
    01637
    01638
    01655         String& operator+=(const std::string& std_str)
    01656         {
    01657                 return append(std_str);
    01658         }
    01659
    01683         String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
    01684         {
    01685                 if (std_str.size() < str_idx)
    01686                         throw std::out_of_range("Index is out of range for std::string");
    01687
    01688                 if (str_num == npos)
    01689                         str_num = (size_type)std_str.size() - str_idx;
    01690
    01691                 size_type newsze = d_cplength + str_num;
    01692
    01693                 grow(newsze);
    01694                 utf32* pt = &ptr()[newsze-1];
    01695
    01696                 while(str_num--)
    01697                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
    01698
    01699                 setlen(newsze);
    01700                 return *this;
    01701         }
    01702
    01703
    01722         String& operator+=(const utf8* utf8_str)
    01723         {
    01724                 return append(utf8_str, utf_length(utf8_str));
    01725         }
    01726
    01745         String& append(const utf8* utf8_str)
    01746         {
    01747                 return append(utf8_str, utf_length(utf8_str));
    01748         }
    01749
    01750
    01772         String& append(const utf8* utf8_str, size_type len)
    01773         {
    01774                 if (len == npos)
    01775                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    01776
    01777                 size_type encsz = encoded_size(utf8_str, len);
    01778                 size_type newsz = d_cplength + encsz;
    01779
    01780                 grow(newsz);
    01781                 encode(utf8_str, &ptr()[d_cplength], encsz, len);
    01782                 setlen(newsz);
    01783
    01784                 return *this;
    01785         }
    01786
    01787
    01800         String& operator+=(utf32 code_point)
    01801         {
    01802                 return append(1, code_point);
    01803         }
    01804
    01820         String& append(size_type num, utf32 code_point)
    01821         {
    01822                 if (num == npos)
    01823                         throw std::length_error("Code point count can not be 'npos'");
    01824
    01825                 size_type newsz = d_cplength + num;
    01826                 grow(newsz);
    01827
    01828                 utf32* p = &ptr()[d_cplength];
    01829
    01830                 while(num--)
    01831                         *p++ = code_point;
    01832
    01833                 setlen(newsz);
    01834
    01835                 return *this;
    01836         }
    01837
    01850         void    push_back(utf32 code_point)
    01851         {
    01852                 append(1, code_point);
    01853         }
    01854
    01870         String& append(const_iterator iter_beg, const_iterator iter_end)
    01871         {
    01872                 return replace(end(), end(), iter_beg, iter_end);
    01873         }
    01874
    01875
    01888         String& operator+=(const char* cstr)
    01889         {
    01890                 return append(cstr, strlen(cstr));
    01891         }
    01892
    01893
    01906         String& append(const char* cstr)
    01907         {
    01908                 return append(cstr, strlen(cstr));
    01909         }
    01910
    01911
    01927         String& append(const char* chars, size_type chars_len)
    01928         {
    01929                 if (chars_len == npos)
    01930                         throw std::length_error("Length for char array can not be 'npos'");
    01931
    01932                 size_type newsz = d_cplength + chars_len;
    01933
    01934                 grow(newsz);
    01935
    01936                 utf32* pt = &ptr()[newsz-1];
    01937
    01938                 while(chars_len--)
    01939                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
    01940
    01941                 setlen(newsz);
    01942
    01943                 return *this;
    01944         }
    01945
    01946
    01948         // Insertion Functions
    01950
    01966         String& insert(size_type idx, const String& str)
    01967         {
    01968                 return insert(idx, str, 0, npos);
    01969         }
    01970
    01993         String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
    01994         {
    01995                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
    01996                         throw std::out_of_range("Index is out of range for CEGUI::String");
    01997
    01998                 if (str_num == npos)
    01999                         str_num = str.d_cplength - str_idx;
    02000
    02001                 size_type newsz = d_cplength + str_num;
    02002                 grow(newsz);
    02003                 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
    02004                 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
    02005                 setlen(newsz);
    02006
    02007                 return *this;
    02008         }
    02009
    02030         String& insert(size_type idx, const std::string& std_str)
    02031         {
    02032                 return insert(idx, std_str, 0, npos);
    02033         }
    02034
    02061         String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
    02062         {
    02063                 if (d_cplength < idx)
    02064                         throw std::out_of_range("Index is out of range for CEGUI::String");
    02065
    02066                 if (std_str.size() < str_idx)
    02067                         throw std::out_of_range("Index is out of range for std::string");
    02068
    02069                 if (str_num == npos)
    02070                         str_num = (size_type)std_str.size() - str_idx;
    02071
    02072                 size_type newsz = d_cplength + str_num;
    02073                 grow(newsz);
    02074
    02075                 memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
    02076
    02077                 utf32* pt = &ptr()[idx + str_num - 1];
    02078
    02079                 while(str_num--)
    02080                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
    02081
    02082                 setlen(newsz);
    02083
    02084                 return *this;
    02085         }
    02086
    02109         String& insert(size_type idx, const utf8* utf8_str)
    02110         {
    02111                 return insert(idx, utf8_str, utf_length(utf8_str));
    02112         }
    02113
    02139         String& insert(size_type idx, const utf8* utf8_str, size_type len)
    02140         {
    02141                 if (d_cplength < idx)
    02142                         throw std::out_of_range("Index is out of range for CEGUI::String");
    02143
    02144                 if (len == npos)
    02145                         throw std::length_error("Length of utf8 encoded string can not be 'npos'");
    02146
    02147                 size_type encsz = encoded_size(utf8_str, len);
    02148                 size_type newsz = d_cplength + encsz;
    02149
    02150                 grow(newsz);
    02151                 memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
    02152                 encode(utf8_str, &ptr()[idx], encsz, len);
    02153                 setlen(newsz);
    02154
    02155                 return *this;
    02156         }
    02157
    02177         String& insert(size_type idx, size_type num, utf32 code_point)
    02178         {
    02179                 if (d_cplength < idx)
    02180                         throw std::out_of_range("Index is out of range for CEGUI::String");
    02181
    02182                 if (num == npos)
    02183                         throw std::length_error("Code point count can not be 'npos'");
    02184
    02185                 size_type newsz = d_cplength + num;
    02186                 grow(newsz);
    02187
    02188                 memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
    02189
    02190                 utf32* pt = &ptr()[idx + num - 1];
    02191
    02192                 while(num--)
    02193                         *pt-- = code_point;
    02194
    02195                 setlen(newsz);
    02196
    02197                 return *this;
    02198         }
    02199
    02218         void insert(iterator pos, size_type num, utf32 code_point)
    02219         {
    02220                 insert(safe_iter_dif(pos, begin()), num, code_point);
    02221         }
    02222
    02238         iterator insert(iterator pos, utf32 code_point)
    02239         {
    02240                 insert(pos, 1, code_point);
    02241                 return pos;
    02242         }
    02243
    02262         void    insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
    02263         {
    02264                 replace(iter_pos, iter_pos, iter_beg, iter_end);
    02265         }
    02266
    02267
    02284         String& insert(size_type idx, const char* cstr)
    02285         {
    02286                 return insert(idx, cstr, strlen(cstr));
    02287         }
    02288
    02289
    02309         String& insert(size_type idx, const char* chars, size_type chars_len)
    02310         {
    02311                 if (d_cplength < idx)
    02312                         throw std::out_of_range("Index is out of range for CEGUI::String");
    02313
    02314                 if (chars_len == npos)
    02315                         throw std::length_error("Length of char array can not be 'npos'");
    02316
    02317                 size_type newsz = d_cplength + chars_len;
    02318
    02319                 grow(newsz);
    02320                 memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
    02321
    02322                 utf32* pt = &ptr()[idx + chars_len - 1];
    02323
    02324                 while(chars_len--)
    02325                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
    02326
    02327                 setlen(newsz);
    02328
    02329                 return *this;
    02330         }
    02331
    02332
    02334         // Erasing characters
    02336
    02343         void    clear(void)
    02344         {
    02345                 setlen(0);
    02346                 trim();
    02347         }
    02348
    02356         String& erase(void)
    02357         {
    02358                 clear();
    02359                 return *this;
    02360         }
    02361
    02374         String& erase(size_type idx)
    02375         {
    02376                 return erase(idx, 1);
    02377         }
    02378
    02394         String& erase(size_type idx, size_type len = npos)
    02395         {
    02396                 if (d_cplength < idx)
    02397                         throw std::out_of_range("Index is out of range foe CEGUI::String");
    02398
    02399                 if (len == npos)
    02400                         len = d_cplength - idx;
    02401
    02402                 size_type newsz = d_cplength - len;
    02403
    02404                 memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
    02405                 setlen(newsz);
    02406                 return  *this;
    02407         }
    02408
    02419         String& erase(iterator pos)
    02420         {
    02421                 return erase(safe_iter_dif(pos, begin()), 1);
    02422         }
    02423
    02437         String& erase(iterator iter_beg, iterator iter_end)
    02438         {
    02439                 return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
    02440         }
    02441
    02443         // Resizing
    02445
    02457         void    resize(size_type num)
    02458         {
    02459                 resize(num, utf32());
    02460         }
    02461
    02477         void    resize(size_type num, utf32 code_point)
    02478         {
    02479                 if (num < d_cplength)
    02480                 {
    02481                         setlen(num);
    02482                 }
    02483                 else
    02484                 {
    02485                         append(num - d_cplength, code_point);
    02486                 }
    02487
    02488         }
    02489
    02491         // Replacing Characters
    02493
    02512         String& replace(size_type idx, size_type len, const String& str)
    02513         {
    02514                 return replace(idx, len, str, 0, npos);
    02515         }
    02516
    02538         String& replace(iterator iter_beg, iterator iter_end, const String& str)
    02539         {
    02540                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
    02541         }
    02542
    02568         String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
    02569         {
    02570                 if ((d_cplength < idx) || (str.d_cplength < str_idx))
    02571                         throw std::out_of_range("Index is out of range for CEGUI::String");
    02572
    02573                 if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
    02574                         str_num = str.d_cplength - str_idx;
    02575
    02576                 if (((len + idx) > d_cplength) || (len == npos))
    02577                         len = d_cplength - idx;
    02578
    02579                 size_type newsz = d_cplength + str_num - len;
    02580
    02581                 grow(newsz);
    02582
    02583                 if ((idx + len) < d_cplength)
    02584                         memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
    02585
    02586                 memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
    02587                 setlen(newsz);
    02588
    02589                 return *this;
    02590         }
    02591
    02592
    02616         String& replace(size_type idx, size_type len, const std::string& std_str)
    02617         {
    02618                 return replace(idx, len, std_str, 0, npos);
    02619         }
    02620
    02646         String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
    02647         {
    02648                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
    02649         }
    02650
    02680         String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
    02681         {
    02682                 if (d_cplength < idx)
    02683                         throw std::out_of_range("Index is out of range for CEGUI::String");
    02684
    02685                 if (std_str.size() < str_idx)
    02686                         throw std::out_of_range("Index is out of range for std::string");
    02687
    02688                 if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
    02689                         str_num = (size_type)std_str.size() - str_idx;
    02690
    02691                 if (((len + idx) > d_cplength) || (len == npos))
    02692                         len = d_cplength - idx;
    02693
    02694                 size_type newsz = d_cplength + str_num - len;
    02695
    02696                 grow(newsz);
    02697
    02698                 if ((idx + len) < d_cplength)
    02699                         memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
    02700
    02701                 utf32* pt = &ptr()[idx + str_num - 1];
    02702
    02703                 while (str_num--)
    02704                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
    02705
    02706                 setlen(newsz);
    02707
    02708                 return *this;
    02709         }
    02710
    02711
    02737         String& replace(size_type idx, size_type len, const utf8* utf8_str)
    02738         {
    02739                 return replace(idx, len, utf8_str, utf_length(utf8_str));
    02740         }
    02741
    02769         String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
    02770         {
    02771                 return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
    02772         }
    02773
    02802         String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
    02803         {
    02804                 if (d_cplength < idx)
    02805                         throw std::out_of_range("Index is out of range for CEGUI::String");
    02806
    02807                 if (str_len == npos)
    02808                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    02809
    02810                 if (((len + idx) > d_cplength) || (len == npos))
    02811                         len = d_cplength - idx;
    02812
    02813                 size_type encsz = encoded_size(utf8_str, str_len);
    02814                 size_type newsz = d_cplength + encsz - len;
    02815
    02816                 grow(newsz);
    02817
    02818                 if ((idx + len) < d_cplength)
    02819                         memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
    02820
    02821                 encode(utf8_str, &ptr()[idx], encsz, str_len);
    02822
    02823                 setlen(newsz);
    02824                 return *this;
    02825         }
    02826
    02857         String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
    02858         {
    02859                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
    02860         }
    02861
    02884         String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
    02885         {
    02886                 if (d_cplength < idx)
    02887                         throw std::out_of_range("Index is out of range for CEGUI::String");
    02888
    02889                 if (num == npos)
    02890                         throw std::length_error("Code point count can not be 'npos'");
    02891
    02892                 if (((len + idx) > d_cplength) || (len == npos))
    02893                         len = d_cplength - idx;
    02894
    02895                 size_type newsz = d_cplength + num - len;
    02896
    02897                 grow(newsz);
    02898
    02899                 if ((idx + len) < d_cplength)
    02900                         memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
    02901
    02902                 utf32* pt = &ptr()[idx + num - 1];
    02903
    02904                 while (num--)
    02905                         *pt-- = code_point;
    02906
    02907                 setlen(newsz);
    02908
    02909                 return *this;
    02910         }
    02911
    02936         String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
    02937         {
    02938                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
    02939         }
    02940
    02941
    02966         String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
    02967         {
    02968                 if (iter_beg == iter_end)
    02969                 {
    02970                         erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
    02971                 }
    02972                 else
    02973                 {
    02974                         size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
    02975                         size_type idx = safe_iter_dif(iter_beg, begin());
    02976                         size_type len = safe_iter_dif(iter_end, iter_beg);
    02977
    02978                         if ((len + idx) > d_cplength)
    02979                                 len = d_cplength - idx;
    02980
    02981                         size_type newsz = d_cplength + str_len - len;
    02982
    02983                         grow(newsz);
    02984
    02985                         if ((idx + len) < d_cplength)
    02986                                 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
    02987
    02988                         memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
    02989                         setlen(newsz);
    02990                 }
    02991
    02992                 return *this;
    02993         }
    02994
    02995
    03015         String& replace(size_type idx, size_type len, const char* cstr)
    03016         {
    03017                 return replace(idx, len, cstr, strlen(cstr));
    03018         }
    03019
    03020
    03042         String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
    03043         {
    03044                 return replace(iter_beg, iter_end, cstr, strlen(cstr));
    03045         }
    03046
    03047
    03070         String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
    03071         {
    03072                 if (d_cplength < idx)
    03073                         throw std::out_of_range("Index is out of range for CEGUI::String");
    03074
    03075                 if (chars_len == npos)
    03076                         throw std::length_error("Length for the char array can not be 'npos'");
    03077
    03078                 if (((len + idx) > d_cplength) || (len == npos))
    03079                         len = d_cplength - idx;
    03080
    03081                 size_type newsz = d_cplength + chars_len - len;
    03082
    03083                 grow(newsz);
    03084
    03085                 if ((idx + len) < d_cplength)
    03086                         memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
    03087
    03088                 utf32* pt = &ptr()[idx + chars_len - 1];
    03089
    03090                 while (chars_len--)
    03091                         *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
    03092
    03093                 setlen(newsz);
    03094                 return *this;
    03095         }
    03096
    03097
    03122         String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
    03123         {
    03124                 return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
    03125         }
    03126
    03127
    03129         // Find a code point
    03131
    03145         size_type       find(utf32 code_point, size_type idx = 0) const
    03146         {
    03147                 if (idx < d_cplength)
    03148                 {
    03149                         const utf32* pt = &ptr()[idx];
    03150
    03151                         while (idx < d_cplength)
    03152                         {
    03153                                 if (*pt++ == code_point)
    03154                                         return idx;
    03155
    03156                                 ++idx;
    03157                         }
    03158
    03159                 }
    03160
    03161                 return npos;
    03162         }
    03163
    03178         size_type       rfind(utf32 code_point, size_type idx = npos) const
    03179         {
    03180                 if (idx >= d_cplength)
    03181                         idx = d_cplength - 1;
    03182
    03183                 if (d_cplength > 0)
    03184                 {
    03185                         const utf32* pt = &ptr()[idx];
    03186
    03187                         do
    03188                         {
    03189                                 if (*pt-- == code_point)
    03190                                         return idx;
    03191
    03192                         } while (idx-- != 0);
    03193
    03194                 }
    03195
    03196                 return npos;
    03197         }
    03198
    03200         // Find a substring
    03202
    03216         size_type       find(const String& str, size_type idx = 0) const
    03217         {
    03218                 if ((str.d_cplength == 0) && (idx < d_cplength))
    03219                         return idx;
    03220
    03221                 if (idx < d_cplength)
    03222                 {
    03223                         // loop while search string could fit in to search area
    03224                         while (d_cplength - idx >= str.d_cplength)
    03225                         {
    03226                                 if (0 == compare(idx, str.d_cplength, str))
    03227                                         return idx;
    03228
    03229                                 ++idx;
    03230                         }
    03231
    03232                 }
    03233
    03234                 return npos;
    03235         }
    03236
    03251         size_type       rfind(const String& str, size_type idx = npos) const
    03252         {
    03253                 if (str.d_cplength == 0)
    03254                         return (idx < d_cplength) ? idx : d_cplength;
    03255
    03256                 if (str.d_cplength <= d_cplength)
    03257                 {
    03258                         if (idx > (d_cplength - str.d_cplength))
    03259                                 idx = d_cplength - str.d_cplength;
    03260
    03261                         do
    03262                         {
    03263                                 if (0 == compare(idx, str.d_cplength, str))
    03264                                         return idx;
    03265
    03266                         } while (idx-- != 0);
    03267
    03268                 }
    03269
    03270                 return npos;
    03271         }
    03272
    03291         size_type       find(const std::string& std_str, size_type idx = 0) const
    03292         {
    03293                 std::string::size_type sze = std_str.size();
    03294
    03295                 if ((sze == 0) && (idx < d_cplength))
    03296                         return idx;
    03297
    03298                 if (idx < d_cplength)
    03299                 {
    03300                         // loop while search string could fit in to search area
    03301                         while (d_cplength - idx >= sze)
    03302                         {
    03303                                 if (0 == compare(idx, (size_type)sze, std_str))
    03304                                         return idx;
    03305
    03306                                 ++idx;
    03307                         }
    03308
    03309                 }
    03310
    03311                 return npos;
    03312         }
    03313
    03332         size_type       rfind(const std::string& std_str, size_type idx = npos) const
    03333         {
    03334                 std::string::size_type sze = std_str.size();
    03335
    03336                 if (sze == 0)
    03337                         return (idx < d_cplength) ? idx : d_cplength;
    03338
    03339                 if (sze <= d_cplength)
    03340                 {
    03341                         if (idx > (d_cplength - sze))
    03342                                 idx = d_cplength - sze;
    03343
    03344                         do
    03345                         {
    03346                                 if (0 == compare(idx, (size_type)sze, std_str))
    03347                                         return idx;
    03348
    03349                         } while (idx-- != 0);
    03350
    03351                 }
    03352
    03353                 return npos;
    03354         }
    03355
    03378         size_type       find(const utf8* utf8_str, size_type idx = 0) const
    03379         {
    03380                 return find(utf8_str, idx, utf_length(utf8_str));
    03381         }
    03382
    03405         size_type       rfind(const utf8* utf8_str, size_type idx = npos) const
    03406         {
    03407                 return rfind(utf8_str, idx, utf_length(utf8_str));
    03408         }
    03409
    03435         size_type       find(const utf8* utf8_str, size_type idx, size_type str_len) const
    03436         {
    03437                 if (str_len == npos)
    03438                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    03439
    03440                 size_type sze = encoded_size(utf8_str, str_len);
    03441
    03442                 if ((sze == 0) && (idx < d_cplength))
    03443                         return idx;
    03444
    03445                 if (idx < d_cplength)
    03446                 {
    03447                         // loop while search string could fit in to search area
    03448                         while (d_cplength - idx >= sze)
    03449                         {
    03450                                 if (0 == compare(idx, sze, utf8_str, sze))
    03451                                         return idx;
    03452
    03453                                 ++idx;
    03454                         }
    03455
    03456                 }
    03457
    03458                 return npos;
    03459         }
    03460
    03486         size_type       rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
    03487         {
    03488                 if (str_len == npos)
    03489                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    03490
    03491                 size_type sze = encoded_size(utf8_str, str_len);
    03492
    03493                 if (sze == 0)
    03494                         return (idx < d_cplength) ? idx : d_cplength;
    03495
    03496                 if (sze <= d_cplength)
    03497                 {
    03498                         if (idx > (d_cplength - sze))
    03499                                 idx = d_cplength - sze;
    03500
    03501                         do
    03502                         {
    03503                                 if (0 == compare(idx, sze, utf8_str, sze))
    03504                                         return idx;
    03505
    03506                         } while (idx-- != 0);
    03507
    03508                 }
    03509
    03510                 return npos;
    03511         }
    03512
    03513
    03530         size_type       find(const char* cstr, size_type idx = 0) const
    03531         {
    03532                 return find(cstr, idx, strlen(cstr));
    03533         }
    03534
    03535
    03552         size_type       rfind(const char* cstr, size_type idx = npos) const
    03553         {
    03554                 return rfind(cstr, idx, strlen(cstr));
    03555         }
    03556
    03557
    03577         size_type       find(const char* chars, size_type idx, size_type chars_len) const
    03578         {
    03579                 if (chars_len == npos)
    03580                         throw std::length_error("Length for char array can not be 'npos'");
    03581
    03582                 if ((chars_len == 0) && (idx < d_cplength))
    03583                         return idx;
    03584
    03585                 if (idx < d_cplength)
    03586                 {
    03587                         // loop while search string could fit in to search area
    03588                         while (d_cplength - idx >= chars_len)
    03589                         {
    03590                                 if (0 == compare(idx, chars_len, chars, chars_len))
    03591                                         return idx;
    03592
    03593                                 ++idx;
    03594                         }
    03595
    03596                 }
    03597
    03598                 return npos;
    03599         }
    03600
    03601
    03621         size_type       rfind(const char* chars, size_type idx, size_type chars_len) const
    03622         {
    03623                 if (chars_len == npos)
    03624                         throw std::length_error("Length for char array can not be 'npos'");
    03625
    03626                 if (chars_len == 0)
    03627                         return (idx < d_cplength) ? idx : d_cplength;
    03628
    03629                 if (chars_len <= d_cplength)
    03630                 {
    03631                         if (idx > (d_cplength - chars_len))
    03632                                 idx = d_cplength - chars_len;
    03633
    03634                         do
    03635                         {
    03636                                 if (0 == compare(idx, chars_len, chars, chars_len))
    03637                                         return idx;
    03638
    03639                         } while (idx-- != 0);
    03640
    03641                 }
    03642
    03643                 return npos;
    03644         }
    03645
    03646
    03648         // Find first of different code-points
    03650
    03664         size_type       find_first_of(const String& str, size_type idx = 0) const
    03665         {
    03666                 if (idx < d_cplength)
    03667                 {
    03668                         const utf32* pt = &ptr()[idx];
    03669
    03670                         do
    03671                         {
    03672                                 if (npos != str.find(*pt++))
    03673                                         return idx;
    03674
    03675                         } while (++idx != d_cplength);
    03676
    03677                 }
    03678
    03679                 return npos;
    03680         }
    03681
    03696         size_type       find_first_not_of(const String& str, size_type idx = 0) const
    03697         {
    03698                 if (idx < d_cplength)
    03699                 {
    03700                         const utf32* pt = &ptr()[idx];
    03701
    03702                         do
    03703                         {
    03704                                 if (npos == str.find(*pt++))
    03705                                         return idx;
    03706
    03707                         } while (++idx != d_cplength);
    03708
    03709                 }
    03710
    03711                 return npos;
    03712         }
    03713
    03714
    03733         size_type       find_first_of(const std::string& std_str, size_type idx = 0) const
    03734         {
    03735                 if (idx < d_cplength)
    03736                 {
    03737                         const utf32* pt = &ptr()[idx];
    03738
    03739                         do
    03740                         {
    03741                                 if (npos != find_codepoint(std_str, *pt++))
    03742                                         return idx;
    03743
    03744                         } while (++idx != d_cplength);
    03745
    03746                 }
    03747
    03748                 return npos;
    03749         }
    03750
    03769         size_type       find_first_not_of(const std::string& std_str, size_type idx = 0) const
    03770         {
    03771                 if (idx < d_cplength)
    03772                 {
    03773                         const utf32* pt = &ptr()[idx];
    03774
    03775                         do
    03776                         {
    03777                                 if (npos == find_codepoint(std_str, *pt++))
    03778                                         return idx;
    03779
    03780                         } while (++idx != d_cplength);
    03781
    03782                 }
    03783
    03784                 return npos;
    03785         }
    03786
    03787
    03810         size_type       find_first_of(const utf8* utf8_str, size_type idx = 0) const
    03811         {
    03812                 return find_first_of(utf8_str, idx, utf_length(utf8_str));
    03813         }
    03814
    03837         size_type       find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
    03838         {
    03839                 return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
    03840         }
    03841
    03867         size_type       find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
    03868         {
    03869                 if (str_len == npos)
    03870                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    03871
    03872                 if (idx < d_cplength)
    03873                 {
    03874                         size_type encsze = encoded_size(utf8_str, str_len);
    03875
    03876                         const utf32* pt = &ptr()[idx];
    03877
    03878                         do
    03879                         {
    03880                                 if (npos != find_codepoint(utf8_str, encsze, *pt++))
    03881                                         return idx;
    03882
    03883                         } while (++idx != d_cplength);
    03884
    03885                 }
    03886
    03887                 return npos;
    03888         }
    03889
    03915         size_type       find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
    03916         {
    03917                 if (str_len == npos)
    03918                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    03919
    03920                 if (idx < d_cplength)
    03921                 {
    03922                         size_type encsze = encoded_size(utf8_str, str_len);
    03923
    03924                         const utf32* pt = &ptr()[idx];
    03925
    03926                         do
    03927                         {
    03928                                 if (npos == find_codepoint(utf8_str, encsze, *pt++))
    03929                                         return idx;
    03930
    03931                         } while (++idx != d_cplength);
    03932
    03933                 }
    03934
    03935                 return npos;
    03936         }
    03937
    03938
    03953         size_type       find_first_of(utf32 code_point, size_type idx = 0) const
    03954         {
    03955                 return find(code_point, idx);
    03956         }
    03957
    03974         size_type       find_first_not_of(utf32 code_point, size_type idx = 0) const
    03975         {
    03976                 if (idx < d_cplength)
    03977                 {
    03978                         do
    03979                         {
    03980                                 if ((*this)[idx] != code_point)
    03981                                         return idx;
    03982
    03983                         } while(idx++ < d_cplength);
    03984
    03985                 }
    03986
    03987                 return npos;
    03988         }
    03989
    03990
    04007         size_type       find_first_of(const char* cstr, size_type idx = 0) const
    04008         {
    04009                 return find_first_of(cstr, idx, strlen(cstr));
    04010         }
    04011
    04012
    04029         size_type       find_first_not_of(const char* cstr, size_type idx = 0) const
    04030         {
    04031                 return find_first_not_of(cstr, idx, strlen(cstr));
    04032         }
    04033
    04034
    04054         size_type       find_first_of(const char* chars, size_type idx, size_type chars_len) const
    04055         {
    04056                 if (chars_len == npos)
    04057                         throw std::length_error("Length for char array can not be 'npos'");
    04058
    04059                 if (idx < d_cplength)
    04060                 {
    04061                         const utf32* pt = &ptr()[idx];
    04062
    04063                         do
    04064                         {
    04065                                 if (npos != find_codepoint(chars, chars_len, *pt++))
    04066                                         return idx;
    04067
    04068                         } while (++idx != d_cplength);
    04069
    04070                 }
    04071
    04072                 return npos;
    04073         }
    04074
    04075
    04095         size_type       find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
    04096         {
    04097                 if (chars_len == npos)
    04098                         throw std::length_error("Length for char array can not be 'npos'");
    04099
    04100                 if (idx < d_cplength)
    04101                 {
    04102                         const utf32* pt = &ptr()[idx];
    04103
    04104                         do
    04105                         {
    04106                                 if (npos == find_codepoint(chars, chars_len, *pt++))
    04107                                         return idx;
    04108
    04109                         } while (++idx != d_cplength);
    04110
    04111                 }
    04112
    04113                 return npos;
    04114         }
    04115
    04116
    04118         // Find last of different code-points
    04120
    04134         size_type       find_last_of(const String& str, size_type idx = npos) const
    04135         {
    04136                 if (d_cplength > 0)
    04137                 {
    04138                         if (idx >= d_cplength)
    04139                                 idx = d_cplength - 1;
    04140
    04141                         const utf32* pt = &ptr()[idx];
    04142
    04143                         do
    04144                         {
    04145                                 if (npos != str.find(*pt--))
    04146                                         return idx;
    04147
    04148                         } while (idx-- != 0);
    04149
    04150                 }
    04151
    04152                 return npos;
    04153         }
    04154
    04169         size_type       find_last_not_of(const String& str, size_type idx = npos) const
    04170         {
    04171                 if (d_cplength > 0)
    04172                 {
    04173                         if (idx >= d_cplength)
    04174                                 idx = d_cplength - 1;
    04175
    04176                         const utf32* pt = &ptr()[idx];
    04177
    04178                         do
    04179                         {
    04180                                 if (npos == str.find(*pt--))
    04181                                         return idx;
    04182
    04183                         } while (idx-- != 0);
    04184
    04185                 }
    04186
    04187                 return npos;
    04188         }
    04189
    04190
    04209         size_type       find_last_of(const std::string& std_str, size_type idx = npos) const
    04210         {
    04211                 if (d_cplength > 0)
    04212                 {
    04213                         if (idx >= d_cplength)
    04214                                 idx = d_cplength - 1;
    04215
    04216                         const utf32* pt = &ptr()[idx];
    04217
    04218                         do
    04219                         {
    04220                                 if (npos != find_codepoint(std_str, *pt--))
    04221                                         return idx;
    04222
    04223                         } while (idx-- != 0);
    04224
    04225                 }
    04226
    04227                 return npos;
    04228         }
    04229
    04248         size_type       find_last_not_of(const std::string& std_str, size_type idx = npos) const
    04249         {
    04250                 if (d_cplength > 0)
    04251                 {
    04252                         if (idx >= d_cplength)
    04253                                 idx = d_cplength - 1;
    04254
    04255                         const utf32* pt = &ptr()[idx];
    04256
    04257                         do
    04258                         {
    04259                                 if (npos == find_codepoint(std_str, *pt--))
    04260                                         return idx;
    04261
    04262                         } while (idx-- != 0);
    04263
    04264                 }
    04265
    04266                 return npos;
    04267         }
    04268
    04269
    04292         size_type       find_last_of(const utf8* utf8_str, size_type idx = npos) const
    04293         {
    04294                 return find_last_of(utf8_str, idx, utf_length(utf8_str));
    04295         }
    04296
    04319         size_type       find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
    04320         {
    04321                 return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
    04322         }
    04323
    04349         size_type       find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
    04350         {
    04351                 if (str_len == npos)
    04352                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    04353
    04354                 if (d_cplength > 0)
    04355                 {
    04356                         if (idx >= d_cplength)
    04357                                 idx = d_cplength - 1;
    04358
    04359                         size_type encsze = encoded_size(utf8_str, str_len);
    04360
    04361                         const utf32* pt = &ptr()[idx];
    04362
    04363                         do
    04364                         {
    04365                                 if (npos != find_codepoint(utf8_str, encsze, *pt--))
    04366                                         return idx;
    04367
    04368                         } while (idx-- != 0);
    04369
    04370                 }
    04371
    04372                 return npos;
    04373         }
    04374
    04400         size_type       find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
    04401         {
    04402                 if (str_len == npos)
    04403                         throw std::length_error("Length for utf8 encoded string can not be 'npos'");
    04404
    04405                 if (d_cplength > 0)
    04406                 {
    04407                         if (idx >= d_cplength)
    04408                                 idx = d_cplength - 1;
    04409
    04410                         size_type encsze = encoded_size(utf8_str, str_len);
    04411
    04412                         const utf32* pt = &ptr()[idx];
    04413
    04414                         do
    04415                         {
    04416                                 if (npos == find_codepoint(utf8_str, encsze, *pt--))
    04417                                         return idx;
    04418
    04419                         } while (idx-- != 0);
    04420
    04421                 }
    04422
    04423                 return npos;
    04424         }
    04425
    04426
    04441         size_type       find_last_of(utf32 code_point, size_type idx = npos) const
    04442         {
    04443                 return rfind(code_point, idx);
    04444         }
    04445
    04460         size_type       find_last_not_of(utf32 code_point, size_type idx = npos) const
    04461         {
    04462                 if (d_cplength > 0)
    04463                 {
    04464                         if (idx >= d_cplength)
    04465                                 idx = d_cplength - 1;
    04466
    04467                         do
    04468                         {
    04469                                 if ((*this)[idx] != code_point)
    04470                                         return idx;
    04471
    04472                         } while(idx-- != 0);
    04473
    04474                 }
    04475
    04476                 return npos;
    04477         }
    04478
    04479
    04496         size_type       find_last_of(const char* cstr, size_type idx = npos) const
    04497         {
    04498                 return find_last_of(cstr, idx, strlen(cstr));
    04499         }
    04500
    04501
    04518         size_type       find_last_not_of(const char* cstr, size_type idx = npos) const
    04519         {
    04520                 return find_last_not_of(cstr, idx, strlen(cstr));
    04521         }
    04522
    04523
    04543         size_type       find_last_of(const char* chars, size_type idx, size_type chars_len) const
    04544         {
    04545                 if (chars_len == npos)
    04546                         throw std::length_error("Length for char array can not be 'npos'");
    04547
    04548                 if (d_cplength > 0)
    04549                 {
    04550                         if (idx >= d_cplength)
    04551                                 idx = d_cplength - 1;
    04552
    04553                         const utf32* pt = &ptr()[idx];
    04554
    04555                         do
    04556                         {
    04557                                 if (npos != find_codepoint(chars, chars_len, *pt--))
    04558                                         return idx;
    04559
    04560                         } while (idx-- != 0);
    04561
    04562                 }
    04563
    04564                 return npos;
    04565         }
    04566
    04567
    04587         size_type       find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
    04588         {
    04589                 if (chars_len == npos)
    04590                         throw std::length_error("Length for char array can not be 'npos'");
    04591
    04592                 if (d_cplength > 0)
    04593                 {
    04594                         if (idx >= d_cplength)
    04595                                 idx = d_cplength - 1;
    04596
    04597                         const utf32* pt = &ptr()[idx];
    04598
    04599                         do
    04600                         {
    04601                                 if (npos == find_codepoint(chars, chars_len, *pt--))
    04602                                         return idx;
    04603
    04604                         } while (idx-- != 0);
    04605
    04606                 }
    04607
    04608                 return npos;
    04609         }
    04610
    04611
    04613         // Substring
    04615
    04630         String  substr(size_type idx = 0, size_type len = npos) const
    04631         {
    04632                 if (d_cplength < idx)
    04633                         throw std::out_of_range("Index is out of range for this CEGUI::String");
    04634
    04635                 return String(*this, idx, len);
    04636         }
    04637
    04639         // Iterator creation
    04641
    04648         iterator                begin(void)
    04649         {
    04650                 return iterator(ptr());
    04651         }
    04652
    04660         const_iterator  begin(void) const
    04661         {
    04662                 return const_iterator(ptr());
    04663         }
    04664
    04672         iterator                end(void)
    04673         {
    04674                 return iterator(&ptr()[d_cplength]);
    04675         }
    04676
    04684         const_iterator  end(void) const
    04685         {
    04686                 return const_iterator(&ptr()[d_cplength]);
    04687         }
    04688
    04696         reverse_iterator                rbegin(void)
    04697         {
    04698                 return reverse_iterator(end());
    04699         }
    04700
    04708         const_reverse_iterator  rbegin(void) const
    04709         {
    04710                 return const_reverse_iterator(end());
    04711         }
    04712
    04720         reverse_iterator                rend(void)
    04721         {
    04722                 return reverse_iterator(begin());
    04723         }
    04724
    04732         const_reverse_iterator  rend(void) const
    04733         {
    04734                 return const_reverse_iterator(begin());
    04735         }
    04736
    04737 private:
    04738         /*************************************************************************
    04739                 Implementation Functions
    04740         *************************************************************************/
    04741         // string management
    04742
    04743         // change size of allocated buffer so it is at least 'new_size'.
    04744         // May or may not cause re-allocation and copy of buffer if size is larger
    04745         // will never re-allocate to make size smaller.  (see trim())
    04746     bool        grow(size_type new_size);
    04747
    04748         // perform re-allocation to remove wasted space.
    04749     void        trim(void);
    04750
    04751         // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
    04752         void    setlen(size_type len)
    04753         {
    04754                 d_cplength = len;
    04755                 ptr()[len] = (utf32)(0);
    04756         }
    04757
    04758         // return a ptr to the buffer in use.
    04759         utf32*  ptr(void)
    04760         {
    04761                 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
    04762         }
    04763
    04764         // return a ptr tot he buffer in use (const version)
    04765         const utf32*    ptr(void) const
    04766         {
    04767                 return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
    04768         }
    04769
    04770         // initialise string object
    04771         void    init(void)
    04772         {
    04773                 d_reserve                       = STR_QUICKBUFF_SIZE;
    04774                 d_encodedbuff           = NULL;
    04775                 d_encodedbufflen        = 0;
    04776                 d_encodeddatlen         = 0;
    04777                 setlen(0);
    04778         }
    04779
    04780         // return true if the given pointer is inside the string data
    04781         bool    inside(utf32* inptr)
    04782         {
    04783                 if (inptr < ptr() || ptr() + d_cplength <= inptr)
    04784                         return false;
    04785                 else
    04786                         return true;
    04787         }
    04788
    04789         // compute distance between two iterators, returning a 'safe' value
    04790         size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
    04791         {
    04792                 return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
    04793         }
    04794
    04795         // encoding functions
    04796         // for all:
    04797         //      src_len is in code units, or 0 for null terminated string.
    04798         //      dest_len is in code units.
    04799         //      returns number of code units put into dest buffer.
    04800         size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
    04801         {
    04802                 // count length for null terminated source...
    04803                 if (src_len == 0)
    04804                 {
    04805                         src_len = utf_length(src);
    04806                 }
    04807
    04808                 size_type destCapacity = dest_len;
    04809
    04810                 // while there is data in the source buffer,
    04811                 for (uint idx = 0; idx < src_len; ++idx)
    04812                 {
    04813                         utf32   cp = src[idx];
    04814
    04815                         // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
    04816                         if (destCapacity < encoded_size(cp))
    04817                         {
    04818                                 break;
    04819                         }
    04820
    04821                         if (cp < 0x80)
    04822                         {
    04823                                 *dest++ = (utf8)cp;
    04824                                 --destCapacity;
    04825                         }
    04826                         else if (cp < 0x0800)
    04827                         {
    04828                                 *dest++ = (utf8)((cp >> 6) | 0xC0);
    04829                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
    04830                                 destCapacity -= 2;
    04831                         }
    04832                         else if (cp < 0x10000)
    04833                         {
    04834                                 *dest++ = (utf8)((cp >> 12) | 0xE0);
    04835                                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
    04836                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
    04837                                 destCapacity -= 3;
    04838                         }
    04839                         else
    04840                         {
    04841                                 *dest++ = (utf8)((cp >> 18) | 0xF0);
    04842                                 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
    04843                                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
    04844                                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
    04845                                 destCapacity -= 4;
    04846                         }
    04847
    04848                 }
    04849
    04850                 return dest_len - destCapacity;
    04851         }
    04852
    04853         size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
    04854         {
    04855                 // count length for null terminated source...
    04856                 if (src_len == 0)
    04857                 {
    04858                         src_len = utf_length(src);
    04859                 }
    04860
    04861                 size_type destCapacity = dest_len;
    04862
    04863                 // while there is data in the source buffer, and space in the dest buffer
    04864                 for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
    04865                 {
    04866                         utf32   cp;
    04867                         utf8    cu = src[idx++];
    04868
    04869                         if (cu < 0x80)
    04870                         {
    04871                                 cp = (utf32)(cu);
    04872                         }
    04873                         else if (cu < 0xE0)
    04874                         {
    04875                                 cp = ((cu & 0x1F) << 6);
    04876                                 cp |= (src[idx++] & 0x3F);
    04877                         }
    04878                         else if (cu < 0xF0)
    04879                         {
    04880                                 cp = ((cu & 0x0F) << 12);
    04881                                 cp |= ((src[idx++] & 0x3F) << 6);
    04882                                 cp |= (src[idx++] & 0x3F);
    04883                         }
    04884                         else
    04885                         {
    04886                                 cp = ((cu & 0x07) << 18);
    04887                                 cp |= ((src[idx++] & 0x3F) << 12);
    04888                                 cp |= ((src[idx++] & 0x3F) << 6);
    04889                                 cp |= (src[idx++] & 0x3F);
    04890                         }
    04891
    04892                         *dest++ = cp;
    04893                         --destCapacity;
    04894                 }
    04895
    04896                 return dest_len - destCapacity;
    04897         }
    04898
    04899         // return the number of utf8 code units required to encode the given utf32 code point
    04900         size_type encoded_size(utf32 code_point) const
    04901         {
    04902                 if (code_point < 0x80)
    04903                         return 1;
    04904                 else if (code_point < 0x0800)
    04905                         return 2;
    04906                 else if (code_point < 0x10000)
    04907                         return 3;
    04908                 else
    04909                         return 4;
    04910         }
    04911
    04912         // return number of code units required to re-encode given null-terminated utf32 data as utf8.  return does not include terminating null.
    04913         size_type encoded_size(const utf32* buf) const
    04914         {
    04915                 return encoded_size(buf, utf_length(buf));
    04916         }
    04917
    04918         // return number of code units required to re-encode given utf32 data as utf8.   len is number of code units in 'buf'.
    04919         size_type encoded_size(const utf32* buf, size_type len) const
    04920         {
    04921                 size_type count = 0;
    04922
    04923                 while (len--)
    04924                 {
    04925                         count += encoded_size(*buf++);
    04926                 }
    04927
    04928                 return count;
    04929         }
    04930
    04931         // return number of utf32 code units required to re-encode given utf8 data as utf32.  return does not include terminating null.
    04932         size_type encoded_size(const utf8* buf) const
    04933         {
    04934                 return encoded_size(buf, utf_length(buf));
    04935         }
    04936
    04937         // return number of utf32 code units required to re-encode given utf8 data as utf32.  len is number of code units in 'buf'.
    04938         size_type encoded_size(const utf8* buf, size_type len) const
    04939         {
    04940                 utf8 tcp;
    04941                 size_type count = 0;
    04942
    04943                 while (len--)
    04944                 {
    04945                         tcp = *buf++;
    04946                         ++count;
    04947
    04948                         if (tcp < 0x80)
    04949                         {
    04950                         }
    04951                         else if (tcp < 0xE0)
    04952                         {
    04953                                 --len;
    04954                                 ++buf;
    04955                         }
    04956                         else if (tcp < 0xF0)
    04957                         {
    04958                                 len -= 2;
    04959                                 buf += 2;
    04960                         }
    04961                         else
    04962                         {
    04963                                 len -= 2;
    04964                                 buf += 3;
    04965                         }
    04966
    04967                 }
    04968
    04969                 return count;
    04970         }
    04971
    04972         // return number of code units in a null terminated string
    04973         size_type utf_length(const utf8* utf8_str) const
    04974         {
    04975                 size_type cnt = 0;
    04976                 while (*utf8_str++)
    04977                         cnt++;
    04978
    04979                 return cnt;
    04980         }
    04981
    04982         // return number of code units in a null terminated string
    04983         size_type utf_length(const utf32* utf32_str) const
    04984         {
    04985                 size_type cnt = 0;
    04986                 while (*utf32_str++)
    04987                         cnt++;
    04988
    04989                 return cnt;
    04990         }
    04991
    04992         // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
    04993     utf8* build_utf8_buff(void) const;
    04994
    04995         // compare two utf32 buffers
    04996         int     utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
    04997         {
    04998                 if (!cp_count)
    04999                         return 0;
    05000
    05001                 while ((--cp_count) && (*buf1 == *buf2))
    05002                         buf1++, buf2++;
    05003
    05004                 return *buf1 - *buf2;
    05005         }
    05006
    05007         // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
    05008         int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
    05009         {
    05010                 if (!cp_count)
    05011                         return 0;
    05012
    05013                 while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
    05014                         buf1++, buf2++;
    05015
    05016                 return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
    05017         }
    05018
    05019         // compare utf32 buffer with encoded utf8 data
    05020         int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
    05021         {
    05022                 if (!cp_count)
    05023                         return 0;
    05024
    05025                 utf32   cp;
    05026                 utf8    cu;
    05027
    05028                 do
    05029                 {
    05030                         cu = *buf2++;
    05031
    05032                         if (cu < 0x80)
    05033                         {
    05034                                 cp = (utf32)(cu);
    05035                         }
    05036                         else if (cu < 0xE0)
    05037                         {
    05038                                 cp = ((cu & 0x1F) << 6);
    05039                                 cp |= (*buf2++ & 0x3F);
    05040                         }
    05041                         else if (cu < 0xF0)
    05042                         {
    05043                                 cp = ((cu & 0x0F) << 12);
    05044                                 cp |= ((*buf2++ & 0x3F) << 6);
    05045                                 cp |= (*buf2++ & 0x3F);
    05046                         }
    05047                         else
    05048                         {
    05049                                 cp = ((cu & 0x07) << 18);
    05050                                 cp |= ((*buf2++ & 0x3F) << 12);
    05051                                 cp |= ((*buf2++ & 0x3F) << 6);
    05052                                 cp |= (*buf2++ & 0x3F);
    05053                         }
    05054
    05055                 } while ((*buf1++ == cp) && (--cp_count));
    05056
    05057                 return (*--buf1) - cp;
    05058         }
    05059
    05060         // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
    05061         size_type find_codepoint(const std::string& str, utf32 code_point) const
    05062         {
    05063                 size_type idx = 0, sze = (size_type)str.size();
    05064
    05065                 while (idx != sze)
    05066                 {
    05067                         if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
    05068                                 return idx;
    05069
    05070                         ++idx;
    05071                 }
    05072
    05073                 return npos;
    05074         }
    05075
    05076         // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none.  len is in code points.
    05077         size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
    05078         {
    05079                 size_type idx = 0;
    05080
    05081                 utf32   cp;
    05082                 utf8    cu;
    05083
    05084                 while (idx != len) {
    05085                         cu = *str++;
    05086
    05087                         if (cu < 0x80)
    05088                         {
    05089                                 cp = (utf32)(cu);
    05090                         }
    05091                         else if (cu < 0xE0)
    05092                         {
    05093                                 cp = ((cu & 0x1F) << 6);
    05094                                 cp |= (*str++ & 0x3F);
    05095                         }
    05096                         else if (cu < 0xF0)
    05097                         {
    05098                                 cp = ((cu & 0x0F) << 12);
    05099                                 cp |= ((*str++ & 0x3F) << 6);
    05100                                 cp |= (*str++ & 0x3F);
    05101                         }
    05102                         else
    05103                         {
    05104                                 cp = ((cu & 0x07) << 18);
    05105                                 cp |= ((*str++ & 0x3F) << 12);
    05106                                 cp |= ((*str++ & 0x3F) << 6);
    05107                                 cp |= (*str++ & 0x3F);
    05108                         }
    05109
    05110                         if (code_point == cp)
    05111                                 return idx;
    05112
    05113                         ++idx;
    05114                 }
    05115
    05116                 return npos;
    05117         }
    05118
    05119
    05120         // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
    05121         size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
    05122         {
    05123                 for (size_type idx = 0; idx != chars_len; ++idx)
    05124                 {
    05125                         if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
    05126                                 return idx;
    05127                 }
    05128
    05129                 return npos;
    05130         }
    05131
    05132 };
    05133
    05134
    05136 // Comparison operators
    05138
    05142 bool CEGUIEXPORT        operator==(const String& str1, const String& str2);
    05143
    05148 bool CEGUIEXPORT        operator==(const String& str, const std::string& std_str);
    05149
    05154 bool CEGUIEXPORT        operator==(const std::string& std_str, const String& str);
    05155
    05160 bool CEGUIEXPORT        operator==(const String& str, const utf8* utf8_str);
    05161
    05166 bool CEGUIEXPORT        operator==(const utf8* utf8_str, const String& str);
    05167
    05172 bool CEGUIEXPORT        operator!=(const String& str1, const String& str2);
    05173
    05178 bool CEGUIEXPORT        operator!=(const String& str, const std::string& std_str);
    05179
    05184 bool CEGUIEXPORT        operator!=(const std::string& std_str, const String& str);
    05185
    05190 bool CEGUIEXPORT        operator!=(const String& str, const utf8* utf8_str);
    05191
    05196 bool CEGUIEXPORT        operator!=(const utf8* utf8_str, const String& str);
    05197
    05202 bool CEGUIEXPORT        operator<(const String& str1, const String& str2);
    05203
    05208 bool CEGUIEXPORT        operator<(const String& str, const std::string& std_str);
    05209
    05214 bool CEGUIEXPORT        operator<(const std::string& std_str, const String& str);
    05215
    05220 bool CEGUIEXPORT        operator<(const String& str, const utf8* utf8_str);
    05221
    05226 bool CEGUIEXPORT        operator<(const utf8* utf8_str, const String& str);
    05227
    05232 bool CEGUIEXPORT        operator>(const String& str1, const String& str2);
    05233
    05238 bool CEGUIEXPORT        operator>(const String& str, const std::string& std_str);
    05239
    05244 bool CEGUIEXPORT        operator>(const std::string& std_str, const String& str);
    05245
    05250 bool CEGUIEXPORT        operator>(const String& str, const utf8* utf8_str);
    05251
    05256 bool CEGUIEXPORT        operator>(const utf8* utf8_str, const String& str);
    05257
    05262 bool CEGUIEXPORT        operator<=(const String& str1, const String& str2);
    05263
    05268 bool CEGUIEXPORT        operator<=(const String& str, const std::string& std_str);
    05269
    05274 bool CEGUIEXPORT        operator<=(const std::string& std_str, const String& str);
    05275
    05280 bool CEGUIEXPORT        operator<=(const String& str, const utf8* utf8_str);
    05281
    05286 bool CEGUIEXPORT        operator<=(const utf8* utf8_str, const String& str);
    05287
    05292 bool CEGUIEXPORT        operator>=(const String& str1, const String& str2);
    05293
    05298 bool CEGUIEXPORT        operator>=(const String& str, const std::string& std_str);
    05299
    05304 bool CEGUIEXPORT        operator>=(const std::string& std_str, const String& str);
    05305
    05310 bool CEGUIEXPORT        operator>=(const String& str, const utf8* utf8_str);
    05311
    05316 bool CEGUIEXPORT        operator>=(const utf8* utf8_str, const String& str);
    05317
    05322 bool CEGUIEXPORT        operator==(const String& str, const char* c_str);
    05323
    05328 bool CEGUIEXPORT        operator==(const char* c_str, const String& str);
    05329
    05334 bool CEGUIEXPORT        operator!=(const String& str, const char* c_str);
    05335
    05340 bool CEGUIEXPORT        operator!=(const char* c_str, const String& str);
    05341
    05346 bool CEGUIEXPORT        operator<(const String& str, const char* c_str);
    05347
    05352 bool CEGUIEXPORT        operator<(const char* c_str, const String& str);
    05353
    05358 bool CEGUIEXPORT        operator>(const String& str, const char* c_str);
    05359
    05364 bool CEGUIEXPORT        operator>(const char* c_str, const String& str);
    05365
    05370 bool CEGUIEXPORT        operator<=(const String& str, const char* c_str);
    05371
    05376 bool CEGUIEXPORT        operator<=(const char* c_str, const String& str);
    05377
    05382 bool CEGUIEXPORT        operator>=(const String& str, const char* c_str);
    05383
    05388 bool CEGUIEXPORT        operator>=(const char* c_str, const String& str);
    05389
    05391 // Concatenation operator functions
    05393
    05408 String CEGUIEXPORT      operator+(const String& str1, const String& str2);
    05409
    05425 String CEGUIEXPORT      operator+(const String& str, const std::string& std_str);
    05426
    05442 String CEGUIEXPORT      operator+(const std::string& std_str, const String& str);
    05443
    05459 String CEGUIEXPORT      operator+(const String& str, const utf8* utf8_str);
    05460
    05476 String CEGUIEXPORT      operator+(const utf8* utf8_str, const String& str);
    05477
    05493 String CEGUIEXPORT      operator+(const String& str, utf32 code_point);
    05494
    05510 String CEGUIEXPORT      operator+(utf32 code_point, const String& str);
    05511
    05527 String CEGUIEXPORT      operator+(const String& str, const char* c_str);
    05528
    05544 String CEGUIEXPORT      operator+(const char* c_str, const String& str);
    05545
    05546
    05548 // Output (stream) functions
    05550 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
    05551
    05552
    05554 // Modifying operations
    05556
    05569 void CEGUIEXPORT swap(String& str1, String& str2);
    05570
    05571
    05572 } // End of  CEGUI namespace section
    05573
    05574
    05575 #endif  // end of guard _CEGUIString_h_