Crazy Eddies GUI System: CEGUIString.h Source File

Crazy Eddies GUI System 0.7.6

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List

CEGUIString.h

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