source: GTP/trunk/App/Demos/Geom/OgreStuff/include/CEGUI/CEGUIString.h @ 1092

Revision 1092, 148.1 KB checked in by gumbau, 18 years ago (diff)

LodStrips? and LODTrees demos

Line 
1/************************************************************************
2        filename:       CEGUIString.h
3        created:        26/2/2004
4        author:         Paul D Turner
5       
6        purpose:        Defines string class used within the GUI system.
7*************************************************************************/
8/*************************************************************************
9    Crazy Eddie's GUI System (http://www.cegui.org.uk)
10    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
11
12    This library is free software; you can redistribute it and/or
13    modify it under the terms of the GNU Lesser General Public
14    License as published by the Free Software Foundation; either
15    version 2.1 of the License, or (at your option) any later version.
16
17    This library is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    Lesser General Public License for more details.
21
22    You should have received a copy of the GNU Lesser General Public
23    License along with this library; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25*************************************************************************/
26#ifndef _CEGUIString_h_
27#define _CEGUIString_h_
28
29#include "CEGUIBase.h"
30#include <string>
31#include <string.h>
32#include <stdexcept>
33
34// Start of CEGUI namespace section
35namespace CEGUI
36{
37#define STR_QUICKBUFF_SIZE      32
38        /*************************************************************************
39                Basic Types
40        *************************************************************************/
41        typedef         uint8   utf8;
42        //typedef               uint16  utf16;  // removed typedef to prevent usage, as utf16 is not supported (yet)
43        typedef         uint32  utf32;
44
45/*!
46\brief
47        String class used within the GUI system.
48
49        For the most part, this class can replace std::string in basic usage.  However, currently String does not use the
50        current locale, and also comparisons do not take into account the Unicode data tables, so are not 'correct'
51        as such.
52*/
53class CEGUIEXPORT String
54{
55public:
56        /*************************************************************************
57                Integral Types
58        *************************************************************************/
59        typedef         utf32                   value_type;                                     //!< Basic 'code point' type used for String (utf32)
60        typedef         size_t                  size_type;                                      //!< Unsigned type used for size values and indices
61        typedef         ptrdiff_t               difference_type;                        //!< Signed type used for differences
62        typedef         utf32&                  reference;                                      //!< Type used for utf32 code point references
63        typedef         const utf32&    const_reference;                        //!< Type used for constant utf32 code point references
64        typedef         utf32*                  pointer;                                        //!< Type used for utf32 code point pointers
65        typedef         const utf32*    const_pointer;                          //!< Type used for constant utf32 code point pointers
66
67        static const size_type          npos;                                           //!< Value used to represent 'not found' conditions and 'all code points' etc.
68
69private:
70        /*************************************************************************
71                Implementation data
72        *************************************************************************/
73        size_type       d_cplength;                     //!< holds length of string in code points (not including null termination)
74        size_type       d_reserve;                      //!< code point reserve size (currently allocated buffer size in code points).
75
76        mutable utf8*           d_encodedbuff;          //!< holds string data encoded as utf8 (generated only by calls to c_str() and data())
77        mutable size_type       d_encodeddatlen;        //!< holds length of encoded data (in case it's smaller than buffer).
78        mutable size_type       d_encodedbufflen;       //!< length of above buffer (since buffer can be bigger then the data it holds to save re-allocations).
79
80        utf32           d_quickbuff[STR_QUICKBUFF_SIZE];        //!< This is a integrated 'quick' buffer to save allocations for smallish strings
81        utf32*          d_buffer;                                                       //!< Pointer the the main buffer memory.  This is only valid when quick-buffer is not being used
82
83public:
84        /*************************************************************************
85                Iterator Classes
86        *************************************************************************/
87        /*!
88        \brief
89                Constant forward iterator class for String objects
90        */
91#if defined(_MSC_VER) && (_MSC_VER <= 1200)
92        class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32>
93#else
94        class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32, std::ptrdiff_t, const utf32*, const utf32&>
95#endif
96        {
97
98        public:
99                //////////////////////////////////////////////////////////////////////////
100                // data
101                //////////////////////////////////////////////////////////////////////////
102                const utf32*    d_ptr;
103
104
105                //////////////////////////////////////////////////////////////////////////
106                // Methods
107                //////////////////////////////////////////////////////////////////////////
108                const_iterator(void)
109                {
110                        d_ptr = 0;
111                }
112                const_iterator(const_pointer ptr)
113                {
114                        d_ptr = ptr;
115                }
116
117                const_reference operator*() const
118                {
119                        return *d_ptr;
120                }
121
122#if defined(_MSC_VER) && (_MSC_VER <= 1200)
123#       pragma warning (push)
124#       pragma warning (disable : 4284)
125#endif
126                const_pointer   operator->() const             
127                {
128                        return &**this;
129                }
130
131#if defined(_MSC_VER) && (_MSC_VER <= 1200)
132#       pragma warning (pop)
133#endif
134
135                const_iterator& operator++()
136                {
137                        ++d_ptr;
138                        return *this;
139                }
140
141                const_iterator  operator++(int)         
142                {
143                        const_iterator temp = *this;
144                        ++*this;
145                        return temp;
146                }
147
148                const_iterator& operator--()
149                {
150                        --d_ptr;
151                        return *this;
152                }
153
154                const_iterator  operator--(int)         
155                {
156                        const_iterator temp = *this;
157                        --*this;
158                        return temp;
159                }
160
161                const_iterator& operator+=(difference_type offset)
162                {
163                        d_ptr += offset;
164                        return *this;
165                }
166
167                const_iterator operator+(difference_type offset) const
168                {
169                        const_iterator temp = *this;
170                        return temp += offset;
171                }
172
173                const_iterator& operator-=(difference_type offset)
174                {
175                        return *this += -offset;
176                }
177
178                const_iterator operator-(difference_type offset) const
179                {
180                        const_iterator temp = *this;
181                        return temp -= offset;
182                }
183
184                difference_type operator-(const const_iterator& iter) const
185                {
186                        return d_ptr - iter.d_ptr;
187                }
188
189                const_reference operator[](difference_type offset) const
190                {
191                        return *(*this + offset);
192                }
193
194                bool operator==(const const_iterator& iter) const
195                {
196                        return d_ptr == iter.d_ptr;
197                }
198
199                bool operator!=(const const_iterator& iter) const
200                {
201                        return !(*this == iter);
202                }
203
204                bool operator<(const const_iterator& iter) const
205                {
206                        return d_ptr < iter.d_ptr;
207                }
208
209                bool operator>(const const_iterator& iter) const
210                {
211                        return (!(iter < *this));
212                }
213
214                bool operator<=(const const_iterator& iter) const
215                {
216                        return (!(iter < *this));
217                }
218
219                bool operator>=(const const_iterator& iter) const
220                {
221                        return (!(*this < iter));
222                }
223
224                friend const_iterator operator+(difference_type offset, const const_iterator& iter)
225                {
226                        return iter + offset;
227                }
228
229        };
230
231        /*!
232        \brief
233                Forward iterator class for String objects
234        */
235        class iterator : public const_iterator
236        {
237        public:
238                iterator(void) {}
239                iterator(pointer ptr) : const_iterator(ptr) {}
240
241
242                reference operator*() const
243                {
244                        return ((reference)**(const_iterator *)this);
245                }
246
247#if defined(_MSC_VER) && (_MSC_VER <= 1200)
248#       pragma warning (push)
249#       pragma warning (disable : 4284)
250#endif
251
252                pointer operator->() const
253                {
254                        return &**this;
255                }
256
257#if defined(_MSC_VER) && (_MSC_VER <= 1200)
258#       pragma warning (pop)
259#endif
260
261                iterator& operator++()
262                {
263                        ++this->d_ptr;
264                        return *this;
265                }
266
267                iterator operator++(int)
268                {
269                        iterator temp = *this;
270                        ++*this;
271                        return temp;
272                }
273
274                iterator& operator--()
275                {
276                        --this->d_ptr;
277                        return *this;
278                }
279
280                iterator operator--(int)
281                {
282                        iterator temp = *this;
283                        --*this;
284                        return temp;
285                }
286
287                iterator& operator+=(difference_type offset)
288                {
289                        this->d_ptr += offset;
290                        return *this;
291                }
292
293                iterator operator+(difference_type offset) const
294                {
295                        iterator temp = *this;
296                        return temp + offset;
297                }
298
299                iterator& operator-=(difference_type offset)
300                {
301                        return *this += -offset;
302                }
303
304                iterator operator-(difference_type offset) const
305                {
306                        iterator temp = *this;
307                        return temp -= offset;
308                }
309
310                difference_type operator-(const const_iterator& iter) const
311                {
312                        return ((const_iterator)*this - iter);
313                }
314
315                reference operator[](difference_type offset) const
316                {
317                        return *(*this + offset);
318                }
319
320                friend iterator operator+(difference_type offset, const iterator& iter)
321                {
322                        return iter + offset;
323                }
324
325        };
326
327        /*!
328        \brief
329                Constant reverse iterator class for String objects
330        */
331#if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
332        typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type>  const_reverse_iterator;
333#else
334        typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
335#endif
336
337        /*!
338        \brief
339                Reverse iterator class for String objects
340        */
341#if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
342        typedef std::reverse_iterator<iterator, pointer, reference, difference_type>                    reverse_iterator;
343#else
344        typedef std::reverse_iterator<iterator>                 reverse_iterator;
345#endif
346
347public:
348        //////////////////////////////////////////////////////////////////////////
349        // Default Construction and Destructor
350        //////////////////////////////////////////////////////////////////////////
351        /*!
352        \brief
353                Constructs an empty string
354        */
355        String(void)
356        {
357                init();
358        }
359
360        /*!
361        \brief
362                Destructor for String objects
363        */
364        ~String(void);
365
366        //////////////////////////////////////////////////////////////////////////
367        // Construction via CEGUI::String
368        //////////////////////////////////////////////////////////////////////////
369        /*!
370        \brief
371                Copy constructor - Creates a new string with the same value as \a str
372
373        \param str
374                String object used to initialise the newly created string
375
376        \return
377                Nothing
378        */
379        String(const String& str)
380        {
381                init();
382                assign(str);
383        }
384       
385
386        /*!
387        \brief
388                Constructs a new string initialised with code points from another String object.
389
390        \param str
391                String object used to initialise the newly created string
392
393        \param str_idx
394                Starting code-point of \a str to be used when initialising the new String
395
396        \param str_num
397                Maximum number of code points from \a str that are to be assigned to the new String
398
399        \return
400                Nothing
401        */
402        String(const String& str, size_type str_idx, size_type str_num = npos)
403        {
404                init();
405                assign(str, str_idx, str_num);
406        }
407
408        //////////////////////////////////////////////////////////////////////////
409        // Construction via std::string
410        //////////////////////////////////////////////////////////////////////////
411        /*!
412        \brief
413                Constructs a new string and initialises it using the std::string std_str
414
415        \param std_str
416                The std::string object that is to be used to initialise the new String object.
417
418        \note
419                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
420                the provided data will occur.
421
422        \return
423                Nothing
424
425        \exception std::length_error    Thrown if resulting String object would be too big.
426        */
427        String(const std::string& std_str)
428        {
429                init();
430                assign(std_str);
431        }
432               
433        /*!
434        \brief
435                Constructs a new string initialised with characters from the given std::string object.
436
437        \param std_str
438                std::string object used to initialise the newly created string
439
440        \param str_idx
441                Starting character of \a std_str to be used when initialising the new String
442
443        \note
444                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
445                the provided data will occur.
446
447        \param str_num
448                Maximum number of characters from \a std_str that are to be assigned to the new String
449
450        \return
451                Nothing
452
453        \exception std::length_error    Thrown if resulting String object would be too big.
454        */
455        String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
456        {
457                init();
458                assign(std_str, str_idx, str_num);
459        }
460
461
462        //////////////////////////////////////////////////////////////////////////
463        // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
464        //////////////////////////////////////////////////////////////////////////
465        /*!
466        \brief
467                Constructs a new String object and initialise it using the provided utf8 encoded string buffer.
468
469        \param utf8_str
470                Pointer to a buffer containing a null-terminated Unicode string encoded as utf8 data.
471
472        \note
473                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
474                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
475                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
476                results.
477
478        \return
479                Nothing
480
481        \exception std::length_error    Thrown if resulting String object would be too big.
482        */
483        String(const utf8* utf8_str)
484        {
485                init();
486                assign(utf8_str);
487        }
488
489        /*!
490        \brief
491                Constructs a new String object and initialise it using the provided utf8 encoded string buffer.
492
493                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
494                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
495                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
496                results.
497
498        \param utf8_str
499                Pointer to a buffer containing Unicode string data encoded as utf8.
500
501        \note
502                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
503                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
504                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
505                results.
506
507        \param chars_len
508                Length of the provided utf8 string in code units (not code-points).
509
510        \return
511                Nothing
512
513        \exception std::length_error    Thrown if resulting String object would be too big.
514        */
515        String(const utf8* utf8_str, size_type chars_len)
516        {
517                init();
518                assign(utf8_str, chars_len);
519        }
520
521        //////////////////////////////////////////////////////////////////////////
522        // Construction via code-point (using a UTF-32 code unit)
523        //////////////////////////////////////////////////////////////////////////
524        /*!
525        \brief
526                Constructs a new String that is initialised with the specified code point
527
528        \param num
529                The number of times \a code_point is to be put into new String object
530
531        \param code_point
532                The Unicode code point to be used when initialising the String object
533
534        \return
535                Nothing
536
537        \exception std::length_error    Thrown if resulting String object would be too big.
538        */
539        String(size_type num, utf32 code_point)
540        {
541                init();
542                assign(num, code_point);
543        }
544
545        //////////////////////////////////////////////////////////////////////////
546        // Construction via iterator
547        //////////////////////////////////////////////////////////////////////////
548        // Create string with characters in the range [beg, end)
549        /*!
550        \brief
551                Construct a new string object and initialise it with code-points from the range [beg, end).
552
553        \param beg
554                Iterator describing the start of the data to be used when initialising the String object
555
556        \param end
557                Iterator describing the (exclusive) end of the data to be used when initialising the String object
558
559        \return
560                Nothing
561        */
562        String(const_iterator beg, const_iterator end)
563        {
564                init();
565                append(beg, end);
566        }
567
568
569        //////////////////////////////////////////////////////////////////////////
570        // Construction via c-string
571        //////////////////////////////////////////////////////////////////////////
572        /*!
573        \brief
574                Constructs a new String object and initialise it using the provided c-string.
575
576        \param c_str
577                Pointer to a c-string.
578
579        \return
580                Nothing
581
582        \exception std::length_error    Thrown if resulting String object would be too big.
583        */
584        String(const char* c_str)
585        {
586                init();
587                assign(c_str);
588        }
589
590        /*!
591        \brief
592                Constructs a new String object and initialise it using characters from the provided char array.
593
594        \param chars
595                char array.
596
597        \param chars_len
598                Number of chars from the array to be used.
599
600        \return
601                Nothing
602
603        \exception std::length_error    Thrown if resulting String object would be too big.
604        */
605        String(const char* chars, size_type chars_len)
606        {
607                init();
608                assign(chars, chars_len);
609        }
610
611
612        //////////////////////////////////////////////////////////////////////////
613        // Size operations
614        //////////////////////////////////////////////////////////////////////////
615        /*!
616        \brief
617                Returns the size of the String in code points
618
619        \return
620                Number of code points currently in the String
621        */
622        size_type       size(void) const
623        {
624                return d_cplength;
625        }
626
627        /*!
628        \brief
629                Returns the size of the String in code points
630
631        \return
632                Number of code points currently in the String
633        */
634        size_type       length(void) const
635        {
636                return d_cplength;
637        }
638
639        /*!
640        \brief
641                Returns true if the String is empty
642
643        \return
644                true if the String is empty, else false.
645        */
646        bool    empty(void) const
647        {
648                return  (d_cplength == 0);
649        }
650
651        /*!
652        \brief
653                Returns the maximum size of a String.
654
655                Any operation that would result in a String that is larger than this value will throw the std::length_error exception.
656
657        \return
658                The maximum number of code points that a string can contain
659        */
660        static size_type        max_size(void)
661        {
662                return (((size_type)-1) / sizeof(utf32));
663        }
664
665        //////////////////////////////////////////////////////////////////////////
666        // Capacity Operations
667        //////////////////////////////////////////////////////////////////////////
668        // return the number of code points the string could hold without re-allocation
669        // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
670        /*!
671        \brief
672                Return the number of code points that the String could hold before a re-allocation would be required.
673
674        \return
675                Size of the current reserve buffer.  This is the maximum number of code points the String could hold before a buffer
676                re-allocation would be required
677        */
678        size_type capacity(void) const
679        {
680                return d_reserve - 1;
681        }
682
683        // reserve internal memory for at-least 'num' code-points (characters).  if num is 0, request is shrink-to-fit.
684        /*!
685        \brief
686                Specifies the amount of reserve capacity to allocate.
687
688        \param num
689                The number of code points to allocate space for.  If \a num is larger that the current reserve, then a re-allocation will occur.  If
690                \a num is smaller than the current reserve (but not 0) the buffer may be shrunk to the larger of the specified number, or the current
691                String size (operation is currently not implemented).  If \a num is 0, then the buffer is re-allocated to fit the current String size.
692
693        \return
694                Nothing
695
696        \exception std::length_error    Thrown if resulting String object would be too big.
697        */
698        void    reserve(size_type num = 0)
699        {
700                if (num == 0)
701                        trim();
702                else
703                        grow(num);
704        }
705
706        //////////////////////////////////////////////////////////////////////////
707        // Comparisons
708        //////////////////////////////////////////////////////////////////////////
709        /*!
710        \brief
711                Compares this String with the String 'str'.
712
713        \note
714                This does currently not properly consider Unicode and / or the system locale.
715
716        \param str
717                The String object that is to compared with this String.
718
719        \return
720                -  0 if the String objects are equal
721                - <0 if this String is lexicographically smaller than \a str
722                - >0 if this String is lexicographically greater than \a str
723        */
724        int             compare(const String& str) const
725        {
726                return compare(0, d_cplength, str);
727        }
728
729        /*!
730        \brief
731                Compares code points from this String with code points from the String 'str'.
732
733        \note
734                This does currently not properly consider Unicode and / or the system locale.
735
736        \param idx
737                Index of the first code point from this String to consider.
738
739        \param len
740                Maximum number of code points from this String to consider.
741
742        \param str
743                The String object that is to compared with this String.
744
745        \param str_idx
746                Index of the first code point from String \a str to consider.
747
748        \param str_len
749                Maximum number of code points from String \a str to consider
750
751        \return
752                -  0 if the specified sub-strings are equal
753                - <0 if specified sub-strings are lexicographically smaller than \a str
754                - >0 if specified sub-strings are lexicographically greater than \a str
755
756        \exception std::out_of_range    Thrown if either \a idx or \a str_idx are invalid.
757        */
758        int             compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
759        {
760                if ((d_cplength < idx) || (str.d_cplength < str_idx))
761                        throw std::out_of_range("Index is out of range for CEGUI::String");
762
763                if ((len == npos) || (idx + len > d_cplength))
764                        len = d_cplength - idx;
765
766                if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
767                        str_len = str.d_cplength - str_idx;
768
769                int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
770
771                return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
772        }
773
774
775        /*!
776        \brief
777                Compares this String with the std::string 'std_str'.
778
779        \note
780                This does currently not properly consider Unicode and / or the system locale.
781
782        \param std_str
783                The std::string object that is to compared with this String.
784
785        \note
786                Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
787                the encountered data is performed.
788
789        \return
790                -  0 if the string objects are equal
791                - <0 if this string is lexicographically smaller than \a std_str
792                - >0 if this string is lexicographically greater than \a std_str
793        */
794        int             compare(const std::string& std_str) const
795        {
796                return compare(0, d_cplength, std_str);
797        }
798
799
800        /*!
801        \brief
802                Compares code points from this String with code points from the std::string 'std_str'.
803
804        \note
805                This does currently not properly consider Unicode and / or the system locale.
806
807        \param idx
808                Index of the first code point from this String to consider.
809
810        \param len
811                Maximum number of code points from this String to consider.
812
813        \param std_str
814                The std::string object that is to compared with this String.
815
816        \note
817                Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
818                the encountered data is performed.
819
820        \param str_idx
821                Index of the first character from std::string \a std_str to consider.
822
823        \param str_len
824                Maximum number of characters from std::string \a std_str to consider
825
826        \return
827                -  0 if the specified sub-strings are equal
828                - <0 if specified sub-strings are lexicographically smaller than \a std_str
829                - >0 if specified sub-strings are lexicographically greater than \a std_str
830
831        \exception std::out_of_range    Thrown if either \a idx or \a str_idx are invalid.
832        */
833        int             compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
834        {
835                if (d_cplength < idx)
836                        throw std::out_of_range("Index is out of range for CEGUI::String");
837
838                if (std_str.size() < str_idx)
839                        throw std::out_of_range("Index is out of range for std::string");
840
841                if ((len == npos) || (idx + len > d_cplength))
842                        len = d_cplength - idx;
843
844                if ((str_len == npos) || (str_idx + str_len > std_str.size()))
845                        str_len = (size_type)std_str.size() - str_idx;
846
847                int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
848
849                return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
850        }
851
852
853        /*!
854        \brief
855                Compares this String with the null-terminated utf8 encoded 'utf8_str'.
856
857        \note
858                This does currently not properly consider Unicode and / or the system locale.
859
860        \param utf8_str
861                The buffer containing valid Unicode data encoded as utf8 that is to compared with this String.
862
863        \note
864                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
865                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
866                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
867                results.
868
869        \return
870                -  0 if the strings are equal
871                - <0 if this string is lexicographically smaller than \a utf8_str
872                - >0 if this string is lexicographically greater than \a utf8_str
873        */
874        int             compare(const utf8* utf8_str) const
875        {
876                return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
877        }
878
879
880        /*!
881        \brief
882                Compares code points from this String with the null-terminated utf8 encoded 'utf8_str'.
883
884        \note
885                This does currently not properly consider Unicode and / or the system locale.
886
887        \param idx
888                Index of the first code point from this String to consider.
889
890        \param len
891                Maximum number of code points from this String to consider.
892
893        \param utf8_str
894                The buffer containing valid Unicode data encoded as utf8 that is to compared with this String.
895
896        \note
897                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
898                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
899                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
900                results.
901
902        \return
903                -  0 if the specified sub-strings are equal
904                - <0 if specified sub-strings are lexicographically smaller than \a utf8_str
905                - >0 if specified sub-strings are lexicographically greater than \a utf8_str
906
907        \exception std::out_of_range    Thrown if \a idx is invalid.
908        */
909        int             compare(size_type idx, size_type len, const utf8* utf8_str) const
910        {
911                return compare(idx, len, utf8_str, encoded_size(utf8_str));
912        }
913
914        /*!
915        \brief
916                Compares code points from this String with the utf8 encoded data in buffer 'utf8_str'.
917
918        \note
919                This does currently not properly consider Unicode and / or the system locale.
920
921        \param idx
922                Index of the first code point from this String to consider.
923
924        \param len
925                Maximum number of code points from this String to consider.
926
927        \param utf8_str
928                The buffer containing valid Unicode data encoded as utf8 that is to compared with this String.
929
930        \note
931                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
932                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
933                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
934                results.
935
936        \param str_cplen
937                The number of encoded code points in the buffer \a utf8_str (this is not the same as the number of code units).
938
939        \return
940                -  0 if the specified sub-strings are equal
941                - <0 if specified sub-strings are lexicographically smaller than \a utf8_str
942                - >0 if specified sub-strings are lexicographically greater than \a utf8_str
943
944        \exception std::out_of_range    Thrown if \a idx is invalid.
945        \exception std::length_error    Thrown if \a str_cplen is set to npos.
946        */
947        int             compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
948        {
949                if (d_cplength < idx)
950                        throw std::out_of_range("Index is out of range for CEGUI::String");
951
952                if (str_cplen == npos)
953                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
954
955                if ((len == npos) || (idx + len > d_cplength))
956                        len = d_cplength - idx;
957
958                int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
959
960                return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
961        }
962
963
964        /*!
965        \brief
966                Compares this String with the given c-string.
967
968        \note
969                This does currently not properly consider Unicode and / or the system locale.
970
971        \param c_str
972                The c-string that is to compared with this String.
973
974        \return
975                -  0 if the strings are equal
976                - <0 if this string is lexicographically smaller than \a c_str
977                - >0 if this string is lexicographically greater than \a c_str
978        */
979        int             compare(const char* c_str) const
980        {
981                return compare(0, d_cplength, c_str, strlen(c_str));
982        }
983
984
985        /*!
986        \brief
987                Compares code points from this String with the given c-string.
988
989        \note
990                This does currently not properly consider Unicode and / or the system locale.
991
992        \param idx
993                Index of the first code point from this String to consider.
994
995        \param len
996                Maximum number of code points from this String to consider.
997
998        \param c_str
999                The c-string that is to compared with this String.
1000
1001        \return
1002                -  0 if the specified sub-strings are equal
1003                - <0 if specified sub-strings are lexicographically smaller than \a c_str
1004                - >0 if specified sub-strings are lexicographically greater than \a c_str
1005
1006        \exception std::out_of_range    Thrown if \a idx is invalid.
1007        */
1008        int             compare(size_type idx, size_type len, const char* c_str) const
1009        {
1010                return compare(idx, len, c_str, strlen(c_str));
1011        }
1012
1013
1014        /*!
1015        \brief
1016                Compares code points from this String with chars in the given char array.
1017
1018        \note
1019                This does currently not properly consider Unicode and / or the system locale.
1020
1021        \param idx
1022                Index of the first code point from this String to consider.
1023
1024        \param len
1025                Maximum number of code points from this String to consider.
1026
1027        \param chars
1028                The array containing the chars that are to compared with this String.
1029
1030        \param chars_len
1031                The number of chars in the array.
1032
1033        \return
1034                -  0 if the specified sub-strings are equal
1035                - <0 if specified sub-strings are lexicographically smaller than \a chars
1036                - >0 if specified sub-strings are lexicographically greater than \a chars
1037
1038        \exception std::out_of_range    Thrown if \a idx is invalid.
1039        \exception std::length_error    Thrown if \a chars_len is set to npos.
1040        */
1041        int             compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
1042        {
1043                if (d_cplength < idx)
1044                        throw std::out_of_range("Index is out of range for CEGUI::String");
1045
1046                if (chars_len == npos)
1047                        throw std::length_error("Length for char array can not be 'npos'");
1048
1049                if ((len == npos) || (idx + len > d_cplength))
1050                        len = d_cplength - idx;
1051
1052                int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
1053
1054                return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
1055        }
1056
1057
1058        //////////////////////////////////////////////////////////////////////////
1059        // Character access
1060        //////////////////////////////////////////////////////////////////////////
1061        /*!
1062        \brief
1063                Returns the code point at the given index.
1064
1065        \param idx
1066                Zero based index of the code point to be returned.
1067
1068        \note
1069                - For constant strings length()/size() provide a valid index and will access the default utf32 value.
1070                - For non-constant strings length()/size() is an invalid index, and acceesing (especially writing) this index could cause string corruption.
1071
1072        \return
1073                The utf32 code point at the given index within the String.
1074        */
1075        reference       operator[](size_type idx)
1076        {
1077                return (ptr()[idx]);
1078        }
1079
1080        /*!
1081        \brief
1082                Returns the code point at the given index.
1083
1084        \param idx
1085                Zero based index of the code point to be returned.
1086
1087        \note
1088                - For constant strings length()/size() provide a valid index and will access the default utf32 value.
1089                - For non-constant strings length()/size() is an invalid index, and acceesing (especially writing) this index could cause string corruption.
1090
1091        \return
1092                The utf32 code point at the given index within the String.
1093        */
1094        value_type      operator[](size_type idx) const
1095        {
1096                return ptr()[idx];
1097        }
1098
1099        /*!
1100        \brief
1101                Returns the code point at the given index.
1102
1103        \param idx
1104                Zero based index of the code point to be returned.
1105
1106        \return
1107                The utf32 code point at the given index within the String.
1108
1109        \exception std::out_of_range    Thrown if \a idx is >= length().
1110        */
1111        reference       at(size_type idx)
1112        {
1113                if (d_cplength <= idx)
1114                        throw std::out_of_range("Index is out of range for CEGUI::String");
1115
1116                return ptr()[idx];
1117        }
1118
1119        /*!
1120        \brief
1121                Returns the code point at the given index.
1122
1123        \param idx
1124                Zero based index of the code point to be returned.
1125
1126        \return
1127                The utf32 code point at the given index within the String.
1128
1129        \exception std::out_of_range    Thrown if \a idx is >= length().
1130        */
1131        const_reference at(size_type idx) const
1132        {
1133                if (d_cplength <= idx)
1134                        throw std::out_of_range("Index is out of range for CEGUI::String");
1135
1136                return ptr()[idx];
1137        }
1138
1139
1140        //////////////////////////////////////////////////////////////////////////
1141        // C-Strings and arrays
1142        //////////////////////////////////////////////////////////////////////////
1143        /*!
1144        \brief
1145                Returns contents of the String as a null terminated string of utf8 encoded data.
1146
1147        \return
1148                Pointer to a char buffer containing the contents of the String encoded as null-terminated utf8 data.
1149
1150        \note
1151                The buffer returned from this function is owned by the String object.
1152
1153        \note
1154                Any function that modifies the String data will invalidate the buffer returned by this call.
1155        */
1156        const char* c_str(void) const
1157        {
1158                return (const char*)build_utf8_buff();
1159        }
1160
1161        /*!
1162        \brief
1163                Returns contents of the String as utf8 encoded data.
1164
1165        \return
1166                Pointer to a buffer containing the contents of the String encoded utf8 data.
1167
1168        \note
1169                The buffer returned from this function is owned by the String object.
1170
1171        \note
1172                Any function that modifies the String data will invalidate the buffer returned by this call.
1173        */
1174        const utf8* data(void) const
1175        {
1176                return build_utf8_buff();
1177        }
1178
1179        // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
1180        // return number of utf8 code units placed into the buffer
1181        /*!
1182        \brief
1183                Copies an area of the String into the provided buffer as encoded utf8 data.
1184
1185        \param buf
1186                Pointer to a buffer that is to receive the encoded data (this must be big enough to hold the encoded data)
1187
1188        \param len
1189                Maximum number of code points from the String that should be encoded into the buffer
1190       
1191        \param idx
1192                Index of the first code point to be encoded into the buffer
1193
1194        \return
1195                The number of utf8 encoded code units transferred to the buffer.
1196
1197                \note A code unit does not equal a code point.  A utf32 code point, when encoded as utf8, can occupy between 1 and 4 code units.
1198
1199        \exception std::out_of_range    Thrown if \a idx was invalid for this String.
1200        */
1201        size_type       copy(utf8* buf, size_type len = npos, size_type idx = 0) const
1202        {
1203                if (d_cplength < idx)
1204                        throw std::out_of_range("Index is out of range for CEGUI::String");
1205
1206                if (len == npos)
1207                        len = d_cplength;
1208
1209                return encode(&ptr()[idx], buf, npos, len);
1210        }
1211
1212        //////////////////////////////////////////////////////////////////////////
1213        // UTF8 Encoding length information
1214        //////////////////////////////////////////////////////////////////////////
1215        // 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.
1216        /*!
1217        \brief
1218                Return the number of utf8 code units required to hold an area of the String when encoded as utf8 data
1219
1220        \param num
1221                Maximum number of code points to consider when calculating utf8 encoded size.
1222
1223        \param idx
1224                Index of the first code point to consider when calculating the utf8 encoded size
1225
1226        \return
1227                The number of utf8 code units (bytes) required to hold the specified sub-string when encoded as utf8 data.
1228
1229        \exception std::out_of_range    Thrown if \a idx was invalid for this String.
1230        */
1231        size_type       utf8_stream_len(size_type num = npos, size_type idx = 0)
1232        {
1233                using namespace std;
1234
1235                if (d_cplength < idx)
1236                        throw out_of_range("Index was out of range for CEGUI::String object");
1237
1238                size_type       maxlen = d_cplength - idx;
1239
1240                return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
1241        }
1242
1243        //////////////////////////////////////////////////////////////////////////
1244        // Assignment Functions
1245        //////////////////////////////////////////////////////////////////////////
1246        /*!
1247        \brief
1248                Assign the value of String \a str to this String
1249
1250        \param str
1251                String object containing the string value to be assigned.
1252
1253        \return
1254                This String after the assignment has happened
1255        */
1256        String& operator=(const String& str)
1257        {
1258                return assign(str);
1259        }
1260
1261        /*!
1262        \brief
1263                Assign a sub-string of String \a str to this String
1264
1265        \param str
1266                String object containing the string data to be assigned.
1267
1268        \param str_idx
1269                Index of the first code point in \a str that is to be assigned
1270
1271        \param str_num
1272                Maximum number of code points from \a str that are be be assigned
1273
1274        \return
1275                This String after the assignment has happened
1276
1277        \exception std::out_of_range    Thrown if str_idx is invalid for \a str
1278        */
1279        String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
1280        {
1281                if (str.d_cplength < str_idx)
1282                        throw std::out_of_range("Index was out of range for CEGUI::String object");
1283
1284                if (str_num == npos)
1285                        str_num = str.d_cplength - str_idx;
1286
1287                grow(str_num);
1288                setlen(str_num);
1289                memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
1290                return *this;
1291        }
1292
1293        /*!
1294        \brief
1295                Assign the value of std::string \a std_str to this String
1296
1297        \note
1298                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
1299                the provided data will occur.
1300
1301        \param std_str
1302                std::string object containing the string value to be assigned.
1303
1304        \return
1305                This String after the assignment has happened
1306
1307        \exception std::length_error    Thrown if the resulting String would have been too large.
1308        */
1309        String& operator=(const std::string& std_str)
1310        {
1311                return assign(std_str);
1312        }
1313
1314        /*!
1315        \brief
1316                Assign a sub-string of std::string \a std_str to this String
1317
1318        \note
1319                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
1320                the provided data will occur.
1321
1322        \param std_str
1323                std::string object containing the string value to be assigned.
1324
1325        \param str_idx
1326                Index of the first character of \a std_str to be assigned
1327
1328        \param str_num
1329                Maximum number of characters from \a std_str to be assigned
1330
1331        \return
1332                This String after the assignment has happened
1333
1334        \exception std::out_of_range    Thrown if \a str_idx is invalid for \a std_str
1335        \exception std::length_error    Thrown if the resulting String would have been too large.
1336        */
1337        String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1338        {
1339                if (std_str.size() < str_idx)
1340                        throw std::out_of_range("Index was out of range for std::string object");
1341
1342                if (str_num == npos)
1343                        str_num = (size_type)std_str.size() - str_idx;
1344
1345                grow(str_num);
1346                setlen(str_num);
1347
1348                while(str_num--)
1349                {
1350                        ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
1351                }
1352
1353                return *this;
1354        }
1355
1356        /*!
1357        \brief
1358                Assign to this String the string value represented by the given null-terminated utf8 encoded data
1359
1360        \note
1361                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
1362                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
1363                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
1364                results.
1365
1366        \param utf8_str
1367                Buffer containing valid null-terminated utf8 encoded data
1368
1369        \return
1370                This String after the assignment has happened
1371
1372        \exception std::length_error    Thrown if the resulting String would have been too large.
1373        */
1374        String& operator=(const utf8* utf8_str)
1375        {
1376                return assign(utf8_str, utf_length(utf8_str));
1377        }
1378
1379        /*!
1380        \brief
1381                Assign to this String the string value represented by the given null-terminated utf8 encoded data
1382
1383        \note
1384                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
1385                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
1386                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
1387                results.
1388
1389        \param utf8_str
1390                Buffer containing valid null-terminated utf8 encoded data
1391
1392        \return
1393                This String after the assignment has happened
1394
1395        \exception std::length_error    Thrown if the resulting String would have been too large.
1396        */
1397        String& assign(const utf8* utf8_str)
1398        {
1399                return assign(utf8_str, utf_length(utf8_str));
1400        }
1401
1402        /*!
1403        \brief
1404                Assign to this String the string value represented by the given utf8 encoded data
1405
1406        \note
1407                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
1408                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
1409                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
1410                results.
1411
1412        \param utf8_str
1413                Buffer containing valid utf8 encoded data
1414
1415        \param str_num
1416                Number of code units (not code points) in the buffer pointed to by \a utf8_str
1417
1418        \return
1419                This String after the assignment has happened
1420
1421        \exception std::length_error    Thrown if the resulting String would have been too large, or if str_num is 'npos'.
1422        */
1423        String& assign(const utf8* utf8_str, size_type str_num)
1424        {
1425                if (str_num == npos)
1426                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
1427
1428                size_type enc_sze = encoded_size(utf8_str, str_num);
1429
1430                grow(enc_sze);
1431                encode(utf8_str, ptr(), d_reserve, str_num);
1432                setlen(enc_sze);
1433                return *this;
1434        }
1435
1436        /*!
1437        \brief
1438                Assigns the specified utf32 code point to this String.  Result is always a String 1 code point in length.
1439
1440        \param code_point
1441                Valid utf32 Unicode code point to be assigned to the string
1442
1443        \return
1444                This String after assignment
1445        */
1446        String& operator=(utf32 code_point)
1447        {
1448                return assign(1, code_point);
1449        }
1450
1451        /*!
1452        \brief
1453                Assigns the specified code point repeatedly to the String
1454
1455        \param num
1456                The number of times to assign the code point
1457
1458        \param code_point
1459                Valid utf32 Unicode code point to be assigned to the string
1460
1461        \return
1462                This String after assignment.
1463
1464        \exception std::length_error    Thrown if \a num was 'npos'
1465        */
1466        String& assign(size_type num, utf32 code_point)
1467        {
1468                if (num == npos)
1469                        throw std::length_error("Code point count can not be 'npos'");
1470
1471                grow(num);
1472                setlen(num);
1473                utf32* p = ptr();
1474
1475                while(num--)
1476                        *p = code_point;
1477
1478                return *this;
1479        }
1480
1481
1482        /*!
1483        \brief
1484                Assign to this String the given C-string.
1485
1486        \param c_str
1487                Pointer to a valid C style string.
1488
1489        \return
1490                This String after the assignment has happened
1491
1492        \exception std::length_error    Thrown if the resulting String would have been too large.
1493        */
1494        String& operator=(const char* c_str)
1495        {
1496                return assign(c_str, strlen(c_str));
1497        }
1498
1499
1500        /*!
1501        \brief
1502                Assign to this String the given C-string.
1503
1504        \param c_str
1505                Pointer to a valid C style string.
1506
1507        \return
1508                This String after the assignment has happened
1509
1510        \exception std::length_error    Thrown if the resulting String would have been too large.
1511        */
1512        String& assign(const char* c_str)
1513        {
1514                return assign(c_str, strlen(c_str));
1515        }
1516
1517
1518        /*!
1519        \brief
1520                Assign to this String a number of chars from a char array.
1521
1522        \param chars
1523                char array.
1524
1525        \param chars_len
1526                Number of chars to be assigned.
1527
1528        \return
1529                This String after the assignment has happened
1530
1531        \exception std::length_error    Thrown if the resulting String would have been too large.
1532        */
1533        String& assign(const char* chars, size_type chars_len)
1534        {
1535                grow(chars_len);
1536                utf32* pt = ptr();
1537
1538                for (size_type i = 0; i < chars_len; ++i)
1539                {
1540                        *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
1541                }
1542
1543                setlen(chars_len);
1544                return *this;
1545        }
1546
1547
1548        /*!
1549        \brief
1550                Swaps the value of this String with the given String \a str
1551
1552        \param str
1553                String object whos value is to be swapped with this String.
1554
1555        \return
1556                Nothing
1557        */
1558        void    swap(String& str)
1559        {
1560                size_type       temp_len        = d_cplength;
1561                d_cplength = str.d_cplength;
1562                str.d_cplength = temp_len;
1563
1564                size_type       temp_res        = d_reserve;
1565                d_reserve = str.d_reserve;
1566                str.d_reserve = temp_res;
1567
1568                utf32*          temp_buf        = d_buffer;
1569                d_buffer = str.d_buffer;
1570                str.d_buffer = temp_buf;
1571
1572                // see if we need to swap 'quick buffer' data
1573                if (temp_res <= STR_QUICKBUFF_SIZE)
1574                {
1575                        utf32           temp_qbf[STR_QUICKBUFF_SIZE];
1576
1577                        memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
1578                        memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
1579                        memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
1580                }
1581
1582        }
1583
1584        //////////////////////////////////////////////////////////////////////////
1585        // Appending Functions
1586        //////////////////////////////////////////////////////////////////////////
1587        /*!
1588        \brief
1589                Appends the String \a str
1590
1591        \param str
1592                String object that is to be appended
1593
1594        \return
1595                This String after the append operation
1596
1597        \exception std::length_error    Thrown if resulting String would be too large.
1598        */
1599        String& operator+=(const String& str)
1600        {
1601                return append(str);
1602        }
1603
1604        /*!
1605        \brief
1606                Appends a sub-string of the String \a str
1607
1608        \param str
1609                String object containing data to be appended
1610
1611        \param str_idx
1612                Index of the first code point to be appended
1613
1614        \param str_num
1615                Maximum number of code points to be appended
1616
1617        \return
1618                This String after the append operation
1619
1620        \exception std::out_of_range    Thrown if \a str_idx is invalid for \a str.
1621        \exception std::length_error    Thrown if resulting String would be too large.
1622        */
1623        String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
1624        {
1625                if (str.d_cplength < str_idx)
1626                        throw std::out_of_range("Index is out of range for CEGUI::String");
1627
1628                if (str_num == npos)
1629                        str_num = str.d_cplength - str_idx;
1630
1631                grow(d_cplength + str_num);
1632                memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
1633                setlen(d_cplength + str_num);
1634                return *this;
1635        }
1636
1637
1638        /*!
1639        \brief
1640                Appends the std::string \a std_str
1641
1642        \param std_str
1643                std::string object that is to be appended
1644
1645        \note
1646                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
1647                the provided data will occur.
1648
1649        \return
1650                This String after the append operation
1651
1652        \exception std::length_error    Thrown if resulting String would be too large.
1653        */
1654        String& operator+=(const std::string& std_str)
1655        {
1656                return append(std_str);
1657        }
1658
1659        /*!
1660        \brief
1661                Appends a sub-string of the std::string \a std_str
1662
1663        \param std_str
1664                std::string object containing data to be appended
1665
1666        \note
1667                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
1668                the provided data will occur.
1669
1670        \param str_idx
1671                Index of the first character to be appended
1672
1673        \param str_num
1674                Maximum number of characters to be appended
1675
1676        \return
1677                This String after the append operation
1678
1679        \exception std::out_of_range    Thrown if \a str_idx is invalid for \a std_str.
1680        \exception std::length_error    Thrown if resulting String would be too large.
1681        */
1682        String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1683        {
1684                if (std_str.size() < str_idx)
1685                        throw std::out_of_range("Index is out of range for std::string");
1686
1687                if (str_num == npos)
1688                        str_num = (size_type)std_str.size() - str_idx;
1689
1690                size_type newsze = d_cplength + str_num;
1691
1692                grow(newsze);
1693                utf32* pt = &ptr()[newsze-1];
1694
1695                while(str_num--)
1696                        *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
1697
1698                setlen(newsze);
1699                return *this;
1700        }
1701
1702
1703        /*!
1704        \brief
1705                Appends to the String the null-terminated utf8 encoded data in the buffer utf8_str.
1706
1707        \param utf8_str
1708                buffer holding the null-terminated utf8 encoded data that is to be appended
1709
1710        \note
1711                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
1712                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
1713                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
1714                results.
1715
1716        \return
1717                This String after the append operation
1718
1719        \exception std::length_error    Thrown if resulting String would be too large.
1720        */
1721        String& operator+=(const utf8* utf8_str)
1722        {
1723                return append(utf8_str, utf_length(utf8_str));
1724        }
1725
1726        /*!
1727        \brief
1728                Appends to the String the null-terminated utf8 encoded data in the buffer utf8_str.
1729
1730        \param utf8_str
1731                Buffer holding the null-terminated utf8 encoded data that is to be appended
1732
1733        \note
1734                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
1735                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
1736                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
1737                results.
1738
1739        \return
1740                This String after the append operation
1741
1742        \exception std::length_error    Thrown if resulting String would be too large.
1743        */
1744        String& append(const utf8* utf8_str)
1745        {
1746                return append(utf8_str, utf_length(utf8_str));
1747        }
1748
1749
1750        /*!
1751        \brief
1752                Appends to the String the utf8 encoded data in the buffer utf8_str.
1753
1754        \param utf8_str
1755                Buffer holding the utf8 encoded data that is to be appended
1756
1757        \note
1758                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
1759                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
1760                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
1761                results.
1762
1763        \param len
1764                Number of code units (not code points) in the buffer to be appended
1765
1766        \return
1767                This String after the append operation
1768
1769        \exception std::length_error    Thrown if resulting String would be too large, or if \a len was 'npos'
1770        */
1771        String& append(const utf8* utf8_str, size_type len)
1772        {
1773                if (len == npos)
1774                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
1775
1776                size_type encsz = encoded_size(utf8_str, len);
1777                size_type newsz = d_cplength + encsz;
1778
1779                grow(newsz);
1780                encode(utf8_str, &ptr()[d_cplength], encsz, len);
1781                setlen(newsz);
1782
1783                return *this;
1784        }
1785
1786
1787        /*!
1788        \brief
1789                Appends a single code point to the string
1790
1791        \param code_point
1792                utf32 Unicode code point that is to be appended
1793
1794        \return
1795                This String after the append operation
1796
1797        \exception std::length_error    Thrown if resulting String would be too long.
1798        */
1799        String& operator+=(utf32 code_point)
1800        {
1801                return append(1, code_point);
1802        }
1803
1804        /*!
1805        \brief
1806                Appends a single code point multiple times to the string
1807
1808        \param num
1809                Number of copies of the code point to be appended
1810
1811        \param code_point
1812                utf32 Unicode code point that is to be appended
1813
1814        \return
1815                This String after the append operation
1816
1817        \exception std::length_error    Thrown if resulting String would be too long, or if \a num was 'npos'.
1818        */
1819        String& append(size_type num, utf32 code_point)
1820        {
1821                if (num == npos)
1822                        throw std::length_error("Code point count can not be 'npos'");
1823
1824                size_type newsz = d_cplength + num;
1825                grow(newsz);
1826
1827                utf32* p = &ptr()[d_cplength];
1828
1829                while(num--)
1830                        *p++ = code_point;
1831
1832                setlen(newsz);
1833
1834                return *this;
1835        }
1836
1837        /*!
1838        \brief
1839                Appends a single code point to the string
1840
1841        \param code_point
1842                utf32 Unicode code point that is to be appended
1843
1844        \return
1845                Nothing
1846
1847        \exception std::length_error    Thrown if resulting String would be too long.
1848        */
1849        void    push_back(utf32 code_point)
1850        {
1851                append(1, code_point);
1852        }
1853
1854        /*!
1855        \brief
1856                Appends the code points in the reange [beg, end)
1857
1858        \param beg
1859                Iterator describing the start of the range to be appended
1860
1861        \param end
1862                Iterator describing the (exclusive) end of the range to be appended.
1863
1864        \return
1865                This String after the append operation
1866
1867        \exception std::length_error    Thrown if the resulting string would be too large.
1868        */
1869        String& append(const_iterator beg, const_iterator end)
1870        {
1871                return replace(this->end(), this->end(), beg, end);
1872        }
1873
1874
1875        /*!
1876        \brief
1877                Appends to the String the given c-string.
1878
1879        \param c_str
1880                c-string that is to be appended.
1881
1882        \return
1883                This String after the append operation
1884
1885        \exception std::length_error    Thrown if resulting String would be too large.
1886        */
1887        String& operator+=(const char* c_str)
1888        {
1889                return append(c_str, strlen(c_str));
1890        }
1891
1892
1893        /*!
1894        \brief
1895                Appends to the String the given c-string.
1896
1897        \param c_str
1898                c-string that is to be appended.
1899
1900        \return
1901                This String after the append operation
1902
1903        \exception std::length_error    Thrown if resulting String would be too large.
1904        */
1905        String& append(const char* c_str)
1906        {
1907                return append(c_str, strlen(c_str));
1908        }
1909
1910
1911        /*!
1912        \brief
1913                Appends to the String chars from the given char array.
1914
1915        \param chars
1916                char array holding the chars that are to be appended
1917
1918        \param chars_len
1919                Number of chars to be appended
1920
1921        \return
1922                This String after the append operation
1923
1924        \exception std::length_error    Thrown if resulting String would be too large, or if \a chars_len was 'npos'
1925        */
1926        String& append(const char* chars, size_type chars_len)
1927        {
1928                if (chars_len == npos)
1929                        throw std::length_error("Length for char array can not be 'npos'");
1930
1931                size_type newsz = d_cplength + chars_len;
1932
1933                grow(newsz);
1934
1935                utf32* pt = &ptr()[newsz-1];
1936
1937                while(chars_len--)
1938                        *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
1939
1940                setlen(newsz);
1941
1942                return *this;
1943        }
1944
1945
1946        //////////////////////////////////////////////////////////////////////////
1947        // Insertion Functions
1948        //////////////////////////////////////////////////////////////////////////
1949        /*!
1950        \brief
1951                Inserts the given String object at the specified position.
1952
1953        \param idx
1954                Index where the string is to be inserted.
1955
1956        \param str
1957                String object that is to be inserted.
1958
1959        \return
1960                This String after the insert.
1961
1962        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
1963        \exception std::length_error    Thrown if resulting String would be too large.
1964        */
1965        String& insert(size_type idx, const String& str)
1966        {
1967                return insert(idx, str, 0, npos);
1968        }
1969
1970        /*!
1971        \brief
1972                Inserts a sub-string of the given String object at the specified position.
1973
1974        \param idx
1975                Index where the string is to be inserted.
1976
1977        \param str
1978                String object containing data to be inserted.
1979
1980        \param str_idx
1981                Index of the first code point from \a str to be inserted.
1982
1983        \param str_num
1984                Maximum number of code points from \a str to be inserted.
1985
1986        \return
1987                This String after the insert.
1988
1989        \exception std::out_of_range    Thrown if \a idx or \a str_idx are out of range.
1990        \exception std::length_error    Thrown if resulting String would be too large.
1991        */
1992        String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
1993        {
1994                if ((d_cplength < idx) || (str.d_cplength < str_idx))
1995                        throw std::out_of_range("Index is out of range for CEGUI::String");
1996
1997                if (str_num == npos)
1998                        str_num = str.d_cplength - str_idx;
1999
2000                size_type newsz = d_cplength + str_num;
2001                grow(newsz);
2002                memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2003                memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2004                setlen(newsz);
2005
2006                return *this;
2007        }
2008
2009        /*!
2010        \brief
2011                Inserts the given std::string object at the specified position.
2012
2013        \param idx
2014                Index where the std::string is to be inserted.
2015
2016        \param std_str
2017                std::string object that is to be inserted.
2018
2019        \note
2020                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
2021                the provided data will occur.
2022
2023        \return
2024                This String after the insert.
2025
2026        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
2027        \exception std::length_error    Thrown if resulting String would be too large.
2028        */
2029        String& insert(size_type idx, const std::string& std_str)
2030        {
2031                return insert(idx, std_str, 0, npos);
2032        }
2033
2034        /*!
2035        \brief
2036                Inserts a sub-string of the given std::string object at the specified position.
2037
2038        \param idx
2039                Index where the string is to be inserted.
2040
2041        \param std_str
2042                std::string object containing data to be inserted.
2043
2044        \note
2045                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
2046                the provided data will occur.
2047
2048        \param str_idx
2049                Index of the first character from \a std_str to be inserted.
2050
2051        \param str_num
2052                Maximum number of characters from \a str to be inserted.
2053
2054        \return
2055                This String after the insert.
2056
2057        \exception std::out_of_range    Thrown if \a idx or \a str_idx are out of range.
2058        \exception std::length_error    Thrown if resulting String would be too large.
2059        */
2060        String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
2061        {
2062                if (d_cplength < idx)
2063                        throw std::out_of_range("Index is out of range for CEGUI::String");
2064
2065                if (std_str.size() < str_idx)
2066                        throw std::out_of_range("Index is out of range for std::string");
2067
2068                if (str_num == npos)
2069                        str_num = (size_type)std_str.size() - str_idx;
2070
2071                size_type newsz = d_cplength + str_num;
2072                grow(newsz);
2073
2074                memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2075
2076                utf32* pt = &ptr()[idx + str_num - 1];
2077               
2078                while(str_num--)
2079                        *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2080
2081                setlen(newsz);
2082
2083                return *this;
2084        }
2085
2086        /*!
2087        \brief
2088                Inserts the given null-terminated utf8 encoded data at the specified position.
2089
2090        \param idx
2091                Index where the data is to be inserted.
2092
2093        \param utf8_str
2094                Buffer containing the null-terminated utf8 encoded data that is to be inserted.
2095
2096        \note
2097                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
2098                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
2099                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
2100                results.
2101
2102        \return
2103                This String after the insert.
2104
2105        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
2106        \exception std::length_error    Thrown if resulting String would be too large.
2107        */
2108        String& insert(size_type idx, const utf8* utf8_str)
2109        {
2110                return insert(idx, utf8_str, utf_length(utf8_str));
2111        }
2112
2113        /*!
2114        \brief
2115                Inserts the given utf8 encoded data at the specified position.
2116
2117        \param idx
2118                Index where the data is to be inserted.
2119
2120        \param utf8_str
2121                Buffer containing the utf8 encoded data that is to be inserted.
2122
2123        \note
2124                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
2125                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
2126                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
2127                results.
2128
2129        \param len
2130                Length of the data to be inserted in uf8 code units (not code points)
2131
2132        \return
2133                This String after the insert.
2134
2135        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
2136        \exception std::length_error    Thrown if resulting String would be too large, or if \a len is 'npos'
2137        */
2138        String& insert(size_type idx, const utf8* utf8_str, size_type len)
2139        {
2140                if (d_cplength < idx)
2141                        throw std::out_of_range("Index is out of range for CEGUI::String");
2142
2143                if (len == npos)
2144                        throw std::length_error("Length of utf8 encoded string can not be 'npos'");
2145
2146                size_type encsz = encoded_size(utf8_str, len);
2147                size_type newsz = d_cplength + encsz;
2148
2149                grow(newsz);
2150                memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2151                encode(utf8_str, &ptr()[idx], encsz, len);
2152                setlen(newsz);
2153
2154                return *this;
2155        }
2156
2157        /*!
2158        \brief
2159                Inserts a code point multiple times into the String
2160
2161        \param idx
2162                Index where the code point(s) are to be inserted
2163
2164        \param num
2165                The number of times to insert the code point
2166
2167        \param code_point
2168                The utf32 code point that is to be inserted
2169
2170        \return
2171                This String after the insertion.
2172
2173        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
2174        \exception std::length_error    Thrown if resulting String would be too large, or if \a num is 'npos'
2175        */
2176        String& insert(size_type idx, size_type num, utf32 code_point)
2177        {
2178                if (d_cplength < idx)
2179                        throw std::out_of_range("Index is out of range for CEGUI::String");
2180
2181                if (num == npos)
2182                        throw std::length_error("Code point count can not be 'npos'");
2183
2184                size_type newsz = d_cplength + num;
2185                grow(newsz);
2186
2187                memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2188
2189                utf32* pt = &ptr()[idx + num - 1];
2190
2191                while(num--)
2192                        *pt-- = code_point;
2193
2194                setlen(newsz);
2195
2196                return *this;
2197        }
2198
2199        /*!
2200        \brief
2201                Inserts a code point multiple times into the String
2202
2203        \param pos
2204                Iterator describing the position where the code point(s) are to be inserted
2205
2206        \param num
2207                The number of times to insert the code point
2208
2209        \param code_point
2210                The utf32 code point that is to be inserted
2211
2212        \return
2213                This String after the insertion.
2214
2215        \exception std::length_error    Thrown if resulting String would be too large, or if \a num is 'npos'
2216        */
2217        void insert(iterator pos, size_type num, utf32 code_point)
2218        {
2219                insert(safe_iter_dif(pos, begin()), num, code_point);
2220        }
2221
2222        /*!
2223        \brief
2224                Inserts a single code point into the String
2225
2226        \param pos
2227                Iterator describing the position where the code point is to be inserted
2228
2229        \param code_point
2230                The utf32 code point that is to be inserted
2231
2232        \return
2233                This String after the insertion.
2234
2235        \exception std::length_error    Thrown if resulting String would be too large.
2236        */
2237        iterator insert(iterator pos, utf32 code_point)
2238        {
2239                insert(pos, 1, code_point);
2240                return pos;
2241        }
2242
2243        /*!
2244        \brief
2245                Inserts code points specified by the range [beg, end).
2246
2247        \param pos
2248                Iterator describing the position where the data is to be inserted
2249
2250        \param beg
2251                Iterator describing the begining of the range to be inserted
2252
2253        \param end
2254                Iterator describing the (exclusive) end of the range to be inserted.
2255
2256        \return
2257                Nothing.
2258
2259        \exception std::length_error    Thrown if resulting String would be too large.
2260        */
2261        void    insert(iterator pos, const_iterator beg, const_iterator end)
2262        {
2263                replace(pos, pos, beg, end);
2264        }
2265
2266
2267        /*!
2268        \brief
2269                Inserts the given c-string at the specified position.
2270
2271        \param idx
2272                Index where the c-string is to be inserted.
2273
2274        \param c_str
2275                c-string that is to be inserted.
2276
2277        \return
2278                This String after the insert.
2279
2280        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
2281        \exception std::length_error    Thrown if resulting String would be too large.
2282        */
2283        String& insert(size_type idx, const char* c_str)
2284        {
2285                return insert(idx, c_str, strlen(c_str));
2286        }
2287
2288
2289        /*!
2290        \brief
2291                Inserts chars from the given char array at the specified position.
2292
2293        \param idx
2294                Index where the data is to be inserted.
2295
2296        \param chars
2297                char array containing the chars that are to be inserted.
2298
2299        \param chars_len
2300                Length of the char array to be inserted.
2301
2302        \return
2303                This String after the insert.
2304
2305        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
2306        \exception std::length_error    Thrown if resulting String would be too large, or if \a chars_len is 'npos'
2307        */
2308        String& insert(size_type idx, const char* chars, size_type chars_len)
2309        {
2310                if (d_cplength < idx)
2311                        throw std::out_of_range("Index is out of range for CEGUI::String");
2312
2313                if (chars_len == npos)
2314                        throw std::length_error("Length of char array can not be 'npos'");
2315
2316                size_type newsz = d_cplength + chars_len;
2317
2318                grow(newsz);
2319                memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2320
2321                utf32* pt = &ptr()[idx + chars_len - 1];
2322
2323                while(chars_len--)
2324                        *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
2325
2326                setlen(newsz);
2327
2328                return *this;
2329        }
2330
2331
2332        //////////////////////////////////////////////////////////////////////////
2333        // Erasing characters
2334        //////////////////////////////////////////////////////////////////////////
2335        /*!
2336        \brief
2337                Removes all data from the String
2338
2339        \return
2340                Nothing
2341        */
2342        void    clear(void)
2343        {
2344                setlen(0);
2345                trim();
2346        }
2347
2348        /*!
2349        \brief
2350                Removes all data from the String
2351
2352        \return
2353                The empty String (*this)
2354        */
2355        String& erase(void)
2356        {
2357                clear();
2358                return *this;
2359        }
2360
2361        /*!
2362        \brief
2363                Erase a single code point from the string
2364
2365        \param idx
2366                The index of the code point to be removed.
2367
2368        \return
2369                This String after the erase operation
2370
2371        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
2372        */
2373        String& erase(size_type idx)
2374        {
2375                return erase(idx, 1);
2376        }
2377
2378        /*!
2379        \brief
2380                Erase a range of code points
2381
2382        \param idx
2383                Index of the first code point to be removed.
2384
2385        \param len
2386                Maximum number of code points to be removed.
2387
2388        \return
2389                This String after the erase operation.
2390
2391        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
2392        */
2393        String& erase(size_type idx, size_type len = npos)
2394        {
2395                if (d_cplength < idx)
2396                        throw std::out_of_range("Index is out of range foe CEGUI::String");
2397
2398                if (len == npos)
2399                        len = d_cplength - idx;
2400
2401                size_type newsz = d_cplength - len;
2402
2403                memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
2404                setlen(newsz);
2405                return  *this;
2406        }
2407
2408        /*!
2409        \brief
2410                Erase the code point described by the given iterator
2411
2412        \param pos
2413                Iterator describing the code point to be erased
2414
2415        \return
2416                This String after the erase operation.
2417        */
2418        String& erase(iterator pos)
2419        {
2420                return erase(safe_iter_dif(pos, begin()), 1);
2421        }
2422
2423        /*!
2424        \brief
2425                Erase a range of code points described by the iterators [beg, end).
2426
2427        \param beg
2428                Iterator describing the postion of the beginning of the range to erase
2429
2430        \param end
2431                Iterator describing the postion of the (exclusive) end of the range to erase
2432
2433        \return
2434                This String after the erase operation.
2435        */
2436        String& erase(iterator beg, iterator end)
2437        {
2438                return erase(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg));
2439        }
2440
2441        //////////////////////////////////////////////////////////////////////////
2442        // Resizing
2443        //////////////////////////////////////////////////////////////////////////
2444        /*!
2445        \brief
2446                Resizes the String either by inserting default utf32 code points to make it larger, or by truncating to make it smaller
2447
2448        \param num
2449                The length, in code points, that the String is to be made.
2450
2451        \return
2452                Nothing.
2453
2454        \exception std::length_error    Thrown if the String would be too large.
2455        */
2456        void    resize(size_type num)
2457        {
2458                resize(num, utf32());
2459        }
2460
2461        /*!
2462        \brief
2463                Resizes the String either by inserting the given utf32 code point to make it larger, or by truncating to make it smaller
2464
2465        \param num
2466                The length, in code points, that the String is to be made.
2467
2468        \param code_point
2469                The utf32 code point that should be used when majing the String larger
2470
2471        \return
2472                Nothing.
2473
2474        \exception std::length_error    Thrown if the String would be too large.
2475        */
2476        void    resize(size_type num, utf32 code_point)
2477        {
2478                if (num < d_cplength)
2479                {
2480                        setlen(num);
2481                }
2482                else
2483                {
2484                        append(num - d_cplength, code_point);
2485                }
2486
2487        }
2488
2489        //////////////////////////////////////////////////////////////////////////
2490        // Replacing Characters
2491        //////////////////////////////////////////////////////////////////////////
2492        /*!
2493        \brief
2494                Replace code points in the String with the specified String object
2495
2496        \param idx
2497                Index of the first code point to be replaced
2498
2499        \param len
2500                Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
2501
2502        \param str
2503                The String object that is to replace the specified code points
2504
2505        \return
2506                This String after the replace operation
2507
2508        \exception std::out_of_range    Thrown if \a idx is invalid for this String
2509        \exception std::length_error    Thrown if the resulting String would be too large.
2510        */
2511        String& replace(size_type idx, size_type len, const String& str)
2512        {
2513                return replace(idx, len, str, 0, npos);
2514        }
2515
2516        /*!
2517        \brief
2518                Replace the code points in the range [beg, end) with the specified String object
2519
2520        \note
2521                If \a beg == \a end, the operation is a insert at iterator position \a beg
2522
2523        \param beg
2524                Iterator describing the start of the range to be replaced
2525
2526        \param end
2527                Iterator describing the (exclusive) end of the range to be replaced.
2528
2529        \param str
2530                The String object that is to replace the specified range of code points
2531
2532        \return
2533                This String after the replace operation
2534
2535        \exception std::length_error    Thrown if the resulting String would be too large.
2536        */
2537        String& replace(iterator beg, iterator end, const String& str)
2538        {
2539                return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), str, 0, npos);
2540        }
2541
2542        /*!
2543        \brief
2544                Replace code points in the String with a specified sub-string of a given String object.
2545
2546        \param idx
2547                Index of the first code point to be replaced
2548
2549        \param len
2550                Maximum number of code points to be replaced.  If this is 0, the operation is an insert at position \a idx.
2551
2552        \param str
2553                String object containing the data that will replace the specified range of code points
2554
2555        \param str_idx
2556                Index of the first code point of \a str that is to replace the specified code point range
2557
2558        \param str_num
2559                Maximum number of code points of \a str that are to replace the specified code point range
2560
2561        \return
2562                This String after the replace operation
2563
2564        \exception std::out_of_range    Thrown if either \a idx, or \a str_idx are invalid
2565        \exception std::length_error    Thrown if the resulting String would have been too large.
2566        */
2567        String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
2568        {
2569                if ((d_cplength < idx) || (str.d_cplength < str_idx))
2570                        throw std::out_of_range("Index is out of range for CEGUI::String");
2571
2572                if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
2573                        str_num = str.d_cplength - str_idx;
2574
2575                if (((len + idx) > d_cplength) || (len == npos))
2576                        len = d_cplength - idx;
2577
2578                size_type newsz = d_cplength + str_num - len;
2579
2580                grow(newsz);
2581
2582                if ((idx + len) < d_cplength)
2583                        memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2584
2585                memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2586                setlen(newsz);
2587
2588                return *this;
2589        }
2590
2591
2592        /*!
2593        \brief
2594                Replace code points in the String with the specified std::string object
2595
2596        \param idx
2597                Index of the first code point to be replaced
2598
2599        \param len
2600                Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
2601
2602        \param std_str
2603                The std::string object that is to replace the specified code points
2604
2605        \note
2606                Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
2607                the encountered data is performed.
2608
2609        \return
2610                This String after the replace operation
2611
2612        \exception std::out_of_range    Thrown if \a idx is invalid for this String
2613        \exception std::length_error    Thrown if the resulting String would be too large.
2614        */
2615        String& replace(size_type idx, size_type len, const std::string& std_str)
2616        {
2617                return replace(idx, len, std_str, 0, npos);
2618        }
2619
2620        /*!
2621        \brief
2622                Replace the code points in the range [beg, end) with the specified std::string object
2623
2624        \note
2625                If \a beg == \a end, the operation is a insert at iterator position \a beg
2626
2627        \param beg
2628                Iterator describing the start of the range to be replaced
2629
2630        \param end
2631                Iterator describing the (exclusive) end of the range to be replaced.
2632
2633        \param std_str
2634                The std::string object that is to replace the specified range of code points
2635
2636        \note
2637                Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
2638                the encountered data is performed.
2639
2640        \return
2641                This String after the replace operation
2642
2643        \exception std::length_error    Thrown if the resulting String would be too large.
2644        */
2645        String& replace(iterator beg, iterator end, const std::string& std_str)
2646        {
2647                return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), std_str, 0, npos);
2648        }
2649
2650        /*!
2651        \brief
2652                Replace code points in the String with a specified sub-string of a given std::string object.
2653
2654        \param idx
2655                Index of the first code point to be replaced
2656
2657        \param len
2658                Maximum number of code points to be replaced.  If this is 0, the operation is an insert at position \a idx.
2659
2660        \param std_str
2661                std::string object containing the data that will replace the specified range of code points
2662
2663        \note
2664                Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
2665                the encountered data is performed.
2666
2667        \param str_idx
2668                Index of the first code point of \a std_str that is to replace the specified code point range
2669
2670        \param str_num
2671                Maximum number of code points of \a std_str that are to replace the specified code point range
2672
2673        \return
2674                This String after the replace operation
2675
2676        \exception std::out_of_range    Thrown if either \a idx, or \a str_idx are invalid
2677        \exception std::length_error    Thrown if the resulting String would have been too large.
2678        */
2679        String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
2680        {
2681                if (d_cplength < idx)
2682                        throw std::out_of_range("Index is out of range for CEGUI::String");
2683
2684                if (std_str.size() < str_idx)
2685                        throw std::out_of_range("Index is out of range for std::string");
2686
2687                if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
2688                        str_num = (size_type)std_str.size() - str_idx;
2689
2690                if (((len + idx) > d_cplength) || (len == npos))
2691                        len = d_cplength - idx;
2692
2693                size_type newsz = d_cplength + str_num - len;
2694
2695                grow(newsz);
2696
2697                if ((idx + len) < d_cplength)
2698                        memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2699
2700                utf32* pt = &ptr()[idx + str_num - 1];
2701
2702                while (str_num--)
2703                        *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2704
2705                setlen(newsz);
2706
2707                return *this;
2708        }
2709
2710
2711        /*!
2712        \brief
2713                Replace code points in the String with the specified null-terminated utf8 encoded data.
2714
2715        \param idx
2716                Index of the first code point to be replaced
2717
2718        \param len
2719                Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
2720
2721        \param utf8_str
2722                Buffer containing the null-terminated utf8 encoded data that is to replace the specified code points
2723
2724        \note
2725                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
2726                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
2727                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
2728                results.
2729
2730        \return
2731                This String after the replace operation
2732
2733        \exception std::out_of_range    Thrown if \a idx is invalid for this String
2734        \exception std::length_error    Thrown if the resulting String would be too large.
2735        */
2736        String& replace(size_type idx, size_type len, const utf8* utf8_str)
2737        {
2738                return replace(idx, len, utf8_str, utf_length(utf8_str));
2739        }
2740
2741        /*!
2742        \brief
2743                Replace the code points in the range [beg, end) with the specified null-terminated utf8 encoded data.
2744
2745        \note
2746                If \a beg == \a end, the operation is a insert at iterator position \a beg
2747
2748        \param beg
2749                Iterator describing the start of the range to be replaced
2750
2751        \param end
2752                Iterator describing the (exclusive) end of the range to be replaced.
2753
2754        \param utf8_str
2755                Buffer containing the null-terminated utf8 encoded data that is to replace the specified range of code points
2756
2757        \note
2758                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
2759                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
2760                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
2761                results.
2762
2763        \return
2764                This String after the replace operation
2765
2766        \exception std::length_error    Thrown if the resulting String would be too large.
2767        */
2768        String& replace(iterator beg, iterator end, const utf8* utf8_str)
2769        {
2770                return replace(beg, end, utf8_str, utf_length(utf8_str));
2771        }
2772
2773        /*!
2774        \brief
2775                Replace code points in the String with the specified utf8 encoded data.
2776
2777        \param idx
2778                Index of the first code point to be replaced
2779
2780        \param len
2781                Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
2782
2783        \param utf8_str
2784                Buffer containing the null-terminated utf8 encoded data that is to replace the specified code points
2785
2786        \note
2787                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
2788                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
2789                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
2790                results.
2791
2792        \param str_len
2793                Length of the utf8 encoded data in utf8 code units (not code points).
2794
2795        \return
2796                This String after the replace operation
2797
2798        \exception std::out_of_range    Thrown if \a idx is invalid for this String
2799        \exception std::length_error    Thrown if the resulting String would be too large, or if \a str_len was 'npos'.
2800        */
2801        String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
2802        {
2803                if (d_cplength < idx)
2804                        throw std::out_of_range("Index is out of range for CEGUI::String");
2805
2806                if (str_len == npos)
2807                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
2808
2809                if (((len + idx) > d_cplength) || (len == npos))
2810                        len = d_cplength - idx;
2811
2812                size_type encsz = encoded_size(utf8_str, str_len);
2813                size_type newsz = d_cplength + encsz - len;
2814
2815                grow(newsz);
2816
2817                if ((idx + len) < d_cplength)
2818                        memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2819
2820                encode(utf8_str, &ptr()[idx], encsz, str_len);
2821
2822                setlen(newsz);
2823                return *this;
2824        }
2825
2826        /*!
2827        \brief
2828                Replace the code points in the range [beg, end) with the specified null-terminated utf8 encoded data.
2829
2830        \note
2831                If \a beg == \a end, the operation is a insert at iterator position \a beg
2832
2833        \param beg
2834                Iterator describing the start of the range to be replaced
2835
2836        \param end
2837                Iterator describing the (exclusive) end of the range to be replaced.
2838
2839        \param utf8_str
2840                Buffer containing the null-terminated utf8 encoded data that is to replace the specified range of code points
2841
2842        \note
2843                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
2844                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
2845                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
2846                results.
2847
2848        \param str_len
2849                Length of the utf8 encoded data in utf8 code units (not code points).
2850
2851        \return
2852                This String after the replace operation
2853
2854                \exception std::length_error    Thrown if the resulting String would be too large, or if \a str_len was 'npos'.
2855        */
2856        String& replace(iterator beg, iterator end, const utf8* utf8_str, size_type str_len)
2857        {
2858                return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), utf8_str, str_len);
2859        }
2860
2861        /*!
2862        \brief
2863                Replaces a specified range of code points with occurrences of a given code point
2864
2865        \param idx
2866                Index of the first code point to be replaced
2867
2868        \param len
2869                Maximum number of code points to replace.  If this is 0 the operation is an insert
2870
2871        \param num
2872                Number of occurrences of \a code_point that are to replace the specified range of code points
2873
2874        \param code_point
2875                Code point that is to be used when replacing the specified range of code points
2876
2877        \return
2878                This String after the replace operation.
2879
2880        \exception std::out_of_range    Thrown if \a idx is invalid for this String
2881        \exception std::length_error    Thrown if resulting String would have been too long, or if \a num was 'npos'.
2882        */
2883        String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
2884        {
2885                if (d_cplength < idx)
2886                        throw std::out_of_range("Index is out of range for CEGUI::String");
2887
2888                if (num == npos)
2889                        throw std::length_error("Code point count can not be 'npos'");
2890
2891                if (((len + idx) > d_cplength) || (len == npos))
2892                        len = d_cplength - idx;
2893
2894                size_type newsz = d_cplength + num - len;
2895
2896                grow(newsz);
2897
2898                if ((idx + len) < d_cplength)
2899                        memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2900
2901                utf32* pt = &ptr()[idx + num - 1];
2902
2903                while (num--)
2904                        *pt-- = code_point;
2905
2906                setlen(newsz);
2907
2908                return *this;
2909        }
2910
2911        /*!
2912        \brief
2913                Replace the code points in the range [beg, end) with occurrences of a given code point
2914
2915        \note
2916                If \a beg == \a end, the operation is an insert at iterator position \a beg
2917
2918        \param beg
2919                Iterator describing the start of the range to be replaced
2920
2921        \param end
2922                Iterator describing the (exclusive) end of the range to be replaced.
2923
2924        \param num
2925                Number of occurrences of \a code_point that are to replace the specified range of code points
2926
2927        \param code_point
2928                Code point that is to be used when replacing the specified range of code points
2929
2930        \return
2931                This String after the replace operation
2932
2933        \exception std::length_error    Thrown if resulting String would have been too long, or if \a num was 'npos'.
2934        */
2935        String& replace(iterator beg, iterator end, size_type num, utf32 code_point)
2936        {
2937                return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), num, code_point);
2938        }
2939
2940
2941        /*!
2942        \brief
2943                Replace the code points in the range [beg, end) with code points from the range [newBeg, newEnd).
2944
2945        \note
2946                If \a beg == \a end, the operation is an insert at iterator position \a beg
2947
2948        \param beg
2949                Iterator describing the start of the range to be replaced
2950
2951        \param end
2952                Iterator describing the (exclusive) end of the range to be replaced.
2953
2954        \param newBeg
2955                Iterator describing the beginning of the range to insert.
2956
2957        \param newEnd   
2958                Iterator describing the (exclusive) end of the range to insert.
2959
2960        \return
2961                This String after the insert operation.
2962
2963        \exception std::length_error    Thrown if the resulting string would be too long.
2964        */
2965        String& replace(iterator beg, iterator end, const_iterator newBeg, const_iterator newEnd)
2966        {
2967                if (beg == end)
2968                {
2969                        erase(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg));
2970                }
2971                else
2972                {
2973                        size_type str_len = safe_iter_dif(newEnd, newBeg);
2974                        size_type idx = safe_iter_dif(beg, begin());
2975                        size_type len = safe_iter_dif(end, beg);
2976
2977                        if ((len + idx) > d_cplength)
2978                                len = d_cplength - idx;
2979
2980                        size_type newsz = d_cplength + str_len - len;
2981
2982                        grow(newsz);
2983
2984                        if ((idx + len) < d_cplength)
2985                                memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2986
2987                        memcpy(&ptr()[idx], newBeg.d_ptr, str_len * sizeof(utf32));
2988                        setlen(newsz);
2989                }
2990
2991                return *this;
2992        }
2993
2994
2995        /*!
2996        \brief
2997                Replace code points in the String with the specified c-string.
2998
2999        \param idx
3000                Index of the first code point to be replaced
3001
3002        \param len
3003                Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
3004
3005        \param c_str
3006                c-string that is to replace the specified code points
3007
3008        \return
3009                This String after the replace operation
3010
3011        \exception std::out_of_range    Thrown if \a idx is invalid for this String
3012        \exception std::length_error    Thrown if the resulting String would be too large.
3013        */
3014        String& replace(size_type idx, size_type len, const char* c_str)
3015        {
3016                return replace(idx, len, c_str, strlen(c_str));
3017        }
3018
3019
3020        /*!
3021        \brief
3022                Replace the code points in the range [beg, end) with the specified c-string.
3023
3024        \note
3025                If \a beg == \a end, the operation is a insert at iterator position \a beg
3026
3027        \param beg
3028                Iterator describing the start of the range to be replaced
3029
3030        \param end
3031                Iterator describing the (exclusive) end of the range to be replaced.
3032
3033        \param c_str
3034                c-string that is to replace the specified range of code points
3035
3036        \return
3037                This String after the replace operation
3038
3039        \exception std::length_error    Thrown if the resulting String would be too large.
3040        */
3041        String& replace(iterator beg, iterator end, const char* c_str)
3042        {
3043                return replace(beg, end, c_str, strlen(c_str));
3044        }
3045
3046
3047        /*!
3048        \brief
3049                Replace code points in the String with chars from the given char array.
3050
3051        \param idx
3052                Index of the first code point to be replaced
3053
3054        \param len
3055                Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
3056
3057        \param chars
3058                char array containing the cars that are to replace the specified code points
3059
3060        \param chars_len
3061                Number of chars in the char array.
3062
3063        \return
3064                This String after the replace operation
3065
3066        \exception std::out_of_range    Thrown if \a idx is invalid for this String
3067        \exception std::length_error    Thrown if the resulting String would be too large, or if \a chars_len was 'npos'.
3068        */
3069        String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
3070        {
3071                if (d_cplength < idx)
3072                        throw std::out_of_range("Index is out of range for CEGUI::String");
3073
3074                if (chars_len == npos)
3075                        throw std::length_error("Length for the char array can not be 'npos'");
3076
3077                if (((len + idx) > d_cplength) || (len == npos))
3078                        len = d_cplength - idx;
3079
3080                size_type newsz = d_cplength + chars_len - len;
3081
3082                grow(newsz);
3083
3084                if ((idx + len) < d_cplength)
3085                        memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
3086
3087                utf32* pt = &ptr()[idx + chars_len - 1];
3088
3089                while (chars_len--)
3090                        *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
3091
3092                setlen(newsz);
3093                return *this;
3094        }
3095
3096
3097        /*!
3098        \brief
3099                Replace the code points in the range [beg, end) with chars from the given char array.
3100
3101        \note
3102                If \a beg == \a end, the operation is a insert at iterator position \a beg
3103
3104        \param beg
3105                Iterator describing the start of the range to be replaced
3106
3107        \param end
3108                Iterator describing the (exclusive) end of the range to be replaced.
3109
3110        \param chars
3111                char array containing the chars that are to replace the specified range of code points
3112
3113        \param chars_len
3114                Number of chars in the char array.
3115
3116        \return
3117                This String after the replace operation
3118
3119        \exception std::length_error    Thrown if the resulting String would be too large, or if \a chars_len was 'npos'.
3120        */
3121        String& replace(iterator beg, iterator end, const char* chars, size_type chars_len)
3122        {
3123                return replace(safe_iter_dif(beg, begin()), safe_iter_dif(end, beg), chars, chars_len);
3124        }
3125
3126
3127        //////////////////////////////////////////////////////////////////////////
3128        // Find a code point
3129        //////////////////////////////////////////////////////////////////////////
3130        /*!
3131        \brief
3132                Search forwards for a given code point
3133
3134        \param code_point
3135                The utf32 code point to search for
3136
3137        \param idx
3138                Index of the code point where the search is to start.
3139
3140        \return
3141                - Index of the first occurrence of \a code_point travelling forwards from \a idx.
3142                - npos if the code point could not be found
3143        */
3144        size_type       find(utf32 code_point, size_type idx = 0) const
3145        {
3146                if (idx < d_cplength)
3147                {
3148                        const utf32* pt = &ptr()[idx];
3149
3150                        while (idx < d_cplength)
3151                        {
3152                                if (*pt++ == code_point)
3153                                        return idx;
3154
3155                                ++idx;
3156                        }
3157
3158                }
3159
3160                return npos;
3161        }
3162
3163        /*!
3164        \brief
3165                Search backwards for a given code point
3166
3167        \param code_point
3168                The utf32 code point to search for
3169
3170        \param idx
3171                Index of the code point where the search is to start.
3172
3173        \return
3174                - Index of the first occurrence of \a code_point travelling backwards from \a idx.
3175                - npos if the code point could not be found
3176        */
3177        size_type       rfind(utf32 code_point, size_type idx = npos) const
3178        {
3179                if (idx >= d_cplength)
3180                        idx = d_cplength - 1;
3181
3182                if (d_cplength > 0)
3183                {
3184                        const utf32* pt = &ptr()[idx];
3185
3186                        do
3187                        {
3188                                if (*pt-- == code_point)
3189                                        return idx;
3190
3191                        } while (idx-- != 0);
3192
3193                }
3194
3195                return npos;
3196        }
3197
3198        //////////////////////////////////////////////////////////////////////////
3199        // Find a substring
3200        //////////////////////////////////////////////////////////////////////////
3201        /*!
3202        \brief
3203                Search forwards for a sub-string
3204
3205        \param str
3206                String object describing the sub-string to search for
3207
3208        \param idx
3209                Index of the code point where the search is to start
3210
3211        \return
3212                - Index of the first occurrence of sub-string \a str travelling forwards from \a idx.
3213                - npos if the sub-string could not be found
3214        */
3215        size_type       find(const String& str, size_type idx = 0) const
3216        {
3217                if ((str.d_cplength == 0) && (idx < d_cplength))
3218                        return idx;
3219
3220                if (idx < d_cplength)
3221                {
3222                        // loop while search string could fit in to search area
3223                        while (d_cplength - idx >= str.d_cplength)
3224                        {
3225                                if (0 == compare(idx, str.d_cplength, str))
3226                                        return idx;
3227
3228                                ++idx;
3229                        }
3230
3231                }
3232
3233                return npos;
3234        }
3235
3236        /*!
3237        \brief
3238                Search backwards for a sub-string
3239
3240        \param str
3241                String object describing the sub-string to search for
3242
3243        \param idx
3244                Index of the code point where the search is to start
3245
3246        \return
3247                - Index of the first occurrence of sub-string \a str travelling backwards from \a idx.
3248                - npos if the sub-string could not be found
3249        */
3250        size_type       rfind(const String& str, size_type idx = npos) const
3251        {
3252                if (str.d_cplength == 0)
3253                        return (idx < d_cplength) ? idx : d_cplength;
3254
3255                if (str.d_cplength <= d_cplength)
3256                {
3257                        if (idx > (d_cplength - str.d_cplength))
3258                                idx = d_cplength - str.d_cplength;
3259
3260                        do
3261                        {
3262                                if (0 == compare(idx, str.d_cplength, str))
3263                                        return idx;
3264
3265                        } while (idx-- != 0);
3266
3267                }
3268
3269                return npos;
3270        }
3271
3272        /*!
3273        \brief
3274                Search forwards for a sub-string
3275
3276        \param std_str
3277                std::string object describing the sub-string to search for
3278
3279        \note
3280                Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
3281                the encountered data is performed.
3282
3283        \param idx
3284                Index of the code point where the search is to start
3285
3286        \return
3287                - Index of the first occurrence of sub-string \a std_str travelling forwards from \a idx.
3288                - npos if the sub-string could not be found
3289        */
3290        size_type       find(const std::string& std_str, size_type idx = 0) const
3291        {
3292                std::string::size_type sze = std_str.size();
3293
3294                if ((sze == 0) && (idx < d_cplength))
3295                        return idx;
3296
3297                if (idx < d_cplength)
3298                {
3299                        // loop while search string could fit in to search area
3300                        while (d_cplength - idx >= sze)
3301                        {
3302                                if (0 == compare(idx, (size_type)sze, std_str))
3303                                        return idx;
3304
3305                                ++idx;
3306                        }
3307
3308                }
3309
3310                return npos;
3311        }
3312
3313        /*!
3314        \brief
3315                Search backwards for a sub-string
3316
3317        \param std_str
3318                std::string object describing the sub-string to search for
3319
3320        \note
3321                Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
3322                the encountered data is performed.
3323
3324        \param idx
3325                Index of the code point where the search is to start
3326
3327        \return
3328                - Index of the first occurrence of sub-string \a std_str travelling backwards from \a idx.
3329                - npos if the sub-string could not be found
3330        */
3331        size_type       rfind(const std::string& std_str, size_type idx = npos) const
3332        {
3333                std::string::size_type sze = std_str.size();
3334
3335                if (sze == 0)
3336                        return (idx < d_cplength) ? idx : d_cplength;
3337
3338                if (sze <= d_cplength)
3339                {
3340                        if (idx > (d_cplength - sze))
3341                                idx = d_cplength - sze;
3342
3343                        do
3344                        {
3345                                if (0 == compare(idx, (size_type)sze, std_str))
3346                                        return idx;
3347
3348                        } while (idx-- != 0);
3349
3350                }
3351
3352                return npos;
3353        }
3354
3355        /*!
3356        \brief
3357                Search forwards for a sub-string
3358
3359        \param utf8_str
3360                Buffer containing null-terminated utf8 encoded data describing the sub-string to search for
3361
3362        \note
3363                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
3364                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
3365                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
3366                results.
3367
3368        \param idx
3369                Index of the code point where the search is to start
3370
3371        \return
3372                - Index of the first occurrence of sub-string \a utf8_str travelling forwards from \a idx.
3373                - npos if the sub-string could not be found
3374
3375        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
3376        */
3377        size_type       find(const utf8* utf8_str, size_type idx = 0) const
3378        {
3379                return find(utf8_str, idx, utf_length(utf8_str));
3380        }
3381
3382        /*!
3383        \brief
3384                Search backwards for a sub-string
3385
3386        \param utf8_str
3387                Buffer containing null-terminated utf8 encoded data describing the sub-string to search for
3388
3389        \note
3390                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
3391                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
3392                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
3393                results.
3394
3395        \param idx
3396                Index of the code point where the search is to start
3397
3398        \return
3399                - Index of the first occurrence of sub-string \a utf8_str travelling backwards from \a idx.
3400                - npos if the sub-string could not be found
3401
3402        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
3403        */
3404        size_type       rfind(const utf8* utf8_str, size_type idx = npos) const
3405        {
3406                return rfind(utf8_str, idx, utf_length(utf8_str));
3407        }
3408
3409        /*!
3410        \brief
3411                Search forwards for a sub-string
3412
3413        \param utf8_str
3414                Buffer containing utf8 encoded data describing the sub-string to search for
3415
3416        \note
3417                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
3418                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
3419                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
3420                results.
3421
3422        \param idx
3423                Index of the code point where the search is to start
3424
3425        \param str_len
3426                Length of the utf8 encoded sub-string in utf8 code units (not code points)
3427
3428        \return
3429                - Index of the first occurrence of sub-string \a utf8_str travelling forwards from \a idx.
3430                - npos if the sub-string could not be found
3431
3432        \exception std::length_error    Thrown if \a str_len is 'npos'
3433        */
3434        size_type       find(const utf8* utf8_str, size_type idx, size_type str_len) const
3435        {
3436                if (str_len == npos)
3437                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
3438
3439                size_type sze = encoded_size(utf8_str, str_len);
3440
3441                if ((sze == 0) && (idx < d_cplength))
3442                        return idx;
3443
3444                if (idx < d_cplength)
3445                {
3446                        // loop while search string could fit in to search area
3447                        while (d_cplength - idx >= sze)
3448                        {
3449                                if (0 == compare(idx, sze, utf8_str, sze))
3450                                        return idx;
3451
3452                                ++idx;
3453                        }
3454
3455                }
3456
3457                return npos;
3458        }
3459
3460        /*!
3461        \brief
3462                Search backwards for a sub-string
3463
3464        \param utf8_str
3465                Buffer containing utf8 encoded data describing the sub-string to search for
3466
3467        \note
3468                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
3469                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
3470                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
3471                results.
3472
3473        \param idx
3474                Index of the code point where the search is to start
3475
3476        \param str_len
3477                Length of the utf8 encoded sub-string in utf8 code units (not code points)
3478
3479        \return
3480                - Index of the first occurrence of sub-string \a utf8_str travelling backwards from \a idx.
3481                - npos if the sub-string could not be found
3482
3483        \exception std::length_error    Thrown if \a str_len is 'npos'
3484        */
3485        size_type       rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
3486        {
3487                if (str_len == npos)
3488                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
3489
3490                size_type sze = encoded_size(utf8_str, str_len);
3491
3492                if (sze == 0)
3493                        return (idx < d_cplength) ? idx : d_cplength;
3494
3495                if (sze <= d_cplength)
3496                {
3497                        if (idx > (d_cplength - sze))
3498                                idx = d_cplength - sze;
3499
3500                        do
3501                        {
3502                                if (0 == compare(idx, sze, utf8_str, sze))
3503                                        return idx;
3504
3505                        } while (idx-- != 0);
3506
3507                }
3508
3509                return npos;
3510        }
3511
3512
3513        /*!
3514        \brief
3515                Search forwards for a sub-string
3516
3517        \param c_str
3518                c-string describing the sub-string to search for
3519
3520        \param idx
3521                Index of the code point where the search is to start
3522
3523        \return
3524                - Index of the first occurrence of sub-string \a c_str travelling forwards from \a idx.
3525                - npos if the sub-string could not be found
3526
3527        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
3528        */
3529        size_type       find(const char* c_str, size_type idx = 0) const
3530        {
3531                return find(c_str, idx, strlen(c_str));
3532        }
3533
3534
3535        /*!
3536        \brief
3537                Search backwards for a sub-string
3538
3539        \param c_str
3540                c-string describing the sub-string to search for
3541
3542        \param idx
3543                Index of the code point where the search is to start
3544
3545        \return
3546                - Index of the first occurrence of sub-string \a c_str travelling backwards from \a idx.
3547                - npos if the sub-string could not be found
3548
3549        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
3550        */
3551        size_type       rfind(const char* c_str, size_type idx = npos) const
3552        {
3553                return rfind(c_str, idx, strlen(c_str));
3554        }
3555
3556
3557        /*!
3558        \brief
3559                Search forwards for a sub-string
3560
3561        \param chars
3562                char array describing the sub-string to search for
3563
3564        \param idx
3565                Index of the code point where the search is to start
3566
3567        \param chars_len
3568                Number of chars in the char array.
3569
3570        \return
3571                - Index of the first occurrence of sub-string \a chars travelling forwards from \a idx.
3572                - npos if the sub-string could not be found
3573
3574        \exception std::length_error    Thrown if \a chars_len is 'npos'
3575        */
3576        size_type       find(const char* chars, size_type idx, size_type chars_len) const
3577        {
3578                if (chars_len == npos)
3579                        throw std::length_error("Length for char array can not be 'npos'");
3580
3581                if ((chars_len == 0) && (idx < d_cplength))
3582                        return idx;
3583
3584                if (idx < d_cplength)
3585                {
3586                        // loop while search string could fit in to search area
3587                        while (d_cplength - idx >= chars_len)
3588                        {
3589                                if (0 == compare(idx, chars_len, chars, chars_len))
3590                                        return idx;
3591
3592                                ++idx;
3593                        }
3594
3595                }
3596
3597                return npos;
3598        }
3599
3600
3601        /*!
3602        \brief
3603                Search backwards for a sub-string
3604
3605        \param chars
3606                char array describing the sub-string to search for
3607
3608        \param idx
3609                Index of the code point where the search is to start
3610
3611        \param chars_len
3612                Number of chars in the char array.
3613
3614        \return
3615                - Index of the first occurrence of sub-string \a chars travelling backwards from \a idx.
3616                - npos if the sub-string could not be found
3617
3618        \exception std::length_error    Thrown if \a chars_len is 'npos'
3619        */
3620        size_type       rfind(const char* chars, size_type idx, size_type chars_len) const
3621        {
3622                if (chars_len == npos)
3623                        throw std::length_error("Length for char array can not be 'npos'");
3624
3625                if (chars_len == 0)
3626                        return (idx < d_cplength) ? idx : d_cplength;
3627
3628                if (chars_len <= d_cplength)
3629                {
3630                        if (idx > (d_cplength - chars_len))
3631                                idx = d_cplength - chars_len;
3632
3633                        do
3634                        {
3635                                if (0 == compare(idx, chars_len, chars, chars_len))
3636                                        return idx;
3637
3638                        } while (idx-- != 0);
3639
3640                }
3641
3642                return npos;
3643        }
3644
3645
3646        //////////////////////////////////////////////////////////////////////////
3647        // Find first of different code-points
3648        //////////////////////////////////////////////////////////////////////////
3649        /*!
3650        \brief
3651                Find the first occurrence of one of a set of code points.
3652
3653        \param str
3654                String object describing the set of code points.
3655
3656        \param idx
3657                Index of the start point for the search
3658
3659        \return
3660                - Index of the first occurrence of any one of the code points in \a str starting from from \a idx.
3661                - npos if none of the code points in \a str were found.
3662        */
3663        size_type       find_first_of(const String& str, size_type idx = 0) const
3664        {
3665                if (idx < d_cplength)
3666                {
3667                        const utf32* pt = &ptr()[idx];
3668
3669                        do
3670                        {
3671                                if (npos != str.find(*pt++))
3672                                        return idx;
3673
3674                        } while (++idx != d_cplength);
3675
3676                }
3677
3678                return npos;
3679        }
3680
3681        /*!
3682        \brief
3683                Find the first code point that is not one of a set of code points.
3684
3685        \param str
3686                String object describing the set of code points.
3687
3688        \param idx
3689                Index of the start point for the search
3690
3691        \return
3692                - Index of the first code point that does not match any one of the code points in \a str starting from from \a idx.
3693                - npos if all code points matched one of the code points in \a str.
3694        */
3695        size_type       find_first_not_of(const String& str, size_type idx = 0) const
3696        {
3697                if (idx < d_cplength)
3698                {
3699                        const utf32* pt = &ptr()[idx];
3700
3701                        do
3702                        {
3703                                if (npos == str.find(*pt++))
3704                                        return idx;
3705
3706                        } while (++idx != d_cplength);
3707
3708                }
3709
3710                return npos;
3711        }
3712
3713
3714        /*!
3715        \brief
3716                Find the first occurrence of one of a set of code points.
3717
3718        \param std_str
3719                std::string object describing the set of code points.
3720
3721        \note
3722                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
3723                the provided data will occur.
3724
3725        \param idx
3726                Index of the start point for the search
3727
3728        \return
3729                - Index of the first occurrence of any one of the code points in \a std_str starting from from \a idx.
3730                - npos if none of the code points in \a std_str were found.
3731        */
3732        size_type       find_first_of(const std::string& std_str, size_type idx = 0) const
3733        {
3734                if (idx < d_cplength)
3735                {
3736                        const utf32* pt = &ptr()[idx];
3737
3738                        do
3739                        {
3740                                if (npos != find_codepoint(std_str, *pt++))
3741                                        return idx;
3742
3743                        } while (++idx != d_cplength);
3744
3745                }
3746
3747                return npos;
3748        }
3749
3750        /*!
3751        \brief
3752                Find the first code point that is not one of a set of code points.
3753
3754        \param std_str
3755                std::string object describing the set of code points.
3756
3757        \note
3758                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
3759                the provided data will occur.
3760
3761        \param idx
3762                Index of the start point for the search
3763
3764        \return
3765                - Index of the first code point that does not match any one of the code points in \a std_str starting from from \a idx.
3766                - npos if all code points matched one of the code points in \a std_str.
3767        */
3768        size_type       find_first_not_of(const std::string& std_str, size_type idx = 0) const
3769        {
3770                if (idx < d_cplength)
3771                {
3772                        const utf32* pt = &ptr()[idx];
3773
3774                        do
3775                        {
3776                                if (npos == find_codepoint(std_str, *pt++))
3777                                        return idx;
3778
3779                        } while (++idx != d_cplength);
3780
3781                }
3782
3783                return npos;
3784        }
3785
3786
3787        /*!
3788        \brief
3789                Find the first occurrence of one of a set of code points.
3790
3791        \param utf8_str
3792                Buffer containing null-terminated utf8 encoded data describing the set of code points.
3793
3794        \note
3795                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
3796                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
3797                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
3798                results.
3799
3800        \param idx
3801                Index of the start point for the search
3802
3803        \return
3804                - Index of the first occurrence of any one of the code points in \a utf8_str starting from from \a idx.
3805                - npos if none of the code points in \a utf8_str were found.
3806
3807        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
3808        */
3809        size_type       find_first_of(const utf8* utf8_str, size_type idx = 0) const
3810        {
3811                return find_first_of(utf8_str, idx, utf_length(utf8_str));
3812        }
3813
3814        /*!
3815        \brief
3816                Find the first code point that is not one of a set of code points.
3817
3818        \param utf8_str
3819                Buffer containing null-terminated utf8 encoded data describing the set of code points.
3820
3821        \note
3822                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
3823                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
3824                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
3825                results.
3826
3827        \param idx
3828                Index of the start point for the search
3829
3830        \return
3831                - Index of the first code point that does not match any one of the code points in \a utf8_str starting from from \a idx.
3832                - npos if all code points matched one of the code points in \a utf8_str.
3833
3834        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
3835        */
3836        size_type       find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
3837        {
3838                return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
3839        }
3840
3841        /*!
3842        \brief
3843                Find the first occurrence of one of a set of code points.
3844
3845        \param utf8_str
3846                Buffer containing utf8 encoded data describing the set of code points.
3847
3848        \note
3849                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
3850                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
3851                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
3852                results.
3853
3854        \param idx
3855                Index of the start point for the search
3856
3857        \param str_len
3858                Length of the utf8 encoded data in utf8 code units (not code points).
3859
3860        \return
3861                - Index of the first occurrence of any one of the code points in \a utf8_str starting from from \a idx.
3862                - npos if none of the code points in \a utf8_str were found.
3863
3864        \exception std::length_error    Thrown if \a str_len was 'npos'.
3865        */
3866        size_type       find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3867        {
3868                if (str_len == npos)
3869                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
3870
3871                if (idx < d_cplength)
3872                {
3873                        size_type encsze = encoded_size(utf8_str, str_len);
3874
3875                        const utf32* pt = &ptr()[idx];
3876
3877                        do
3878                        {
3879                                if (npos != find_codepoint(utf8_str, encsze, *pt++))
3880                                        return idx;
3881
3882                        } while (++idx != d_cplength);
3883
3884                }
3885
3886                return npos;
3887        }
3888
3889        /*!
3890        \brief
3891                Find the first code point that is not one of a set of code points.
3892
3893        \param utf8_str
3894                Buffer containing utf8 encoded data describing the set of code points.
3895
3896        \note
3897                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
3898                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
3899                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
3900                results.
3901
3902        \param idx
3903                Index of the start point for the search
3904
3905        \param str_len
3906                Length of the utf8 encoded data in utf8 code units (not code points).
3907
3908        \return
3909                - Index of the first code point that does not match any one of the code points in \a utf8_str starting from from \a idx.
3910                - npos if all code points matched one of the code points in \a utf8_str.
3911
3912        \exception std::length_error    Thrown if \a str_len was 'npos'.
3913        */
3914        size_type       find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3915        {
3916                if (str_len == npos)
3917                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
3918
3919                if (idx < d_cplength)
3920                {
3921                        size_type encsze = encoded_size(utf8_str, str_len);
3922
3923                        const utf32* pt = &ptr()[idx];
3924
3925                        do
3926                        {
3927                                if (npos == find_codepoint(utf8_str, encsze, *pt++))
3928                                        return idx;
3929
3930                        } while (++idx != d_cplength);
3931
3932                }
3933
3934                return npos;
3935        }
3936
3937
3938        /*!
3939        \brief
3940                Search forwards for a given code point
3941
3942        \param code_point
3943                The utf32 code point to search for
3944
3945        \param idx
3946                Index of the code point where the search is to start.
3947
3948        \return
3949                - Index of the first occurrence of \a code_point starting from from \a idx.
3950                - npos if the code point could not be found
3951        */
3952        size_type       find_first_of(utf32 code_point, size_type idx = 0) const
3953        {
3954                return find(code_point, idx);
3955        }
3956
3957        /*!
3958        \brief
3959                Search forwards for the first code point that does not match a given code point
3960
3961        \param code_point
3962                The utf32 code point to search for
3963
3964        \param idx
3965                Index of the code point where the search is to start.
3966
3967        \return
3968                - Index of the first code point that does not match \a code_point starting from from \a idx.
3969                - npos if all code points matched \a code_point
3970
3971        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
3972        */
3973        size_type       find_first_not_of(utf32 code_point, size_type idx = 0) const
3974        {
3975                if (idx < d_cplength)
3976                {
3977                        do
3978                        {
3979                                if ((*this)[idx] != code_point)
3980                                        return idx;
3981
3982                        } while(idx++ < d_cplength);
3983
3984                }
3985
3986                return npos;
3987        }
3988
3989
3990        /*!
3991        \brief
3992                Find the first occurrence of one of a set of chars.
3993
3994        \param c_str
3995                c-string describing the set of chars.
3996
3997        \param idx
3998                Index of the start point for the search
3999
4000        \return
4001                - Index of the first occurrence of any one of the chars in \a c_str starting from from \a idx.
4002                - npos if none of the chars in \a c_str were found.
4003
4004        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
4005        */
4006        size_type       find_first_of(const char* c_str, size_type idx = 0) const
4007        {
4008                return find_first_of(c_str, idx, strlen(c_str));
4009        }
4010
4011
4012        /*!
4013        \brief
4014                Find the first code point that is not one of a set of chars.
4015
4016        \param c_str
4017                c-string describing the set of chars.
4018
4019        \param idx
4020                Index of the start point for the search
4021
4022        \return
4023                - Index of the first code point that does not match any one of the chars in \a c_str starting from from \a idx.
4024                - npos if all code points matched any of the chars in \a c_str.
4025
4026        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
4027        */
4028        size_type       find_first_not_of(const char* c_str, size_type idx = 0) const
4029        {
4030                return find_first_not_of(c_str, idx, strlen(c_str));
4031        }
4032
4033
4034        /*!
4035        \brief
4036                Find the first occurrence of one of a set of chars.
4037
4038        \param chars
4039                char array containing the set of chars.
4040
4041        \param idx
4042                Index of the start point for the search
4043
4044        \param chars_len
4045                Number of chars in the char array.
4046
4047        \return
4048                - Index of the first occurrence of any one of the chars in \a chars starting from from \a idx.
4049                - npos if none of the chars in \a chars were found.
4050
4051        \exception std::length_error    Thrown if \a chars_len was 'npos'.
4052        */
4053        size_type       find_first_of(const char* chars, size_type idx, size_type chars_len) const
4054        {
4055                if (chars_len == npos)
4056                        throw std::length_error("Length for char array can not be 'npos'");
4057
4058                if (idx < d_cplength)
4059                {
4060                        const utf32* pt = &ptr()[idx];
4061
4062                        do
4063                        {
4064                                if (npos != find_codepoint(chars, chars_len, *pt++))
4065                                        return idx;
4066
4067                        } while (++idx != d_cplength);
4068
4069                }
4070
4071                return npos;
4072        }
4073
4074
4075        /*!
4076        \brief
4077                Find the first code point that is not one of a set of chars.
4078
4079        \param chars
4080                char array containing the set of chars.
4081
4082        \param idx
4083                Index of the start point for the search
4084
4085        \param chars_len
4086                Number of chars in the car array.
4087
4088        \return
4089                - Index of the first code point that does not match any one of the chars in \a chars starting from from \a idx.
4090                - npos if all code points matched any of the chars in \a chars.
4091
4092        \exception std::length_error    Thrown if \a chars_len was 'npos'.
4093        */
4094        size_type       find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
4095        {
4096                if (chars_len == npos)
4097                        throw std::length_error("Length for char array can not be 'npos'");
4098
4099                if (idx < d_cplength)
4100                {
4101                        const utf32* pt = &ptr()[idx];
4102
4103                        do
4104                        {
4105                                if (npos == find_codepoint(chars, chars_len, *pt++))
4106                                        return idx;
4107
4108                        } while (++idx != d_cplength);
4109
4110                }
4111
4112                return npos;
4113        }
4114
4115
4116        //////////////////////////////////////////////////////////////////////////
4117        // Find last of different code-points
4118        //////////////////////////////////////////////////////////////////////////
4119        /*!
4120        \brief
4121                Find the last occurrence of one of a set of code points.
4122
4123        \param str
4124                String object describing the set of code points.
4125
4126        \param idx
4127                Index of the start point for the search
4128
4129        \return
4130                - Index of the last occurrence of any one of the code points in \a str starting from \a idx.
4131                - npos if none of the code points in \a str were found.
4132        */
4133        size_type       find_last_of(const String& str, size_type idx = npos) const
4134        {
4135                if (d_cplength > 0)
4136                {
4137                        if (idx >= d_cplength)
4138                                idx = d_cplength - 1;
4139
4140                        const utf32* pt = &ptr()[idx];
4141
4142                        do
4143                        {
4144                                if (npos != str.find(*pt--))
4145                                        return idx;
4146
4147                        } while (idx-- != 0);
4148
4149                }
4150
4151                return npos;
4152        }
4153
4154        /*!
4155        \brief
4156                Find the last code point that is not one of a set of code points.
4157
4158        \param str
4159                String object describing the set of code points.
4160
4161        \param idx
4162                Index of the start point for the search
4163
4164        \return
4165                - Index of the last code point that does not match any one of the code points in \a str starting from \a idx.
4166                - npos if all code points matched one of the code points in \a str.
4167        */
4168        size_type       find_last_not_of(const String& str, size_type idx = npos) const
4169        {
4170                if (d_cplength > 0)
4171                {
4172                        if (idx >= d_cplength)
4173                                idx = d_cplength - 1;
4174
4175                        const utf32* pt = &ptr()[idx];
4176
4177                        do
4178                        {
4179                                if (npos == str.find(*pt--))
4180                                        return idx;
4181
4182                        } while (idx-- != 0);
4183
4184                }
4185
4186                return npos;
4187        }
4188
4189
4190        /*!
4191        \brief
4192                Find the last occurrence of one of a set of code points.
4193
4194        \param std_str
4195                std::string object describing the set of code points.
4196
4197        \note
4198                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
4199                the provided data will occur.
4200
4201        \param idx
4202                Index of the start point for the search
4203
4204        \return
4205                - Index of the last occurrence of any one of the code points in \a std_str starting from \a idx.
4206                - npos if none of the code points in \a std_str were found.
4207        */
4208        size_type       find_last_of(const std::string& std_str, size_type idx = npos) const
4209        {
4210                if (d_cplength > 0)
4211                {
4212                        if (idx >= d_cplength)
4213                                idx = d_cplength - 1;
4214
4215                        const utf32* pt = &ptr()[idx];
4216
4217                        do
4218                        {
4219                                if (npos != find_codepoint(std_str, *pt--))
4220                                        return idx;
4221
4222                        } while (idx-- != 0);
4223
4224                }
4225
4226                return npos;
4227        }
4228
4229        /*!
4230        \brief
4231                Find the last code point that is not one of a set of code points.
4232
4233        \param std_str
4234                std::string object describing the set of code points.
4235
4236        \note
4237                The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
4238                the provided data will occur.
4239
4240        \param idx
4241                Index of the start point for the search
4242
4243        \return
4244                - Index of the last code point that does not match any one of the code points in \a std_str starting from \a idx.
4245                - npos if all code points matched one of the code points in \a std_str.
4246        */
4247        size_type       find_last_not_of(const std::string& std_str, size_type idx = npos) const
4248        {
4249                if (d_cplength > 0)
4250                {
4251                        if (idx >= d_cplength)
4252                                idx = d_cplength - 1;
4253
4254                        const utf32* pt = &ptr()[idx];
4255
4256                        do
4257                        {
4258                                if (npos == find_codepoint(std_str, *pt--))
4259                                        return idx;
4260
4261                        } while (idx-- != 0);
4262
4263                }
4264
4265                return npos;
4266        }
4267
4268
4269        /*!
4270        \brief
4271                Find the last occurrence of one of a set of code points.
4272
4273        \param utf8_str
4274                Buffer containing null-terminated utf8 encoded data describing the set of code points.
4275
4276        \note
4277                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
4278                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
4279                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
4280                results.
4281
4282        \param idx
4283                Index of the start point for the search
4284
4285        \return
4286                - Index of the last occurrence of any one of the code points in \a utf8_str starting from \a idx.
4287                - npos if none of the code points in \a utf8_str were found.
4288
4289        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
4290        */
4291        size_type       find_last_of(const utf8* utf8_str, size_type idx = npos) const
4292        {
4293                return find_last_of(utf8_str, idx, utf_length(utf8_str));
4294        }
4295
4296        /*!
4297        \brief
4298                Find the last code point that is not one of a set of code points.
4299
4300        \param utf8_str
4301                Buffer containing null-terminated utf8 encoded data describing the set of code points.
4302
4303        \note
4304                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
4305                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
4306                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
4307                results.
4308
4309        \param idx
4310                Index of the start point for the search
4311
4312        \return
4313                - Index of the last code point that does not match any one of the code points in \a utf8_str starting from \a idx.
4314                - npos if all code points matched one of the code points in \a utf8_str.
4315
4316        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
4317        */
4318        size_type       find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
4319        {
4320                return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
4321        }
4322
4323        /*!
4324        \brief
4325                Find the last occurrence of one of a set of code points.
4326
4327        \param utf8_str
4328                Buffer containing utf8 encoded data describing the set of code points.
4329
4330        \note
4331                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
4332                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
4333                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
4334                results.
4335
4336        \param idx
4337                Index of the start point for the search
4338
4339        \param str_len
4340                Length of the utf8 encoded data in utf8 code units (not code points).
4341
4342        \return
4343                - Index of the last occurrence of any one of the code points in \a utf8_str starting from from \a idx.
4344                - npos if none of the code points in \a utf8_str were found.
4345
4346        \exception std::length_error    Thrown if \a str_len was 'npos'.
4347        */
4348        size_type       find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4349        {
4350                if (str_len == npos)
4351                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
4352
4353                if (d_cplength > 0)
4354                {
4355                        if (idx >= d_cplength)
4356                                idx = d_cplength - 1;
4357
4358                        size_type encsze = encoded_size(utf8_str, str_len);
4359
4360                        const utf32* pt = &ptr()[idx];
4361
4362                        do
4363                        {
4364                                if (npos != find_codepoint(utf8_str, encsze, *pt--))
4365                                        return idx;
4366
4367                        } while (idx-- != 0);
4368
4369                }
4370
4371                return npos;
4372        }
4373
4374        /*!
4375        \brief
4376                Find the last code point that is not one of a set of code points.
4377
4378        \param utf8_str
4379                Buffer containing utf8 encoded data describing the set of code points.
4380
4381        \note
4382                A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
4383                comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
4384                would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
4385                results.
4386
4387        \param idx
4388                Index of the start point for the search
4389
4390        \param str_len
4391                Length of the utf8 encoded data in utf8 code units (not code points).
4392
4393        \return
4394                - Index of the last code point that does not match any one of the code points in \a utf8_str starting from from \a idx.
4395                - npos if all code points matched one of the code points in \a utf8_str.
4396
4397        \exception std::length_error    Thrown if \a str_len was 'npos'.
4398        */
4399        size_type       find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4400        {
4401                if (str_len == npos)
4402                        throw std::length_error("Length for utf8 encoded string can not be 'npos'");
4403
4404                if (d_cplength > 0)
4405                {
4406                        if (idx >= d_cplength)
4407                                idx = d_cplength - 1;
4408
4409                        size_type encsze = encoded_size(utf8_str, str_len);
4410
4411                        const utf32* pt = &ptr()[idx];
4412
4413                        do
4414                        {
4415                                if (npos == find_codepoint(utf8_str, encsze, *pt--))
4416                                        return idx;
4417
4418                        } while (idx-- != 0);
4419
4420                }
4421
4422                return npos;
4423        }
4424
4425
4426        /*!
4427        \brief
4428                Search for last occurrence of a given code point
4429
4430        \param code_point
4431                The utf32 code point to search for
4432
4433        \param idx
4434                Index of the code point where the search is to start.
4435
4436        \return
4437                - Index of the last occurrence of \a code_point starting from \a idx.
4438                - npos if the code point could not be found
4439        */
4440        size_type       find_last_of(utf32 code_point, size_type idx = npos) const
4441        {
4442                return rfind(code_point, idx);
4443        }
4444
4445        /*!
4446        \brief
4447                Search for the last code point that does not match a given code point
4448
4449        \param code_point
4450                The utf32 code point to search for
4451
4452        \param idx
4453                Index of the code point where the search is to start.
4454
4455        \return
4456                - Index of the last code point that does not match \a code_point starting from from \a idx.
4457                - npos if all code points matched \a code_point
4458        */
4459        size_type       find_last_not_of(utf32 code_point, size_type idx = npos) const
4460        {
4461                if (d_cplength > 0)
4462                {
4463                        if (idx >= d_cplength)
4464                                idx = d_cplength - 1;
4465
4466                        do
4467                        {
4468                                if ((*this)[idx] != code_point)
4469                                        return idx;
4470
4471                        } while(idx-- != 0);
4472
4473                }
4474
4475                return npos;
4476        }
4477
4478
4479        /*!
4480        \brief
4481                Find the last occurrence of one of a set of chars.
4482
4483        \param c_str
4484                c-string describing the set of chars.
4485
4486        \param idx
4487                Index of the start point for the search
4488
4489        \return
4490                - Index of the last occurrence of any one of the chars in \a c_str starting from \a idx.
4491                - npos if none of the chars in \a c_str were found.
4492
4493        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
4494        */
4495        size_type       find_last_of(const char* c_str, size_type idx = npos) const
4496        {
4497                return find_last_of(c_str, idx, strlen(c_str));
4498        }
4499
4500
4501        /*!
4502        \brief
4503                Find the last code point that is not one of a set of chars.
4504
4505        \param c_str
4506                c-string describing the set of chars.
4507
4508        \param idx
4509                Index of the start point for the search
4510
4511        \return
4512                - Index of the last code point that does not match any one of the chars in \a c_str starting from \a idx.
4513                - npos if all code points matched any of the chars in \a c_str.
4514
4515        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
4516        */
4517        size_type       find_last_not_of(const char* c_str, size_type idx = npos) const
4518        {
4519                return find_last_not_of(c_str, idx, strlen(c_str));
4520        }
4521
4522
4523        /*!
4524        \brief
4525                Find the last occurrence of one of a set of chars.
4526
4527        \param chars
4528                char array containing the set of chars.
4529
4530        \param idx
4531                Index of the start point for the search
4532
4533        \param chars_len
4534                Number of chars in the char array.
4535
4536        \return
4537                - Index of the last occurrence of any one of the chars in \a chars, starting from from \a idx.
4538                - npos if none of the chars in \a chars were found.
4539
4540        \exception std::length_error    Thrown if \a chars_len was 'npos'.
4541        */
4542        size_type       find_last_of(const char* chars, size_type idx, size_type chars_len) const
4543        {
4544                if (chars_len == npos)
4545                        throw std::length_error("Length for char array can not be 'npos'");
4546
4547                if (d_cplength > 0)
4548                {
4549                        if (idx >= d_cplength)
4550                                idx = d_cplength - 1;
4551
4552                        const utf32* pt = &ptr()[idx];
4553
4554                        do
4555                        {
4556                                if (npos != find_codepoint(chars, chars_len, *pt--))
4557                                        return idx;
4558
4559                        } while (idx-- != 0);
4560
4561                }
4562
4563                return npos;
4564        }
4565
4566
4567        /*!
4568        \brief
4569                Find the last code point that is not one of a set of chars.
4570
4571        \param chars
4572                char array containing the set of chars.
4573
4574        \param idx
4575                Index of the start point for the search
4576
4577        \param chars_len
4578                Number of chars in the char array.
4579
4580        \return
4581                - Index of the last code point that does not match any one of the chars in \a chars, starting from from \a idx.
4582                - npos if all code points matched any of the chars in \a chars.
4583
4584        \exception std::length_error    Thrown if \a chars_len was 'npos'.
4585        */
4586        size_type       find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
4587        {
4588                if (chars_len == npos)
4589                        throw std::length_error("Length for char array can not be 'npos'");
4590
4591                if (d_cplength > 0)
4592                {
4593                        if (idx >= d_cplength)
4594                                idx = d_cplength - 1;
4595
4596                        const utf32* pt = &ptr()[idx];
4597
4598                        do
4599                        {
4600                                if (npos == find_codepoint(chars, chars_len, *pt--))
4601                                        return idx;
4602
4603                        } while (idx-- != 0);
4604
4605                }
4606
4607                return npos;
4608        }
4609
4610
4611        //////////////////////////////////////////////////////////////////////////
4612        // Substring
4613        //////////////////////////////////////////////////////////////////////////
4614        /*!
4615        \brief
4616                Returns a substring of this String.
4617
4618        \param idx
4619                Index of the first code point to use for the sub-string.
4620
4621        \param len
4622                Maximum number of code points to use for the sub-string
4623
4624        \return
4625                A String object containing the specified sub-string.
4626
4627        \exception std::out_of_range    Thrown if \a idx is invalid for this String.
4628        */
4629        String  substr(size_type idx = 0, size_type len = npos) const
4630        {
4631                if (d_cplength < idx)
4632                        throw std::out_of_range("Index is out of range for this CEGUI::String");
4633
4634                return String(*this, idx, len);
4635        }
4636
4637        //////////////////////////////////////////////////////////////////////////
4638        // Iterator creation
4639        //////////////////////////////////////////////////////////////////////////
4640        /*!
4641        \brief
4642                Return a forwards iterator that describes the beginning of the String
4643
4644        \return
4645                iterator object that describes the beginning of the String.
4646        */
4647        iterator                begin(void)
4648        {
4649                return iterator(ptr());
4650        }
4651
4652        /*!
4653        \brief
4654                Return a constant forwards iterator that describes the beginning of the String
4655
4656        \return
4657                const_iterator object that describes the beginning of the String.
4658        */
4659        const_iterator  begin(void) const
4660        {
4661                return const_iterator(ptr());
4662        }
4663
4664        /*!
4665        \brief
4666                Return a forwards iterator that describes the end of the String
4667
4668        \return
4669                iterator object that describes the end of the String.
4670        */
4671        iterator                end(void)
4672        {
4673                return iterator(&ptr()[d_cplength]);
4674        }
4675
4676        /*!
4677        \brief
4678                Return a constant forwards iterator that describes the end of the String
4679
4680        \return
4681                const_iterator object that describes the end of the String.
4682        */
4683        const_iterator  end(void) const
4684        {
4685                return const_iterator(&ptr()[d_cplength]);
4686        }
4687
4688        /*!
4689        \brief
4690                Return a reverse iterator that describes the beginning of the String
4691
4692        \return
4693                reverse_iterator object that describes the beginning of the String (so is actually at the end)
4694        */
4695        reverse_iterator                rbegin(void)
4696        {
4697                return reverse_iterator(end());
4698        }
4699
4700        /*!
4701        \brief
4702                Return a constant reverse iterator that describes the beginning of the String
4703
4704        \return
4705                const_reverse_iterator object that describes the beginning of the String (so is actually at the end)
4706        */
4707        const_reverse_iterator  rbegin(void) const
4708        {
4709                return const_reverse_iterator(end());
4710        }
4711
4712        /*!
4713        \brief
4714                Return a reverse iterator that describes the end of the String
4715
4716        \return
4717                reverse_iterator object that describes the end of the String (so is actually at the beginning)
4718        */
4719        reverse_iterator                rend(void)
4720        {
4721                return reverse_iterator(begin());
4722        }
4723
4724        /*!
4725        \brief
4726                Return a constant reverse iterator that describes the end of the String
4727
4728        \return
4729                const_reverse_iterator object that describes the end of the String (so is actually at the beginning)
4730        */
4731        const_reverse_iterator  rend(void) const
4732        {
4733                return const_reverse_iterator(begin());
4734        }
4735
4736private:
4737        /*************************************************************************
4738                Implementation Functions
4739        *************************************************************************/
4740        // string management
4741
4742        // change size of allocated buffer so it is at least 'new_size'.
4743        // May or may not cause re-allocation and copy of buffer if size is larger
4744        // will never re-allocate to make size smaller.  (see trim())
4745    bool        grow(size_type new_size);
4746
4747        // perform re-allocation to remove wasted space.
4748    void        trim(void);
4749
4750        // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
4751        void    setlen(size_type len)
4752        {
4753                d_cplength = len;
4754                ptr()[len] = (utf32)(0);
4755        }
4756
4757        // return a ptr to the buffer in use.
4758        utf32*  ptr(void)
4759        {
4760                return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
4761        }
4762
4763        // return a ptr tot he buffer in use (const version)
4764        const utf32*    ptr(void) const
4765        {
4766                return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
4767        }
4768
4769        // initialise string object
4770        void    init(void)
4771        {
4772                d_reserve                       = STR_QUICKBUFF_SIZE;
4773                d_encodedbuff           = NULL;
4774                d_encodedbufflen        = 0;
4775                d_encodeddatlen         = 0;
4776                setlen(0);
4777        }
4778
4779        // return true if the given pointer is inside the string data
4780        bool    inside(utf32* inptr)
4781        {
4782                if (inptr < ptr() || ptr() + d_cplength <= inptr)
4783                        return false;
4784                else
4785                        return true;
4786        }
4787
4788        // compute distance between two iterators, returning a 'safe' value
4789        size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
4790        {
4791                return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
4792        }
4793       
4794        // encoding functions
4795        // for all:
4796        //      src_len is in code units, or 0 for null terminated string.
4797        //      dest_len is in code units.
4798        //      returns number of code units put into dest buffer.
4799        size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
4800        {
4801                // count length for null terminated source...
4802                if (src_len == 0)
4803                {
4804                        src_len = utf_length(src);
4805                }
4806
4807                size_type destCapacity = dest_len;
4808
4809                // while there is data in the source buffer,
4810                for (uint idx = 0; idx < src_len; ++idx)
4811                {
4812                        utf32   cp = src[idx];
4813
4814                        // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
4815                        if (destCapacity < encoded_size(cp))
4816                        {
4817                                break;
4818                        }
4819
4820                        if (cp < 0x80)
4821                        {
4822                                *dest++ = (utf8)cp;
4823                                --destCapacity;
4824                        }
4825                        else if (cp < 0x0800)
4826                        {
4827                                *dest++ = (utf8)((cp >> 6) | 0xC0);
4828                                *dest++ = (utf8)((cp & 0x3F) | 0x80);
4829                                destCapacity -= 2;
4830                        }
4831                        else if (cp < 0x10000)
4832                        {
4833                                *dest++ = (utf8)((cp >> 12) | 0xE0);
4834                                *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4835                                *dest++ = (utf8)((cp & 0x3F) | 0x80);
4836                                destCapacity -= 3;
4837                        }
4838                        else
4839                        {
4840                                *dest++ = (utf8)((cp >> 18) | 0xF0);
4841                                *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
4842                                *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4843                                *dest++ = (utf8)((cp & 0x3F) | 0x80);
4844                                destCapacity -= 4;
4845                        }
4846
4847                }
4848
4849                return dest_len - destCapacity;
4850        }
4851
4852        size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
4853        {
4854                // count length for null terminated source...
4855                if (src_len == 0)
4856                {
4857                        src_len = utf_length(src);
4858                }
4859
4860                size_type destCapacity = dest_len;
4861
4862                // while there is data in the source buffer, and space in the dest buffer
4863                for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
4864                {
4865                        utf32   cp;
4866                        utf8    cu = src[idx++];
4867
4868                        if (cu < 0x80)
4869                        {
4870                                cp = (utf32)(cu);
4871                        }
4872                        else if (cu < 0xE0)
4873                        {
4874                                cp = ((cu & 0x1F) << 6);
4875                                cp |= (src[idx++] & 0x3F);
4876                        }
4877                        else if (cu < 0xF0)
4878                        {
4879                                cp = ((cu & 0x0F) << 12);
4880                                cp |= ((src[idx++] & 0x3F) << 6);
4881                                cp |= (src[idx++] & 0x3F);
4882                        }
4883                        else
4884                        {
4885                                cp = ((cu & 0x07) << 18);
4886                                cp |= ((src[idx++] & 0x3F) << 12);
4887                                cp |= ((src[idx++] & 0x3F) << 6);
4888                                cp |= (src[idx++] & 0x3F);
4889                        }
4890
4891                        *dest++ = cp;
4892                        --destCapacity;
4893                }
4894
4895                return dest_len - destCapacity;
4896        }
4897
4898        // return the number of utf8 code units required to encode the given utf32 code point
4899        size_type encoded_size(utf32 code_point) const
4900        {
4901                if (code_point < 0x80)
4902                        return 1;
4903                else if (code_point < 0x0800)
4904                        return 2;
4905                else if (code_point < 0x10000)
4906                        return 3;
4907                else
4908                        return 4;
4909        }
4910
4911        // return number of code units required to re-encode given null-terminated utf32 data as utf8.  return does not include terminating null.
4912        size_type encoded_size(const utf32* buf) const
4913        {
4914                return encoded_size(buf, utf_length(buf));
4915        }
4916
4917        // return number of code units required to re-encode given utf32 data as utf8.   len is number of code units in 'buf'.
4918        size_type encoded_size(const utf32* buf, size_type len) const
4919        {
4920                size_type count = 0;
4921
4922                while (len--)
4923                {
4924                        count += encoded_size(*buf++);
4925                }
4926
4927                return count;
4928        }
4929
4930        // return number of utf32 code units required to re-encode given utf8 data as utf32.  return does not include terminating null.
4931        size_type encoded_size(const utf8* buf) const
4932        {
4933                return encoded_size(buf, utf_length(buf));
4934        }
4935
4936        // return number of utf32 code units required to re-encode given utf8 data as utf32.  len is number of code units in 'buf'.
4937        size_type encoded_size(const utf8* buf, size_type len) const
4938        {
4939                utf8 tcp;
4940                size_type count = 0;
4941
4942                while (len--)
4943                {
4944                        tcp = *buf++;
4945                        ++count;
4946
4947                        if (tcp < 0x80)
4948                        {
4949                        }
4950                        else if (tcp < 0xE0)
4951                        {
4952                                --len;
4953                                ++buf;
4954                        }
4955                        else if (tcp < 0xF0)
4956                        {
4957                                len -= 2;
4958                                buf += 2;
4959                        }
4960                        else
4961                        {
4962                                len -= 2;
4963                                buf += 3;
4964                        }
4965
4966                }
4967
4968                return count;
4969        }
4970
4971        // return number of code units in a null terminated string
4972        size_type utf_length(const utf8* utf8_str) const
4973        {
4974                size_type cnt = 0;
4975                while (*utf8_str++)
4976                        cnt++;
4977
4978                return cnt;
4979        }
4980
4981        // return number of code units in a null terminated string
4982        size_type utf_length(const utf32* utf32_str) const
4983        {
4984                size_type cnt = 0;
4985                while (*utf32_str++)
4986                        cnt++;
4987
4988                return cnt;
4989        }
4990
4991        // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
4992    utf8* build_utf8_buff(void) const;
4993
4994        // compare two utf32 buffers
4995        int     utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
4996        {
4997                if (!cp_count)
4998                        return 0;
4999
5000                while ((--cp_count) && (*buf1 == *buf2))
5001                        buf1++, buf2++;
5002               
5003                return *buf1 - *buf2;
5004        }
5005
5006        // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
5007        int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
5008        {
5009                if (!cp_count)
5010                        return 0;
5011
5012                while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
5013                        buf1++, buf2++;
5014
5015                return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
5016        }
5017
5018        // compare utf32 buffer with encoded utf8 data
5019        int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
5020        {
5021                if (!cp_count)
5022                        return 0;
5023
5024                utf32   cp;
5025                utf8    cu;
5026
5027                do
5028                {
5029                        cu = *buf2++;
5030
5031                        if (cu < 0x80)
5032                        {
5033                                cp = (utf32)(cu);
5034                        }
5035                        else if (cu < 0xE0)
5036                        {
5037                                cp = ((cu & 0x1F) << 6);
5038                                cp |= (*buf2++ & 0x3F);
5039                        }
5040                        else if (cu < 0xF0)
5041                        {
5042                                cp = ((cu & 0x0F) << 12);
5043                                cp |= ((*buf2++ & 0x3F) << 6);
5044                                cp |= (*buf2++ & 0x3F);
5045                        }
5046                        else
5047                        {
5048                                cp = ((cu & 0x07) << 18);
5049                                cp |= ((*buf2++ & 0x3F) << 12);
5050                                cp |= ((*buf2++ & 0x3F) << 6);
5051                                cp |= (*buf2++ & 0x3F);
5052                        }
5053
5054                } while ((*buf1++ == cp) && (--cp_count));
5055
5056                return (*--buf1) - cp;
5057        }
5058
5059        // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
5060        size_type find_codepoint(const std::string& str, utf32 code_point) const
5061        {
5062                size_type idx = 0, sze = (size_type)str.size();
5063
5064                while (idx != sze)
5065                {
5066                        if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
5067                                return idx;
5068
5069                        ++idx;
5070                }
5071
5072                return npos;
5073        }
5074
5075        // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none.  len is in code points.
5076        size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
5077        {
5078                size_type idx = 0;
5079
5080                utf32   cp;
5081                utf8    cu;
5082
5083                while (idx != len) {
5084                        cu = *str++;
5085
5086                        if (cu < 0x80)
5087                        {
5088                                cp = (utf32)(cu);
5089                        }
5090                        else if (cu < 0xE0)
5091                        {
5092                                cp = ((cu & 0x1F) << 6);
5093                                cp |= (*str++ & 0x3F);
5094                        }
5095                        else if (cu < 0xF0)
5096                        {
5097                                cp = ((cu & 0x0F) << 12);
5098                                cp |= ((*str++ & 0x3F) << 6);
5099                                cp |= (*str++ & 0x3F);
5100                        }
5101                        else
5102                        {
5103                                cp = ((cu & 0x07) << 18);
5104                                cp |= ((*str++ & 0x3F) << 12);
5105                                cp |= ((*str++ & 0x3F) << 6);
5106                                cp |= (*str++ & 0x3F);
5107                        }
5108
5109                        if (code_point == cp)
5110                                return idx;
5111
5112                        ++idx;
5113                }
5114
5115                return npos;
5116        }
5117
5118
5119        // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
5120        size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
5121        {
5122                for (size_type idx = 0; idx != chars_len; ++idx)
5123                {
5124                        if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
5125                                return idx;
5126                }
5127
5128                return npos;
5129        }
5130
5131};
5132
5133
5134//////////////////////////////////////////////////////////////////////////
5135// Comparison operators
5136//////////////////////////////////////////////////////////////////////////
5137/*!
5138\brief
5139        Return true if String \a str1 is equal to String \a str2
5140*/
5141bool CEGUIEXPORT        operator==(const String& str1, const String& str2);
5142
5143/*!
5144\brief
5145        Return true if String \a str is equal to std::string \a std_str
5146*/
5147bool CEGUIEXPORT        operator==(const String& str, const std::string& std_str);
5148
5149/*!
5150\brief
5151        Return true if String \a str is equal to std::string \a std_str
5152*/
5153bool CEGUIEXPORT        operator==(const std::string& std_str, const String& str);
5154
5155/*!
5156\brief
5157        Return true if String \a str is equal to null-terminated utf8 data \a utf8_str
5158*/
5159bool CEGUIEXPORT        operator==(const String& str, const utf8* utf8_str);
5160
5161/*!
5162\brief
5163        Return true if String \a str is equal to null-terminated utf8 data \a utf8_str
5164*/
5165bool CEGUIEXPORT        operator==(const utf8* utf8_str, const String& str);
5166
5167/*!
5168\brief
5169        Return true if String \a str1 is not equal to String \a str2
5170*/
5171bool CEGUIEXPORT        operator!=(const String& str1, const String& str2);
5172
5173/*!
5174\brief
5175        Return true if String \a str is not equal to std::string \a std_str
5176*/
5177bool CEGUIEXPORT        operator!=(const String& str, const std::string& std_str);
5178
5179/*!
5180\brief
5181        Return true if String \a str is not equal to std::string \a std_str
5182*/
5183bool CEGUIEXPORT        operator!=(const std::string& std_str, const String& str);
5184
5185/*!
5186\brief
5187        Return true if String \a str is not equal to null-terminated utf8 data \a utf8_str
5188*/
5189bool CEGUIEXPORT        operator!=(const String& str, const utf8* utf8_str);
5190
5191/*!
5192\brief
5193        Return true if String \a str is not equal to null-terminated utf8 data \a utf8_str
5194*/
5195bool CEGUIEXPORT        operator!=(const utf8* utf8_str, const String& str);
5196
5197/*!
5198\brief
5199        Return true if String \a str1 is lexicographically less than String \a str2
5200*/
5201bool CEGUIEXPORT        operator<(const String& str1, const String& str2);
5202
5203/*!
5204\brief
5205        Return true if String \a str is lexicographically less than std::string \a std_str
5206*/
5207bool CEGUIEXPORT        operator<(const String& str, const std::string& std_str);
5208
5209/*!
5210\brief
5211        Return true if String \a str is lexicographically less than std::string \a std_str
5212*/
5213bool CEGUIEXPORT        operator<(const std::string& std_str, const String& str);
5214
5215/*!
5216\brief
5217        Return true if String \a str is lexicographically less than null-terminated utf8 data \a utf8_str
5218*/
5219bool CEGUIEXPORT        operator<(const String& str, const utf8* utf8_str);
5220
5221/*!
5222\brief
5223        Return true if String \a str is lexicographically less than null-terminated utf8 data \a utf8_str
5224*/
5225bool CEGUIEXPORT        operator<(const utf8* utf8_str, const String& str);
5226
5227/*!
5228\brief
5229        Return true if String \a str1 is lexicographically greater than String \a str2
5230*/
5231bool CEGUIEXPORT        operator>(const String& str1, const String& str2);
5232
5233/*!
5234\brief
5235        Return true if String \a str is lexicographically greater than std::string \a std_str
5236*/
5237bool CEGUIEXPORT        operator>(const String& str, const std::string& std_str);
5238
5239/*!
5240\brief
5241        Return true if String \a str is lexicographically greater than std::string \a std_str
5242*/
5243bool CEGUIEXPORT        operator>(const std::string& std_str, const String& str);
5244
5245/*!
5246\brief
5247        Return true if String \a str is lexicographically greater than null-terminated utf8 data \a utf8_str
5248*/
5249bool CEGUIEXPORT        operator>(const String& str, const utf8* utf8_str);
5250
5251/*!
5252\brief
5253        Return true if String \a str is lexicographically greater than null-terminated utf8 data \a utf8_str
5254*/
5255bool CEGUIEXPORT        operator>(const utf8* utf8_str, const String& str);
5256
5257/*!
5258\brief
5259        Return true if String \a str1 is lexicographically less than or equal to String \a str2
5260*/
5261bool CEGUIEXPORT        operator<=(const String& str1, const String& str2);
5262
5263/*!
5264\brief
5265        Return true if String \a str is lexicographically less than or equal to std::string \a std_str
5266*/
5267bool CEGUIEXPORT        operator<=(const String& str, const std::string& std_str);
5268
5269/*!
5270\brief
5271        Return true if String \a str is lexicographically less than or equal to std::string \a std_str
5272*/
5273bool CEGUIEXPORT        operator<=(const std::string& std_str, const String& str);
5274
5275/*!
5276\brief
5277        Return true if String \a str is lexicographically less than or equal to null-terminated utf8 data \a utf8_str
5278*/
5279bool CEGUIEXPORT        operator<=(const String& str, const utf8* utf8_str);
5280
5281/*!
5282\brief
5283        Return true if String \a str is lexicographically less than or equal to null-terminated utf8 data \a utf8_str
5284*/
5285bool CEGUIEXPORT        operator<=(const utf8* utf8_str, const String& str);
5286
5287/*!
5288\brief
5289        Return true if String \a str1 is lexicographically greater than or equal to String \a str2
5290*/
5291bool CEGUIEXPORT        operator>=(const String& str1, const String& str2);
5292
5293/*!
5294\brief
5295        Return true if String \a str is lexicographically greater than or equal to std::string \a std_str
5296*/
5297bool CEGUIEXPORT        operator>=(const String& str, const std::string& std_str);
5298
5299/*!
5300\brief
5301        Return true if String \a str is lexicographically greater than or equal to std::string \a std_str
5302*/
5303bool CEGUIEXPORT        operator>=(const std::string& std_str, const String& str);
5304
5305/*!
5306\brief
5307        Return true if String \a str is lexicographically greater than or equal to null-terminated utf8 data \a utf8_str
5308*/
5309bool CEGUIEXPORT        operator>=(const String& str, const utf8* utf8_str);
5310
5311/*!
5312\brief
5313        Return true if String \a str is lexicographically greater than or equal to null-terminated utf8 data \a utf8_str
5314*/
5315bool CEGUIEXPORT        operator>=(const utf8* utf8_str, const String& str);
5316
5317/*!
5318\brief
5319        Return true if String \a str is equal to c-string \a c_str
5320*/
5321bool CEGUIEXPORT        operator==(const String& str, const char* c_str);
5322
5323/*!
5324\brief
5325        Return true if c-string \a c_str is equal to String \a str
5326*/
5327bool CEGUIEXPORT        operator==(const char* c_str, const String& str);
5328
5329/*!
5330\brief
5331        Return true if String \a str is not equal to c-string \a c_str
5332*/
5333bool CEGUIEXPORT        operator!=(const String& str, const char* c_str);
5334
5335/*!
5336\brief
5337        Return true if c-string \a c_str is not equal to String \a str
5338*/
5339bool CEGUIEXPORT        operator!=(const char* c_str, const String& str);
5340
5341/*!
5342\brief
5343        Return true if String \a str is lexicographically less than c-string \a c_str
5344*/
5345bool CEGUIEXPORT        operator<(const String& str, const char* c_str);
5346
5347/*!
5348\brief
5349        Return true if c-string \a c_str is lexicographically less than String \a str
5350*/
5351bool CEGUIEXPORT        operator<(const char* c_str, const String& str);
5352
5353/*!
5354\brief
5355Return true if String \a str is lexicographically greater than c-string \a c_str
5356*/
5357bool CEGUIEXPORT        operator>(const String& str, const char* c_str);
5358
5359/*!
5360\brief
5361Return true if c-string \a c_str is lexicographically greater than String \a str
5362*/
5363bool CEGUIEXPORT        operator>(const char* c_str, const String& str);
5364
5365/*!
5366\brief
5367        Return true if String \a str is lexicographically less than or equal to c-string \a c_str
5368*/
5369bool CEGUIEXPORT        operator<=(const String& str, const char* c_str);
5370
5371/*!
5372\brief
5373        Return true if c-string \a c_str is lexicographically less than or equal to String \a str
5374*/
5375bool CEGUIEXPORT        operator<=(const char* c_str, const String& str);
5376
5377/*!
5378\brief
5379        Return true if String \a str is lexicographically greater than or equal to c-string \a c_str
5380*/
5381bool CEGUIEXPORT        operator>=(const String& str, const char* c_str);
5382
5383/*!
5384\brief
5385        Return true if c-string \a c_str is lexicographically greater than or equal to String \a str
5386*/
5387bool CEGUIEXPORT        operator>=(const char* c_str, const String& str);
5388
5389//////////////////////////////////////////////////////////////////////////
5390// Concatenation operator functions
5391//////////////////////////////////////////////////////////////////////////
5392/*!
5393\brief
5394        Return String object that is the concatenation of the given inputs
5395
5396\param str1
5397        String object describing first part of the new string
5398
5399\param str2
5400        String object describing the second part of the new string
5401
5402\return
5403        A String object that is the concatenation of \a str1 and \a str2
5404
5405\exception std::length_error    Thrown if the resulting String would be too large.
5406*/
5407String CEGUIEXPORT      operator+(const String str1, const String& str2);
5408
5409/*!
5410\brief
5411        Return String object that is the concatenation of the given inputs
5412
5413\param str
5414        String object describing first part of the new string
5415
5416\param std_str
5417        std::string object describing the second part of the new string
5418
5419\return
5420        A String object that is the concatenation of \a str and \a std_str
5421
5422\exception std::length_error    Thrown if the resulting String would be too large.
5423*/
5424String CEGUIEXPORT      operator+(const String str, const std::string& std_str);
5425
5426/*!
5427\brief
5428        Return String object that is the concatenation of the given inputs
5429
5430\param std_str
5431        std::string object describing the first part of the new string
5432
5433\param str
5434        String object describing the second part of the new string
5435
5436\return
5437        A String object that is the concatenation of \a std_str and \a str
5438
5439\exception std::length_error    Thrown if the resulting String would be too large.
5440*/
5441String CEGUIEXPORT      operator+(const std::string& std_str, const String& str);
5442
5443/*!
5444\brief
5445        Return String object that is the concatenation of the given inputs
5446
5447\param str
5448        String object describing first part of the new string
5449
5450\param utf8_str
5451        Buffer containing null-terminated utf8 encoded data describing the second part of the new string
5452
5453\return
5454        A String object that is the concatenation of \a str and \a utf8_str
5455
5456\exception std::length_error    Thrown if the resulting String would be too large.
5457*/
5458String CEGUIEXPORT      operator+(const String str, const utf8* utf8_str);
5459
5460/*!
5461\brief
5462        Return String object that is the concatenation of the given inputs
5463
5464\param utf8_str
5465        Buffer containing null-terminated utf8 encoded data describing the first part of the new string
5466
5467\param str
5468        String object describing the second part of the new string
5469
5470\return
5471        A String object that is the concatenation of \a str and \a utf8_str
5472
5473\exception std::length_error    Thrown if the resulting String would be too large.
5474*/
5475String CEGUIEXPORT      operator+(const utf8* utf8_str, const String& str);
5476
5477/*!
5478\brief
5479        Return String object that is the concatenation of the given inputs
5480
5481\param str
5482        String object describing the first part of the new string
5483
5484\param code_point
5485        utf32 code point describing the second part of the new string
5486
5487\return
5488        A String object that is the concatenation of \a str and \a code_point
5489
5490\exception std::length_error    Thrown if the resulting String would be too large.
5491*/
5492String CEGUIEXPORT      operator+(const String str, utf32 code_point);
5493
5494/*!
5495\brief
5496        Return String object that is the concatenation of the given inputs
5497
5498\param code_point
5499        utf32 code point describing the first part of the new string
5500
5501\param str
5502        String object describing the second part of the new string
5503
5504\return
5505        A String object that is the concatenation of \a code_point and \a str
5506
5507\exception std::length_error    Thrown if the resulting String would be too large.
5508*/
5509String CEGUIEXPORT      operator+(utf32 code_point, const String& str);
5510
5511/*!
5512\brief
5513        Return String object that is the concatenation of the given inputs
5514
5515\param str
5516        String object describing first part of the new string
5517
5518\param c_str
5519        c-string describing the second part of the new string
5520
5521\return
5522        A String object that is the concatenation of \a str and \a c_str
5523
5524\exception std::length_error    Thrown if the resulting String would be too large.
5525*/
5526String CEGUIEXPORT      operator+(const String str, const char* c_str);
5527
5528/*!
5529\brief
5530        Return String object that is the concatenation of the given inputs
5531
5532\param c_str
5533        c-string describing the first part of the new string
5534
5535\param str
5536        String object describing the second part of the new string
5537
5538\return
5539        A String object that is the concatenation of \a c_str and \a str
5540
5541\exception std::length_error    Thrown if the resulting String would be too large.
5542*/
5543String CEGUIEXPORT      operator+(const char* c_str, const String& str);
5544
5545
5546//////////////////////////////////////////////////////////////////////////
5547// Output (stream) functions
5548//////////////////////////////////////////////////////////////////////////
5549std::ostream& operator<<(std::ostream& s, const String& str);
5550
5551
5552//////////////////////////////////////////////////////////////////////////
5553// Modifying operations
5554//////////////////////////////////////////////////////////////////////////
5555/*!
5556\brief
5557        Swap the contents for two String objects
5558
5559\param str1
5560        String object who's contents are to be swapped with \a str2
5561
5562\param str2
5563        String object who's contents are to be swapped with \a str1
5564
5565\return
5566        Nothing
5567*/
5568void CEGUIEXPORT swap(String& str1, String& str2);
5569
5570
5571} // End of  CEGUI namespace section
5572
5573
5574#endif  // end of guard _CEGUIString_h_
Note: See TracBrowser for help on using the repository browser.