Crazy Eddies GUI System  0.7.2
CEGUIString.h
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  * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining
12  * a copy of this software and associated documentation files (the
13  * "Software"), to deal in the Software without restriction, including
14  * without limitation the rights to use, copy, modify, merge, publish,
15  * distribute, sublicense, and/or sell copies of the Software, and to
16  * permit persons to whom the Software is furnished to do so, subject to
17  * the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be
20  * included in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  ***************************************************************************/
30 #ifndef _CEGUIString_h_
31 #define _CEGUIString_h_
32 
33 #include "CEGUIBase.h"
34 #include <string>
35 #include <string.h>
36 #include <stdexcept>
37 
38 // Start of CEGUI namespace section
39 namespace CEGUI
40 {
41 #define STR_QUICKBUFF_SIZE 32
42  /*************************************************************************
43  Basic Types
44  *************************************************************************/
45  typedef uint8 utf8;
46  //typedef uint16 utf16; // removed typedef to prevent usage, as utf16 is not supported (yet)
47  typedef uint32 utf32;
48 
57 class CEGUIEXPORT String
58 {
59 public:
60  /*************************************************************************
61  Integral Types
62  *************************************************************************/
63  typedef utf32 value_type;
64  typedef size_t size_type;
65  typedef ptrdiff_t difference_type;
66  typedef utf32& reference;
67  typedef const utf32& const_reference;
68  typedef utf32* pointer;
69  typedef const utf32* const_pointer;
70 
71  static const size_type npos;
72 
73 private:
74  /*************************************************************************
75  Implementation data
76  *************************************************************************/
77  size_type d_cplength;
78  size_type d_reserve;
79 
80  mutable utf8* d_encodedbuff;
81  mutable size_type d_encodeddatlen;
82  mutable size_type d_encodedbufflen;
83 
84  utf32 d_quickbuff[STR_QUICKBUFF_SIZE];
85  utf32* d_buffer;
86 
87 public:
88  /*************************************************************************
89  Iterator Classes
90  *************************************************************************/
95 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
96  class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32>
97 #else
98  class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32, std::ptrdiff_t, const utf32*, const utf32&>
99 #endif
100  {
101 
102  public:
104  // data
106  const utf32* d_ptr;
107 
108 
110  // Methods
112  const_iterator(void)
113  {
114  d_ptr = 0;
115  }
117  {
118  d_ptr = ptr;
119  }
120 
121  const_reference operator*() const
122  {
123  return *d_ptr;
124  }
125 
126 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
127 # pragma warning (push)
128 # pragma warning (disable : 4284)
129 #endif
130  const_pointer operator->() const
131  {
132  return &**this;
133  }
134 
135 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
136 # pragma warning (pop)
137 #endif
138 
139  const_iterator& operator++()
140  {
141  ++d_ptr;
142  return *this;
143  }
144 
145  const_iterator operator++(int)
146  {
147  const_iterator temp = *this;
148  ++*this;
149  return temp;
150  }
151 
152  const_iterator& operator--()
153  {
154  --d_ptr;
155  return *this;
156  }
157 
158  const_iterator operator--(int)
159  {
160  const_iterator temp = *this;
161  --*this;
162  return temp;
163  }
164 
165  const_iterator& operator+=(difference_type offset)
166  {
167  d_ptr += offset;
168  return *this;
169  }
170 
172  {
173  const_iterator temp = *this;
174  return temp += offset;
175  }
176 
177  const_iterator& operator-=(difference_type offset)
178  {
179  return *this += -offset;
180  }
181 
182  const_iterator operator-(difference_type offset) const
183  {
184  const_iterator temp = *this;
185  return temp -= offset;
186  }
187 
188  difference_type operator-(const const_iterator& iter) const
189  {
190  return d_ptr - iter.d_ptr;
191  }
192 
193  const_reference operator[](difference_type offset) const
194  {
195  return *(*this + offset);
196  }
197 
198  bool operator==(const const_iterator& iter) const
199  {
200  return d_ptr == iter.d_ptr;
201  }
202 
203  bool operator!=(const const_iterator& iter) const
204  {
205  return !(*this == iter);
206  }
207 
208  bool operator<(const const_iterator& iter) const
209  {
210  return d_ptr < iter.d_ptr;
211  }
212 
213  bool operator>(const const_iterator& iter) const
214  {
215  return (!(iter < *this));
216  }
217 
218  bool operator<=(const const_iterator& iter) const
219  {
220  return (!(iter < *this));
221  }
222 
223  bool operator>=(const const_iterator& iter) const
224  {
225  return (!(*this < iter));
226  }
227 
228  friend const_iterator operator+(difference_type offset, const const_iterator& iter)
229  {
230  return iter + offset;
231  }
232 
233  };
234 
239  class iterator : public const_iterator
240  {
241  public:
242  iterator(void) {}
243  iterator(pointer ptr) : const_iterator(ptr) {}
244 
245 
246  reference operator*() const
247  {
248  return ((reference)**(const_iterator *)this);
249  }
250 
251 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
252 # pragma warning (push)
253 # pragma warning (disable : 4284)
254 #endif
255 
256  pointer operator->() const
257  {
258  return &**this;
259  }
260 
261 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
262 # pragma warning (pop)
263 #endif
264 
265  iterator& operator++()
266  {
267  ++this->d_ptr;
268  return *this;
269  }
270 
271  iterator operator++(int)
272  {
273  iterator temp = *this;
274  ++*this;
275  return temp;
276  }
277 
278  iterator& operator--()
279  {
280  --this->d_ptr;
281  return *this;
282  }
283 
284  iterator operator--(int)
285  {
286  iterator temp = *this;
287  --*this;
288  return temp;
289  }
290 
291  iterator& operator+=(difference_type offset)
292  {
293  this->d_ptr += offset;
294  return *this;
295  }
296 
297  iterator operator+(difference_type offset) const
298  {
299  iterator temp = *this;
300  return temp += offset;
301  }
302 
303  iterator& operator-=(difference_type offset)
304  {
305  return *this += -offset;
306  }
307 
308  iterator operator-(difference_type offset) const
309  {
310  iterator temp = *this;
311  return temp -= offset;
312  }
313 
314  difference_type operator-(const const_iterator& iter) const
315  {
316  return ((const_iterator)*this - iter);
317  }
318 
319  reference operator[](difference_type offset) const
320  {
321  return *(*this + offset);
322  }
323 
324  friend iterator operator+(difference_type offset, const iterator& iter)
325  {
326  return iter + offset;
327  }
328 
329  };
330 
335 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
336  typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator;
337 #else
338  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
339 #endif
340 
345 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
346  typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator;
347 #else
348  typedef std::reverse_iterator<iterator> reverse_iterator;
349 #endif
350 
351 public:
358  {
359  bool operator() (const String& a, const String& b) const
360  {
361  const size_t la = a.length();
362  const size_t lb = b.length();
363  if (la == lb)
364  return (memcmp(a.ptr(), b.ptr(), la*sizeof(utf32)) < 0);
365  return (la < lb);
366  }
367  };
368 
369 public:
371  // Default Construction and Destructor
373 
377  String(void)
378  {
379  init();
380  }
381 
386  ~String(void);
387 
389  // Construction via CEGUI::String
391 
401  String(const String& str)
402  {
403  init();
404  assign(str);
405  }
406 
407 
424  String(const String& str, size_type str_idx, size_type str_num = npos)
425  {
426  init();
427  assign(str, str_idx, str_num);
428  }
429 
431  // Construction via std::string
433 
449  String(const std::string& std_str)
450  {
451  init();
452  assign(std_str);
453  }
454 
477  String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
478  {
479  init();
480  assign(std_str, str_idx, str_num);
481  }
482 
483 
485  // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
487 
505  String(const utf8* utf8_str)
506  {
507  init();
508  assign(utf8_str);
509  }
510 
537  String(const utf8* utf8_str, size_type chars_len)
538  {
539  init();
540  assign(utf8_str, chars_len);
541  }
542 
544  // Construction via code-point (using a UTF-32 code unit)
546 
561  String(size_type num, utf32 code_point)
562  {
563  init();
564  assign(num, code_point);
565  }
566 
568  // Construction via iterator
570  // Create string with characters in the range [beg, end)
585  {
586  init();
587  append(iter_beg, iter_end);
588  }
589 
590 
592  // Construction via c-string
594 
606  String(const char* cstr)
607  {
608  init();
609  assign(cstr);
610  }
611 
627  String(const char* chars, size_type chars_len)
628  {
629  init();
630  assign(chars, chars_len);
631  }
632 
633 
635  // Size operations
637 
644  size_type size(void) const
645  {
646  return d_cplength;
647  }
648 
656  size_type length(void) const
657  {
658  return d_cplength;
659  }
660 
668  bool empty(void) const
669  {
670  return (d_cplength == 0);
671  }
672 
682  static size_type max_size(void)
683  {
684  return (((size_type)-1) / sizeof(utf32));
685  }
686 
688  // Capacity Operations
690  // return the number of code points the string could hold without re-allocation
691  // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
700  size_type capacity(void) const
701  {
702  return d_reserve - 1;
703  }
704 
705  // reserve internal memory for at-least 'num' code-points (characters). if num is 0, request is shrink-to-fit.
720  void reserve(size_type num = 0)
721  {
722  if (num == 0)
723  trim();
724  else
725  grow(num);
726  }
727 
729  // Comparisons
731 
746  int compare(const String& str) const
747  {
748  return compare(0, d_cplength, str);
749  }
750 
780  int compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
781  {
782  if ((d_cplength < idx) || (str.d_cplength < str_idx))
783  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
784 
785  if ((len == npos) || (idx + len > d_cplength))
786  len = d_cplength - idx;
787 
788  if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
789  str_len = str.d_cplength - str_idx;
790 
791  int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
792 
793  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
794  }
795 
796 
816  int compare(const std::string& std_str) const
817  {
818  return compare(0, d_cplength, std_str);
819  }
820 
821 
855  int compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
856  {
857  if (d_cplength < idx)
858  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
859 
860  if (std_str.size() < str_idx)
861  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
862 
863  if ((len == npos) || (idx + len > d_cplength))
864  len = d_cplength - idx;
865 
866  if ((str_len == npos) || (str_idx + str_len > std_str.size()))
867  str_len = (size_type)std_str.size() - str_idx;
868 
869  int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
870 
871  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
872  }
873 
874 
896  int compare(const utf8* utf8_str) const
897  {
898  return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
899  }
900 
901 
931  int compare(size_type idx, size_type len, const utf8* utf8_str) const
932  {
933  return compare(idx, len, utf8_str, encoded_size(utf8_str));
934  }
935 
969  int compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
970  {
971  if (d_cplength < idx)
972  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
973 
974  if (str_cplen == npos)
975  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
976 
977  if ((len == npos) || (idx + len > d_cplength))
978  len = d_cplength - idx;
979 
980  int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
981 
982  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
983  }
984 
985 
1001  int compare(const char* cstr) const
1002  {
1003  return compare(0, d_cplength, cstr, strlen(cstr));
1004  }
1005 
1006 
1030  int compare(size_type idx, size_type len, const char* cstr) const
1031  {
1032  return compare(idx, len, cstr, strlen(cstr));
1033  }
1034 
1035 
1063  int compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
1064  {
1065  if (d_cplength < idx)
1066  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1067 
1068  if (chars_len == npos)
1069  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
1070 
1071  if ((len == npos) || (idx + len > d_cplength))
1072  len = d_cplength - idx;
1073 
1074  int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
1075 
1076  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
1077  }
1078 
1079 
1081  // Character access
1083 
1097  reference operator[](size_type idx)
1098  {
1099  return (ptr()[idx]);
1100  }
1101 
1116  value_type operator[](size_type idx) const
1117  {
1118  return ptr()[idx];
1119  }
1120 
1134  {
1135  if (d_cplength <= idx)
1136  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1137 
1138  return ptr()[idx];
1139  }
1140 
1154  {
1155  if (d_cplength <= idx)
1156  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1157 
1158  return ptr()[idx];
1159  }
1160 
1161 
1163  // C-Strings and arrays
1165 
1178  const char* c_str(void) const
1179  {
1180  return (const char*)build_utf8_buff();
1181  }
1182 
1196  const utf8* data(void) const
1197  {
1198  return build_utf8_buff();
1199  }
1200 
1205  utf32* ptr(void)
1206  {
1207  return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
1208  }
1209 
1214  const utf32* ptr(void) const
1215  {
1216  return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
1217  }
1218 
1219  // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
1220  // return number of utf8 code units placed into the buffer
1241  size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const
1242  {
1243  if (d_cplength < idx)
1244  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1245 
1246  if (len == npos)
1247  len = d_cplength;
1248 
1249  return encode(&ptr()[idx], buf, npos, len);
1250  }
1251 
1253  // UTF8 Encoding length information
1255  // 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.
1271  size_type utf8_stream_len(size_type num = npos, size_type idx = 0) const
1272  {
1273  using namespace std;
1274 
1275  if (d_cplength < idx)
1276  CEGUI_THROW(out_of_range("Index was out of range for CEGUI::String object"));
1277 
1278  size_type maxlen = d_cplength - idx;
1279 
1280  return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
1281  }
1282 
1284  // Assignment Functions
1286 
1296  String& operator=(const String& str)
1297  {
1298  return assign(str);
1299  }
1300 
1319  String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
1320  {
1321  if (str.d_cplength < str_idx)
1322  CEGUI_THROW(std::out_of_range("Index was out of range for CEGUI::String object"));
1323 
1324  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
1325  str_num = str.d_cplength - str_idx;
1326 
1327  grow(str_num);
1328  setlen(str_num);
1329  memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
1330 
1331  return *this;
1332  }
1333 
1350  String& operator=(const std::string& std_str)
1351  {
1352  return assign(std_str);
1353  }
1354 
1378  String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1379  {
1380  if (std_str.size() < str_idx)
1381  CEGUI_THROW(std::out_of_range("Index was out of range for std::string object"));
1382 
1383  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
1384  str_num = (size_type)std_str.size() - str_idx;
1385 
1386  grow(str_num);
1387  setlen(str_num);
1388 
1389  while(str_num--)
1390  {
1391  ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
1392  }
1393 
1394  return *this;
1395  }
1396 
1415  String& operator=(const utf8* utf8_str)
1416  {
1417  return assign(utf8_str, utf_length(utf8_str));
1418  }
1419 
1438  String& assign(const utf8* utf8_str)
1439  {
1440  return assign(utf8_str, utf_length(utf8_str));
1441  }
1442 
1464  String& assign(const utf8* utf8_str, size_type str_num)
1465  {
1466  if (str_num == npos)
1467  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
1468 
1469  size_type enc_sze = encoded_size(utf8_str, str_num);
1470 
1471  grow(enc_sze);
1472  encode(utf8_str, ptr(), d_reserve, str_num);
1473  setlen(enc_sze);
1474  return *this;
1475  }
1476 
1487  String& operator=(utf32 code_point)
1488  {
1489  return assign(1, code_point);
1490  }
1491 
1507  String& assign(size_type num, utf32 code_point)
1508  {
1509  if (num == npos)
1510  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
1511 
1512  grow(num);
1513  setlen(num);
1514  utf32* p = ptr();
1515 
1516  while(num--)
1517  *p++ = code_point;
1518 
1519  return *this;
1520  }
1521 
1522 
1535  String& operator=(const char* cstr)
1536  {
1537  return assign(cstr, strlen(cstr));
1538  }
1539 
1540 
1553  String& assign(const char* cstr)
1554  {
1555  return assign(cstr, strlen(cstr));
1556  }
1557 
1558 
1574  String& assign(const char* chars, size_type chars_len)
1575  {
1576  grow(chars_len);
1577  utf32* pt = ptr();
1578 
1579  for (size_type i = 0; i < chars_len; ++i)
1580  {
1581  *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
1582  }
1583 
1584  setlen(chars_len);
1585  return *this;
1586  }
1587 
1588 
1599  void swap(String& str)
1600  {
1601  size_type temp_len = d_cplength;
1602  d_cplength = str.d_cplength;
1603  str.d_cplength = temp_len;
1604 
1605  size_type temp_res = d_reserve;
1606  d_reserve = str.d_reserve;
1607  str.d_reserve = temp_res;
1608 
1609  utf32* temp_buf = d_buffer;
1610  d_buffer = str.d_buffer;
1611  str.d_buffer = temp_buf;
1612 
1613  // see if we need to swap 'quick buffer' data
1614  if (temp_res <= STR_QUICKBUFF_SIZE)
1615  {
1616  utf32 temp_qbf[STR_QUICKBUFF_SIZE];
1617 
1618  memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
1619  memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
1620  memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
1621  }
1622 
1623  }
1624 
1626  // Appending Functions
1628 
1640  String& operator+=(const String& str)
1641  {
1642  return append(str);
1643  }
1644 
1664  String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
1665  {
1666  if (str.d_cplength < str_idx)
1667  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1668 
1669  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
1670  str_num = str.d_cplength - str_idx;
1671 
1672  grow(d_cplength + str_num);
1673  memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
1674  setlen(d_cplength + str_num);
1675  return *this;
1676  }
1677 
1678 
1695  String& operator+=(const std::string& std_str)
1696  {
1697  return append(std_str);
1698  }
1699 
1723  String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1724  {
1725  if (std_str.size() < str_idx)
1726  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
1727 
1728  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
1729  str_num = (size_type)std_str.size() - str_idx;
1730 
1731  size_type newsze = d_cplength + str_num;
1732 
1733  grow(newsze);
1734  utf32* pt = &ptr()[newsze-1];
1735 
1736  while(str_num--)
1737  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
1738 
1739  setlen(newsze);
1740  return *this;
1741  }
1742 
1743 
1762  String& operator+=(const utf8* utf8_str)
1763  {
1764  return append(utf8_str, utf_length(utf8_str));
1765  }
1766 
1785  String& append(const utf8* utf8_str)
1786  {
1787  return append(utf8_str, utf_length(utf8_str));
1788  }
1789 
1790 
1812  String& append(const utf8* utf8_str, size_type len)
1813  {
1814  if (len == npos)
1815  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
1816 
1817  size_type encsz = encoded_size(utf8_str, len);
1818  size_type newsz = d_cplength + encsz;
1819 
1820  grow(newsz);
1821  encode(utf8_str, &ptr()[d_cplength], encsz, len);
1822  setlen(newsz);
1823 
1824  return *this;
1825  }
1826 
1827 
1840  String& operator+=(utf32 code_point)
1841  {
1842  return append(1, code_point);
1843  }
1844 
1860  String& append(size_type num, utf32 code_point)
1861  {
1862  if (num == npos)
1863  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
1864 
1865  size_type newsz = d_cplength + num;
1866  grow(newsz);
1867 
1868  utf32* p = &ptr()[d_cplength];
1869 
1870  while(num--)
1871  *p++ = code_point;
1872 
1873  setlen(newsz);
1874 
1875  return *this;
1876  }
1877 
1890  void push_back(utf32 code_point)
1891  {
1892  append(1, code_point);
1893  }
1894 
1910  String& append(const_iterator iter_beg, const_iterator iter_end)
1911  {
1912  return replace(end(), end(), iter_beg, iter_end);
1913  }
1914 
1915 
1928  String& operator+=(const char* cstr)
1929  {
1930  return append(cstr, strlen(cstr));
1931  }
1932 
1933 
1946  String& append(const char* cstr)
1947  {
1948  return append(cstr, strlen(cstr));
1949  }
1950 
1951 
1967  String& append(const char* chars, size_type chars_len)
1968  {
1969  if (chars_len == npos)
1970  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
1971 
1972  size_type newsz = d_cplength + chars_len;
1973 
1974  grow(newsz);
1975 
1976  utf32* pt = &ptr()[newsz-1];
1977 
1978  while(chars_len--)
1979  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
1980 
1981  setlen(newsz);
1982 
1983  return *this;
1984  }
1985 
1986 
1988  // Insertion Functions
1990 
2006  String& insert(size_type idx, const String& str)
2007  {
2008  return insert(idx, str, 0, npos);
2009  }
2010 
2033  String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
2034  {
2035  if ((d_cplength < idx) || (str.d_cplength < str_idx))
2036  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2037 
2038  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
2039  str_num = str.d_cplength - str_idx;
2040 
2041  size_type newsz = d_cplength + str_num;
2042  grow(newsz);
2043  memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2044  memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2045  setlen(newsz);
2046 
2047  return *this;
2048  }
2049 
2070  String& insert(size_type idx, const std::string& std_str)
2071  {
2072  return insert(idx, std_str, 0, npos);
2073  }
2074 
2101  String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
2102  {
2103  if (d_cplength < idx)
2104  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2105 
2106  if (std_str.size() < str_idx)
2107  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
2108 
2109  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
2110  str_num = (size_type)std_str.size() - str_idx;
2111 
2112  size_type newsz = d_cplength + str_num;
2113  grow(newsz);
2114 
2115  memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2116 
2117  utf32* pt = &ptr()[idx + str_num - 1];
2118 
2119  while(str_num--)
2120  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2121 
2122  setlen(newsz);
2123 
2124  return *this;
2125  }
2126 
2149  String& insert(size_type idx, const utf8* utf8_str)
2150  {
2151  return insert(idx, utf8_str, utf_length(utf8_str));
2152  }
2153 
2179  String& insert(size_type idx, const utf8* utf8_str, size_type len)
2180  {
2181  if (d_cplength < idx)
2182  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2183 
2184  if (len == npos)
2185  CEGUI_THROW(std::length_error("Length of utf8 encoded string can not be 'npos'"));
2186 
2187  size_type encsz = encoded_size(utf8_str, len);
2188  size_type newsz = d_cplength + encsz;
2189 
2190  grow(newsz);
2191  memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2192  encode(utf8_str, &ptr()[idx], encsz, len);
2193  setlen(newsz);
2194 
2195  return *this;
2196  }
2197 
2217  String& insert(size_type idx, size_type num, utf32 code_point)
2218  {
2219  if (d_cplength < idx)
2220  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2221 
2222  if (num == npos)
2223  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
2224 
2225  size_type newsz = d_cplength + num;
2226  grow(newsz);
2227 
2228  memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2229 
2230  utf32* pt = &ptr()[idx + num - 1];
2231 
2232  while(num--)
2233  *pt-- = code_point;
2234 
2235  setlen(newsz);
2236 
2237  return *this;
2238  }
2239 
2258  void insert(iterator pos, size_type num, utf32 code_point)
2259  {
2260  insert(safe_iter_dif(pos, begin()), num, code_point);
2261  }
2262 
2278  iterator insert(iterator pos, utf32 code_point)
2279  {
2280  insert(pos, 1, code_point);
2281  return pos;
2282  }
2283 
2302  void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
2303  {
2304  replace(iter_pos, iter_pos, iter_beg, iter_end);
2305  }
2306 
2307 
2324  String& insert(size_type idx, const char* cstr)
2325  {
2326  return insert(idx, cstr, strlen(cstr));
2327  }
2328 
2329 
2349  String& insert(size_type idx, const char* chars, size_type chars_len)
2350  {
2351  if (d_cplength < idx)
2352  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2353 
2354  if (chars_len == npos)
2355  CEGUI_THROW(std::length_error("Length of char array can not be 'npos'"));
2356 
2357  size_type newsz = d_cplength + chars_len;
2358 
2359  grow(newsz);
2360  memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2361 
2362  utf32* pt = &ptr()[idx + chars_len - 1];
2363 
2364  while(chars_len--)
2365  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
2366 
2367  setlen(newsz);
2368 
2369  return *this;
2370  }
2371 
2372 
2374  // Erasing characters
2376 
2383  void clear(void)
2384  {
2385  setlen(0);
2386  trim();
2387  }
2388 
2396  String& erase(void)
2397  {
2398  clear();
2399  return *this;
2400  }
2401 
2414  String& erase(size_type idx)
2415  {
2416  return erase(idx, 1);
2417  }
2418 
2434  String& erase(size_type idx, size_type len = npos)
2435  {
2436  // cover the no-op case.
2437  if (len == 0)
2438  return *this;
2439 
2440  if (d_cplength <= idx)
2441  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2442 
2443  if (len == npos)
2444  len = d_cplength - idx;
2445 
2446  size_type newsz = d_cplength - len;
2447 
2448  memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
2449  setlen(newsz);
2450  return *this;
2451  }
2452 
2463  String& erase(iterator pos)
2464  {
2465  return erase(safe_iter_dif(pos, begin()), 1);
2466  }
2467 
2481  String& erase(iterator iter_beg, iterator iter_end)
2482  {
2483  return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
2484  }
2485 
2487  // Resizing
2489 
2501  void resize(size_type num)
2502  {
2503  resize(num, utf32());
2504  }
2505 
2521  void resize(size_type num, utf32 code_point)
2522  {
2523  if (num < d_cplength)
2524  {
2525  setlen(num);
2526  }
2527  else
2528  {
2529  append(num - d_cplength, code_point);
2530  }
2531 
2532  }
2533 
2535  // Replacing Characters
2537 
2556  String& replace(size_type idx, size_type len, const String& str)
2557  {
2558  return replace(idx, len, str, 0, npos);
2559  }
2560 
2582  String& replace(iterator iter_beg, iterator iter_end, const String& str)
2583  {
2584  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
2585  }
2586 
2612  String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
2613  {
2614  if ((d_cplength < idx) || (str.d_cplength < str_idx))
2615  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2616 
2617  if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
2618  str_num = str.d_cplength - str_idx;
2619 
2620  if (((len + idx) > d_cplength) || (len == npos))
2621  len = d_cplength - idx;
2622 
2623  size_type newsz = d_cplength + str_num - len;
2624 
2625  grow(newsz);
2626 
2627  if ((idx + len) < d_cplength)
2628  memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2629 
2630  memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2631  setlen(newsz);
2632 
2633  return *this;
2634  }
2635 
2636 
2660  String& replace(size_type idx, size_type len, const std::string& std_str)
2661  {
2662  return replace(idx, len, std_str, 0, npos);
2663  }
2664 
2690  String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
2691  {
2692  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
2693  }
2694 
2724  String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
2725  {
2726  if (d_cplength < idx)
2727  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2728 
2729  if (std_str.size() < str_idx)
2730  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
2731 
2732  if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
2733  str_num = (size_type)std_str.size() - str_idx;
2734 
2735  if (((len + idx) > d_cplength) || (len == npos))
2736  len = d_cplength - idx;
2737 
2738  size_type newsz = d_cplength + str_num - len;
2739 
2740  grow(newsz);
2741 
2742  if ((idx + len) < d_cplength)
2743  memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2744 
2745  utf32* pt = &ptr()[idx + str_num - 1];
2746 
2747  while (str_num--)
2748  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2749 
2750  setlen(newsz);
2751 
2752  return *this;
2753  }
2754 
2755 
2781  String& replace(size_type idx, size_type len, const utf8* utf8_str)
2782  {
2783  return replace(idx, len, utf8_str, utf_length(utf8_str));
2784  }
2785 
2813  String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
2814  {
2815  return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
2816  }
2817 
2846  String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
2847  {
2848  if (d_cplength < idx)
2849  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2850 
2851  if (str_len == npos)
2852  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
2853 
2854  if (((len + idx) > d_cplength) || (len == npos))
2855  len = d_cplength - idx;
2856 
2857  size_type encsz = encoded_size(utf8_str, str_len);
2858  size_type newsz = d_cplength + encsz - len;
2859 
2860  grow(newsz);
2861 
2862  if ((idx + len) < d_cplength)
2863  memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2864 
2865  encode(utf8_str, &ptr()[idx], encsz, str_len);
2866 
2867  setlen(newsz);
2868  return *this;
2869  }
2870 
2901  String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
2902  {
2903  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
2904  }
2905 
2928  String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
2929  {
2930  if (d_cplength < idx)
2931  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2932 
2933  if (num == npos)
2934  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
2935 
2936  if (((len + idx) > d_cplength) || (len == npos))
2937  len = d_cplength - idx;
2938 
2939  size_type newsz = d_cplength + num - len;
2940 
2941  grow(newsz);
2942 
2943  if ((idx + len) < d_cplength)
2944  memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2945 
2946  utf32* pt = &ptr()[idx + num - 1];
2947 
2948  while (num--)
2949  *pt-- = code_point;
2950 
2951  setlen(newsz);
2952 
2953  return *this;
2954  }
2955 
2980  String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
2981  {
2982  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
2983  }
2984 
2985 
3010  String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
3011  {
3012  if (iter_newBeg == iter_newEnd)
3013  {
3014  erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
3015  }
3016  else
3017  {
3018  size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
3019  size_type idx = safe_iter_dif(iter_beg, begin());
3020  size_type len = safe_iter_dif(iter_end, iter_beg);
3021 
3022  if ((len + idx) > d_cplength)
3023  len = d_cplength - idx;
3024 
3025  size_type newsz = d_cplength + str_len - len;
3026 
3027  grow(newsz);
3028 
3029  if ((idx + len) < d_cplength)
3030  memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
3031 
3032  memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
3033  setlen(newsz);
3034  }
3035 
3036  return *this;
3037  }
3038 
3039 
3059  String& replace(size_type idx, size_type len, const char* cstr)
3060  {
3061  return replace(idx, len, cstr, strlen(cstr));
3062  }
3063 
3064 
3086  String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
3087  {
3088  return replace(iter_beg, iter_end, cstr, strlen(cstr));
3089  }
3090 
3091 
3114  String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
3115  {
3116  if (d_cplength < idx)
3117  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
3118 
3119  if (chars_len == npos)
3120  CEGUI_THROW(std::length_error("Length for the char array can not be 'npos'"));
3121 
3122  if (((len + idx) > d_cplength) || (len == npos))
3123  len = d_cplength - idx;
3124 
3125  size_type newsz = d_cplength + chars_len - len;
3126 
3127  grow(newsz);
3128 
3129  if ((idx + len) < d_cplength)
3130  memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
3131 
3132  utf32* pt = &ptr()[idx + chars_len - 1];
3133 
3134  while (chars_len--)
3135  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
3136 
3137  setlen(newsz);
3138  return *this;
3139  }
3140 
3141 
3166  String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
3167  {
3168  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
3169  }
3170 
3171 
3173  // Find a code point
3175 
3189  size_type find(utf32 code_point, size_type idx = 0) const
3190  {
3191  if (idx < d_cplength)
3192  {
3193  const utf32* pt = &ptr()[idx];
3194 
3195  while (idx < d_cplength)
3196  {
3197  if (*pt++ == code_point)
3198  return idx;
3199 
3200  ++idx;
3201  }
3202 
3203  }
3204 
3205  return npos;
3206  }
3207 
3222  size_type rfind(utf32 code_point, size_type idx = npos) const
3223  {
3224  if (idx >= d_cplength)
3225  idx = d_cplength - 1;
3226 
3227  if (d_cplength > 0)
3228  {
3229  const utf32* pt = &ptr()[idx];
3230 
3231  do
3232  {
3233  if (*pt-- == code_point)
3234  return idx;
3235 
3236  } while (idx-- != 0);
3237 
3238  }
3239 
3240  return npos;
3241  }
3242 
3244  // Find a substring
3246 
3260  size_type find(const String& str, size_type idx = 0) const
3261  {
3262  if ((str.d_cplength == 0) && (idx < d_cplength))
3263  return idx;
3264 
3265  if (idx < d_cplength)
3266  {
3267  // loop while search string could fit in to search area
3268  while (d_cplength - idx >= str.d_cplength)
3269  {
3270  if (0 == compare(idx, str.d_cplength, str))
3271  return idx;
3272 
3273  ++idx;
3274  }
3275 
3276  }
3277 
3278  return npos;
3279  }
3280 
3295  size_type rfind(const String& str, size_type idx = npos) const
3296  {
3297  if (str.d_cplength == 0)
3298  return (idx < d_cplength) ? idx : d_cplength;
3299 
3300  if (str.d_cplength <= d_cplength)
3301  {
3302  if (idx > (d_cplength - str.d_cplength))
3303  idx = d_cplength - str.d_cplength;
3304 
3305  do
3306  {
3307  if (0 == compare(idx, str.d_cplength, str))
3308  return idx;
3309 
3310  } while (idx-- != 0);
3311 
3312  }
3313 
3314  return npos;
3315  }
3316 
3335  size_type find(const std::string& std_str, size_type idx = 0) const
3336  {
3337  std::string::size_type sze = std_str.size();
3338 
3339  if ((sze == 0) && (idx < d_cplength))
3340  return idx;
3341 
3342  if (idx < d_cplength)
3343  {
3344  // loop while search string could fit in to search area
3345  while (d_cplength - idx >= sze)
3346  {
3347  if (0 == compare(idx, (size_type)sze, std_str))
3348  return idx;
3349 
3350  ++idx;
3351  }
3352 
3353  }
3354 
3355  return npos;
3356  }
3357 
3376  size_type rfind(const std::string& std_str, size_type idx = npos) const
3377  {
3378  std::string::size_type sze = std_str.size();
3379 
3380  if (sze == 0)
3381  return (idx < d_cplength) ? idx : d_cplength;
3382 
3383  if (sze <= d_cplength)
3384  {
3385  if (idx > (d_cplength - sze))
3386  idx = d_cplength - sze;
3387 
3388  do
3389  {
3390  if (0 == compare(idx, (size_type)sze, std_str))
3391  return idx;
3392 
3393  } while (idx-- != 0);
3394 
3395  }
3396 
3397  return npos;
3398  }
3399 
3422  size_type find(const utf8* utf8_str, size_type idx = 0) const
3423  {
3424  return find(utf8_str, idx, utf_length(utf8_str));
3425  }
3426 
3449  size_type rfind(const utf8* utf8_str, size_type idx = npos) const
3450  {
3451  return rfind(utf8_str, idx, utf_length(utf8_str));
3452  }
3453 
3479  size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const
3480  {
3481  if (str_len == npos)
3482  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3483 
3484  size_type sze = encoded_size(utf8_str, str_len);
3485 
3486  if ((sze == 0) && (idx < d_cplength))
3487  return idx;
3488 
3489  if (idx < d_cplength)
3490  {
3491  // loop while search string could fit in to search area
3492  while (d_cplength - idx >= sze)
3493  {
3494  if (0 == compare(idx, sze, utf8_str, sze))
3495  return idx;
3496 
3497  ++idx;
3498  }
3499 
3500  }
3501 
3502  return npos;
3503  }
3504 
3530  size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
3531  {
3532  if (str_len == npos)
3533  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3534 
3535  size_type sze = encoded_size(utf8_str, str_len);
3536 
3537  if (sze == 0)
3538  return (idx < d_cplength) ? idx : d_cplength;
3539 
3540  if (sze <= d_cplength)
3541  {
3542  if (idx > (d_cplength - sze))
3543  idx = d_cplength - sze;
3544 
3545  do
3546  {
3547  if (0 == compare(idx, sze, utf8_str, sze))
3548  return idx;
3549 
3550  } while (idx-- != 0);
3551 
3552  }
3553 
3554  return npos;
3555  }
3556 
3557 
3574  size_type find(const char* cstr, size_type idx = 0) const
3575  {
3576  return find(cstr, idx, strlen(cstr));
3577  }
3578 
3579 
3596  size_type rfind(const char* cstr, size_type idx = npos) const
3597  {
3598  return rfind(cstr, idx, strlen(cstr));
3599  }
3600 
3601 
3621  size_type find(const char* chars, size_type idx, size_type chars_len) const
3622  {
3623  if (chars_len == npos)
3624  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
3625 
3626  if ((chars_len == 0) && (idx < d_cplength))
3627  return idx;
3628 
3629  if (idx < d_cplength)
3630  {
3631  // loop while search string could fit in to search area
3632  while (d_cplength - idx >= chars_len)
3633  {
3634  if (0 == compare(idx, chars_len, chars, chars_len))
3635  return idx;
3636 
3637  ++idx;
3638  }
3639 
3640  }
3641 
3642  return npos;
3643  }
3644 
3645 
3665  size_type rfind(const char* chars, size_type idx, size_type chars_len) const
3666  {
3667  if (chars_len == npos)
3668  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
3669 
3670  if (chars_len == 0)
3671  return (idx < d_cplength) ? idx : d_cplength;
3672 
3673  if (chars_len <= d_cplength)
3674  {
3675  if (idx > (d_cplength - chars_len))
3676  idx = d_cplength - chars_len;
3677 
3678  do
3679  {
3680  if (0 == compare(idx, chars_len, chars, chars_len))
3681  return idx;
3682 
3683  } while (idx-- != 0);
3684 
3685  }
3686 
3687  return npos;
3688  }
3689 
3690 
3692  // Find first of different code-points
3694 
3708  size_type find_first_of(const String& str, size_type idx = 0) const
3709  {
3710  if (idx < d_cplength)
3711  {
3712  const utf32* pt = &ptr()[idx];
3713 
3714  do
3715  {
3716  if (npos != str.find(*pt++))
3717  return idx;
3718 
3719  } while (++idx != d_cplength);
3720 
3721  }
3722 
3723  return npos;
3724  }
3725 
3740  size_type find_first_not_of(const String& str, size_type idx = 0) const
3741  {
3742  if (idx < d_cplength)
3743  {
3744  const utf32* pt = &ptr()[idx];
3745 
3746  do
3747  {
3748  if (npos == str.find(*pt++))
3749  return idx;
3750 
3751  } while (++idx != d_cplength);
3752 
3753  }
3754 
3755  return npos;
3756  }
3757 
3758 
3777  size_type find_first_of(const std::string& std_str, size_type idx = 0) const
3778  {
3779  if (idx < d_cplength)
3780  {
3781  const utf32* pt = &ptr()[idx];
3782 
3783  do
3784  {
3785  if (npos != find_codepoint(std_str, *pt++))
3786  return idx;
3787 
3788  } while (++idx != d_cplength);
3789 
3790  }
3791 
3792  return npos;
3793  }
3794 
3813  size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const
3814  {
3815  if (idx < d_cplength)
3816  {
3817  const utf32* pt = &ptr()[idx];
3818 
3819  do
3820  {
3821  if (npos == find_codepoint(std_str, *pt++))
3822  return idx;
3823 
3824  } while (++idx != d_cplength);
3825 
3826  }
3827 
3828  return npos;
3829  }
3830 
3831 
3854  size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const
3855  {
3856  return find_first_of(utf8_str, idx, utf_length(utf8_str));
3857  }
3858 
3881  size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
3882  {
3883  return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
3884  }
3885 
3911  size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3912  {
3913  if (str_len == npos)
3914  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3915 
3916  if (idx < d_cplength)
3917  {
3918  size_type encsze = encoded_size(utf8_str, str_len);
3919 
3920  const utf32* pt = &ptr()[idx];
3921 
3922  do
3923  {
3924  if (npos != find_codepoint(utf8_str, encsze, *pt++))
3925  return idx;
3926 
3927  } while (++idx != d_cplength);
3928 
3929  }
3930 
3931  return npos;
3932  }
3933 
3959  size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3960  {
3961  if (str_len == npos)
3962  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3963 
3964  if (idx < d_cplength)
3965  {
3966  size_type encsze = encoded_size(utf8_str, str_len);
3967 
3968  const utf32* pt = &ptr()[idx];
3969 
3970  do
3971  {
3972  if (npos == find_codepoint(utf8_str, encsze, *pt++))
3973  return idx;
3974 
3975  } while (++idx != d_cplength);
3976 
3977  }
3978 
3979  return npos;
3980  }
3981 
3982 
3997  size_type find_first_of(utf32 code_point, size_type idx = 0) const
3998  {
3999  return find(code_point, idx);
4000  }
4001 
4018  size_type find_first_not_of(utf32 code_point, size_type idx = 0) const
4019  {
4020  if (idx < d_cplength)
4021  {
4022  do
4023  {
4024  if ((*this)[idx] != code_point)
4025  return idx;
4026 
4027  } while(idx++ < d_cplength);
4028 
4029  }
4030 
4031  return npos;
4032  }
4033 
4034 
4051  size_type find_first_of(const char* cstr, size_type idx = 0) const
4052  {
4053  return find_first_of(cstr, idx, strlen(cstr));
4054  }
4055 
4056 
4073  size_type find_first_not_of(const char* cstr, size_type idx = 0) const
4074  {
4075  return find_first_not_of(cstr, idx, strlen(cstr));
4076  }
4077 
4078 
4098  size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const
4099  {
4100  if (chars_len == npos)
4101  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4102 
4103  if (idx < d_cplength)
4104  {
4105  const utf32* pt = &ptr()[idx];
4106 
4107  do
4108  {
4109  if (npos != find_codepoint(chars, chars_len, *pt++))
4110  return idx;
4111 
4112  } while (++idx != d_cplength);
4113 
4114  }
4115 
4116  return npos;
4117  }
4118 
4119 
4139  size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
4140  {
4141  if (chars_len == npos)
4142  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4143 
4144  if (idx < d_cplength)
4145  {
4146  const utf32* pt = &ptr()[idx];
4147 
4148  do
4149  {
4150  if (npos == find_codepoint(chars, chars_len, *pt++))
4151  return idx;
4152 
4153  } while (++idx != d_cplength);
4154 
4155  }
4156 
4157  return npos;
4158  }
4159 
4160 
4162  // Find last of different code-points
4164 
4178  size_type find_last_of(const String& str, size_type idx = npos) const
4179  {
4180  if (d_cplength > 0)
4181  {
4182  if (idx >= d_cplength)
4183  idx = d_cplength - 1;
4184 
4185  const utf32* pt = &ptr()[idx];
4186 
4187  do
4188  {
4189  if (npos != str.find(*pt--))
4190  return idx;
4191 
4192  } while (idx-- != 0);
4193 
4194  }
4195 
4196  return npos;
4197  }
4198 
4213  size_type find_last_not_of(const String& str, size_type idx = npos) const
4214  {
4215  if (d_cplength > 0)
4216  {
4217  if (idx >= d_cplength)
4218  idx = d_cplength - 1;
4219 
4220  const utf32* pt = &ptr()[idx];
4221 
4222  do
4223  {
4224  if (npos == str.find(*pt--))
4225  return idx;
4226 
4227  } while (idx-- != 0);
4228 
4229  }
4230 
4231  return npos;
4232  }
4233 
4234 
4253  size_type find_last_of(const std::string& std_str, size_type idx = npos) const
4254  {
4255  if (d_cplength > 0)
4256  {
4257  if (idx >= d_cplength)
4258  idx = d_cplength - 1;
4259 
4260  const utf32* pt = &ptr()[idx];
4261 
4262  do
4263  {
4264  if (npos != find_codepoint(std_str, *pt--))
4265  return idx;
4266 
4267  } while (idx-- != 0);
4268 
4269  }
4270 
4271  return npos;
4272  }
4273 
4292  size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const
4293  {
4294  if (d_cplength > 0)
4295  {
4296  if (idx >= d_cplength)
4297  idx = d_cplength - 1;
4298 
4299  const utf32* pt = &ptr()[idx];
4300 
4301  do
4302  {
4303  if (npos == find_codepoint(std_str, *pt--))
4304  return idx;
4305 
4306  } while (idx-- != 0);
4307 
4308  }
4309 
4310  return npos;
4311  }
4312 
4313 
4336  size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const
4337  {
4338  return find_last_of(utf8_str, idx, utf_length(utf8_str));
4339  }
4340 
4363  size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
4364  {
4365  return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
4366  }
4367 
4393  size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4394  {
4395  if (str_len == npos)
4396  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
4397 
4398  if (d_cplength > 0)
4399  {
4400  if (idx >= d_cplength)
4401  idx = d_cplength - 1;
4402 
4403  size_type encsze = encoded_size(utf8_str, str_len);
4404 
4405  const utf32* pt = &ptr()[idx];
4406 
4407  do
4408  {
4409  if (npos != find_codepoint(utf8_str, encsze, *pt--))
4410  return idx;
4411 
4412  } while (idx-- != 0);
4413 
4414  }
4415 
4416  return npos;
4417  }
4418 
4444  size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4445  {
4446  if (str_len == npos)
4447  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
4448 
4449  if (d_cplength > 0)
4450  {
4451  if (idx >= d_cplength)
4452  idx = d_cplength - 1;
4453 
4454  size_type encsze = encoded_size(utf8_str, str_len);
4455 
4456  const utf32* pt = &ptr()[idx];
4457 
4458  do
4459  {
4460  if (npos == find_codepoint(utf8_str, encsze, *pt--))
4461  return idx;
4462 
4463  } while (idx-- != 0);
4464 
4465  }
4466 
4467  return npos;
4468  }
4469 
4470 
4485  size_type find_last_of(utf32 code_point, size_type idx = npos) const
4486  {
4487  return rfind(code_point, idx);
4488  }
4489 
4504  size_type find_last_not_of(utf32 code_point, size_type idx = npos) const
4505  {
4506  if (d_cplength > 0)
4507  {
4508  if (idx >= d_cplength)
4509  idx = d_cplength - 1;
4510 
4511  do
4512  {
4513  if ((*this)[idx] != code_point)
4514  return idx;
4515 
4516  } while(idx-- != 0);
4517 
4518  }
4519 
4520  return npos;
4521  }
4522 
4523 
4540  size_type find_last_of(const char* cstr, size_type idx = npos) const
4541  {
4542  return find_last_of(cstr, idx, strlen(cstr));
4543  }
4544 
4545 
4562  size_type find_last_not_of(const char* cstr, size_type idx = npos) const
4563  {
4564  return find_last_not_of(cstr, idx, strlen(cstr));
4565  }
4566 
4567 
4587  size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const
4588  {
4589  if (chars_len == npos)
4590  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4591 
4592  if (d_cplength > 0)
4593  {
4594  if (idx >= d_cplength)
4595  idx = d_cplength - 1;
4596 
4597  const utf32* pt = &ptr()[idx];
4598 
4599  do
4600  {
4601  if (npos != find_codepoint(chars, chars_len, *pt--))
4602  return idx;
4603 
4604  } while (idx-- != 0);
4605 
4606  }
4607 
4608  return npos;
4609  }
4610 
4611 
4631  size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
4632  {
4633  if (chars_len == npos)
4634  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4635 
4636  if (d_cplength > 0)
4637  {
4638  if (idx >= d_cplength)
4639  idx = d_cplength - 1;
4640 
4641  const utf32* pt = &ptr()[idx];
4642 
4643  do
4644  {
4645  if (npos == find_codepoint(chars, chars_len, *pt--))
4646  return idx;
4647 
4648  } while (idx-- != 0);
4649 
4650  }
4651 
4652  return npos;
4653  }
4654 
4655 
4657  // Substring
4659 
4674  String substr(size_type idx = 0, size_type len = npos) const
4675  {
4676  if (d_cplength < idx)
4677  CEGUI_THROW(std::out_of_range("Index is out of range for this CEGUI::String"));
4678 
4679  return String(*this, idx, len);
4680  }
4681 
4683  // Iterator creation
4685 
4692  iterator begin(void)
4693  {
4694  return iterator(ptr());
4695  }
4696 
4704  const_iterator begin(void) const
4705  {
4706  return const_iterator(ptr());
4707  }
4708 
4716  iterator end(void)
4717  {
4718  return iterator(&ptr()[d_cplength]);
4719  }
4720 
4728  const_iterator end(void) const
4729  {
4730  return const_iterator(&ptr()[d_cplength]);
4731  }
4732 
4740  reverse_iterator rbegin(void)
4741  {
4742  return reverse_iterator(end());
4743  }
4744 
4752  const_reverse_iterator rbegin(void) const
4753  {
4754  return const_reverse_iterator(end());
4755  }
4756 
4764  reverse_iterator rend(void)
4765  {
4766  return reverse_iterator(begin());
4767  }
4768 
4776  const_reverse_iterator rend(void) const
4777  {
4778  return const_reverse_iterator(begin());
4779  }
4780 
4781 private:
4782  /*************************************************************************
4783  Implementation Functions
4784  *************************************************************************/
4785  // string management
4786 
4787  // change size of allocated buffer so it is at least 'new_size'.
4788  // May or may not cause re-allocation and copy of buffer if size is larger
4789  // will never re-allocate to make size smaller. (see trim())
4790  bool grow(size_type new_size);
4791 
4792  // perform re-allocation to remove wasted space.
4793  void trim(void);
4794 
4795  // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
4796  void setlen(size_type len)
4797  {
4798  d_cplength = len;
4799  ptr()[len] = (utf32)(0);
4800  }
4801 
4802  // initialise string object
4803  void init(void)
4804  {
4805  d_reserve = STR_QUICKBUFF_SIZE;
4806  d_encodedbuff = 0;
4807  d_encodedbufflen = 0;
4808  d_encodeddatlen = 0;
4809  d_buffer = 0;
4810  setlen(0);
4811  }
4812 
4813  // return true if the given pointer is inside the string data
4814  bool inside(utf32* inptr)
4815  {
4816  if (inptr < ptr() || ptr() + d_cplength <= inptr)
4817  return false;
4818  else
4819  return true;
4820  }
4821 
4822  // compute distance between two iterators, returning a 'safe' value
4823  size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
4824  {
4825  return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
4826  }
4827 
4828  // encoding functions
4829  // for all:
4830  // src_len is in code units, or 0 for null terminated string.
4831  // dest_len is in code units.
4832  // returns number of code units put into dest buffer.
4833  size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
4834  {
4835  // count length for null terminated source...
4836  if (src_len == 0)
4837  {
4838  src_len = utf_length(src);
4839  }
4840 
4841  size_type destCapacity = dest_len;
4842 
4843  // while there is data in the source buffer,
4844  for (uint idx = 0; idx < src_len; ++idx)
4845  {
4846  utf32 cp = src[idx];
4847 
4848  // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
4849  if (destCapacity < encoded_size(cp))
4850  {
4851  break;
4852  }
4853 
4854  if (cp < 0x80)
4855  {
4856  *dest++ = (utf8)cp;
4857  --destCapacity;
4858  }
4859  else if (cp < 0x0800)
4860  {
4861  *dest++ = (utf8)((cp >> 6) | 0xC0);
4862  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4863  destCapacity -= 2;
4864  }
4865  else if (cp < 0x10000)
4866  {
4867  *dest++ = (utf8)((cp >> 12) | 0xE0);
4868  *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4869  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4870  destCapacity -= 3;
4871  }
4872  else
4873  {
4874  *dest++ = (utf8)((cp >> 18) | 0xF0);
4875  *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
4876  *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4877  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4878  destCapacity -= 4;
4879  }
4880 
4881  }
4882 
4883  return dest_len - destCapacity;
4884  }
4885 
4886  size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
4887  {
4888  // count length for null terminated source...
4889  if (src_len == 0)
4890  {
4891  src_len = utf_length(src);
4892  }
4893 
4894  size_type destCapacity = dest_len;
4895 
4896  // while there is data in the source buffer, and space in the dest buffer
4897  for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
4898  {
4899  utf32 cp;
4900  utf8 cu = src[idx++];
4901 
4902  if (cu < 0x80)
4903  {
4904  cp = (utf32)(cu);
4905  }
4906  else if (cu < 0xE0)
4907  {
4908  cp = ((cu & 0x1F) << 6);
4909  cp |= (src[idx++] & 0x3F);
4910  }
4911  else if (cu < 0xF0)
4912  {
4913  cp = ((cu & 0x0F) << 12);
4914  cp |= ((src[idx++] & 0x3F) << 6);
4915  cp |= (src[idx++] & 0x3F);
4916  }
4917  else
4918  {
4919  cp = ((cu & 0x07) << 18);
4920  cp |= ((src[idx++] & 0x3F) << 12);
4921  cp |= ((src[idx++] & 0x3F) << 6);
4922  cp |= (src[idx++] & 0x3F);
4923  }
4924 
4925  *dest++ = cp;
4926  --destCapacity;
4927  }
4928 
4929  return dest_len - destCapacity;
4930  }
4931 
4932  // return the number of utf8 code units required to encode the given utf32 code point
4933  size_type encoded_size(utf32 code_point) const
4934  {
4935  if (code_point < 0x80)
4936  return 1;
4937  else if (code_point < 0x0800)
4938  return 2;
4939  else if (code_point < 0x10000)
4940  return 3;
4941  else
4942  return 4;
4943  }
4944 
4945  // return number of code units required to re-encode given null-terminated utf32 data as utf8. return does not include terminating null.
4946  size_type encoded_size(const utf32* buf) const
4947  {
4948  return encoded_size(buf, utf_length(buf));
4949  }
4950 
4951  // return number of code units required to re-encode given utf32 data as utf8. len is number of code units in 'buf'.
4952  size_type encoded_size(const utf32* buf, size_type len) const
4953  {
4954  size_type count = 0;
4955 
4956  while (len--)
4957  {
4958  count += encoded_size(*buf++);
4959  }
4960 
4961  return count;
4962  }
4963 
4964  // return number of utf32 code units required to re-encode given utf8 data as utf32. return does not include terminating null.
4965  size_type encoded_size(const utf8* buf) const
4966  {
4967  return encoded_size(buf, utf_length(buf));
4968  }
4969 
4970  // return number of utf32 code units required to re-encode given utf8 data as utf32. len is number of code units in 'buf'.
4971  size_type encoded_size(const utf8* buf, size_type len) const
4972  {
4973  utf8 tcp;
4974  size_type count = 0;
4975 
4976  while (len--)
4977  {
4978  tcp = *buf++;
4979  ++count;
4980  size_type size = 0;
4981 
4982  if (tcp < 0x80)
4983  {
4984  }
4985  else if (tcp < 0xE0)
4986  {
4987  size = 1;
4988  ++buf;
4989  }
4990  else if (tcp < 0xF0)
4991  {
4992  size = 2;
4993  buf += 2;
4994  }
4995  else
4996  {
4997  size = 3;
4998  buf += 3;
4999  }
5000 
5001  if (len >= size)
5002  len -= size;
5003  else
5004  break;
5005  }
5006 
5007  return count;
5008  }
5009 
5010  // return number of code units in a null terminated string
5011  size_type utf_length(const utf8* utf8_str) const
5012  {
5013  size_type cnt = 0;
5014  while (*utf8_str++)
5015  cnt++;
5016 
5017  return cnt;
5018  }
5019 
5020  // return number of code units in a null terminated string
5021  size_type utf_length(const utf32* utf32_str) const
5022  {
5023  size_type cnt = 0;
5024  while (*utf32_str++)
5025  cnt++;
5026 
5027  return cnt;
5028  }
5029 
5030  // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
5031  utf8* build_utf8_buff(void) const;
5032 
5033  // compare two utf32 buffers
5034  int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
5035  {
5036  if (!cp_count)
5037  return 0;
5038 
5039  while ((--cp_count) && (*buf1 == *buf2))
5040  buf1++, buf2++;
5041 
5042  return *buf1 - *buf2;
5043  }
5044 
5045  // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
5046  int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
5047  {
5048  if (!cp_count)
5049  return 0;
5050 
5051  while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
5052  buf1++, buf2++;
5053 
5054  return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
5055  }
5056 
5057  // compare utf32 buffer with encoded utf8 data
5058  int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
5059  {
5060  if (!cp_count)
5061  return 0;
5062 
5063  utf32 cp;
5064  utf8 cu;
5065 
5066  do
5067  {
5068  cu = *buf2++;
5069 
5070  if (cu < 0x80)
5071  {
5072  cp = (utf32)(cu);
5073  }
5074  else if (cu < 0xE0)
5075  {
5076  cp = ((cu & 0x1F) << 6);
5077  cp |= (*buf2++ & 0x3F);
5078  }
5079  else if (cu < 0xF0)
5080  {
5081  cp = ((cu & 0x0F) << 12);
5082  cp |= ((*buf2++ & 0x3F) << 6);
5083  cp |= (*buf2++ & 0x3F);
5084  }
5085  else
5086  {
5087  cp = ((cu & 0x07) << 18);
5088  cp |= ((*buf2++ & 0x3F) << 12);
5089  cp |= ((*buf2++ & 0x3F) << 6);
5090  cp |= (*buf2++ & 0x3F);
5091  }
5092 
5093  } while ((*buf1++ == cp) && (--cp_count));
5094 
5095  return (*--buf1) - cp;
5096  }
5097 
5098  // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
5099  size_type find_codepoint(const std::string& str, utf32 code_point) const
5100  {
5101  size_type idx = 0, sze = (size_type)str.size();
5102 
5103  while (idx != sze)
5104  {
5105  if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
5106  return idx;
5107 
5108  ++idx;
5109  }
5110 
5111  return npos;
5112  }
5113 
5114  // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none. len is in code points.
5115  size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
5116  {
5117  size_type idx = 0;
5118 
5119  utf32 cp;
5120  utf8 cu;
5121 
5122  while (idx != len) {
5123  cu = *str++;
5124 
5125  if (cu < 0x80)
5126  {
5127  cp = (utf32)(cu);
5128  }
5129  else if (cu < 0xE0)
5130  {
5131  cp = ((cu & 0x1F) << 6);
5132  cp |= (*str++ & 0x3F);
5133  }
5134  else if (cu < 0xF0)
5135  {
5136  cp = ((cu & 0x0F) << 12);
5137  cp |= ((*str++ & 0x3F) << 6);
5138  cp |= (*str++ & 0x3F);
5139  }
5140  else
5141  {
5142  cp = ((cu & 0x07) << 18);
5143  cp |= ((*str++ & 0x3F) << 12);
5144  cp |= ((*str++ & 0x3F) << 6);
5145  cp |= (*str++ & 0x3F);
5146  }
5147 
5148  if (code_point == cp)
5149  return idx;
5150 
5151  ++idx;
5152  }
5153 
5154  return npos;
5155  }
5156 
5157 
5158  // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
5159  size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
5160  {
5161  for (size_type idx = 0; idx != chars_len; ++idx)
5162  {
5163  if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
5164  return idx;
5165  }
5166 
5167  return npos;
5168  }
5169 
5170 };
5171 
5172 
5174 // Comparison operators
5176 
5180 bool CEGUIEXPORT operator==(const String& str1, const String& str2);
5181 
5186 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str);
5187 
5192 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str);
5193 
5198 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str);
5199 
5204 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str);
5205 
5210 bool CEGUIEXPORT operator!=(const String& str1, const String& str2);
5211 
5216 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str);
5217 
5222 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str);
5223 
5228 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str);
5229 
5234 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str);
5235 
5240 bool CEGUIEXPORT operator<(const String& str1, const String& str2);
5241 
5246 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str);
5247 
5252 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str);
5253 
5258 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str);
5259 
5264 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str);
5265 
5270 bool CEGUIEXPORT operator>(const String& str1, const String& str2);
5271 
5276 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str);
5277 
5282 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str);
5283 
5288 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str);
5289 
5294 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str);
5295 
5300 bool CEGUIEXPORT operator<=(const String& str1, const String& str2);
5301 
5306 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str);
5307 
5312 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str);
5313 
5318 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str);
5319 
5324 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str);
5325 
5330 bool CEGUIEXPORT operator>=(const String& str1, const String& str2);
5331 
5336 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str);
5337 
5342 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str);
5343 
5348 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str);
5349 
5354 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str);
5355 
5360 bool CEGUIEXPORT operator==(const String& str, const char* c_str);
5361 
5366 bool CEGUIEXPORT operator==(const char* c_str, const String& str);
5367 
5372 bool CEGUIEXPORT operator!=(const String& str, const char* c_str);
5373 
5378 bool CEGUIEXPORT operator!=(const char* c_str, const String& str);
5379 
5384 bool CEGUIEXPORT operator<(const String& str, const char* c_str);
5385 
5390 bool CEGUIEXPORT operator<(const char* c_str, const String& str);
5391 
5396 bool CEGUIEXPORT operator>(const String& str, const char* c_str);
5397 
5402 bool CEGUIEXPORT operator>(const char* c_str, const String& str);
5403 
5408 bool CEGUIEXPORT operator<=(const String& str, const char* c_str);
5409 
5414 bool CEGUIEXPORT operator<=(const char* c_str, const String& str);
5415 
5420 bool CEGUIEXPORT operator>=(const String& str, const char* c_str);
5421 
5426 bool CEGUIEXPORT operator>=(const char* c_str, const String& str);
5427 
5429 // Concatenation operator functions
5431 
5446 String CEGUIEXPORT operator+(const String& str1, const String& str2);
5447 
5463 String CEGUIEXPORT operator+(const String& str, const std::string& std_str);
5464 
5480 String CEGUIEXPORT operator+(const std::string& std_str, const String& str);
5481 
5497 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str);
5498 
5514 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str);
5515 
5531 String CEGUIEXPORT operator+(const String& str, utf32 code_point);
5532 
5548 String CEGUIEXPORT operator+(utf32 code_point, const String& str);
5549 
5565 String CEGUIEXPORT operator+(const String& str, const char* c_str);
5566 
5582 String CEGUIEXPORT operator+(const char* c_str, const String& str);
5583 
5584 
5586 // Output (stream) functions
5588 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
5589 
5590 
5592 // Modifying operations
5594 
5607 void CEGUIEXPORT swap(String& str1, String& str2);
5608 
5609 
5610 } // End of CEGUI namespace section
5611 
5612 
5613 #endif // end of guard _CEGUIString_h_