Crazy Eddies GUI System  0.7.7
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 <cstddef>
35 #include <string.h>
36 #include <stdexcept>
37 #include <cstddef>
38 
39 // Start of CEGUI namespace section
40 namespace CEGUI
41 {
42 #define STR_QUICKBUFF_SIZE 32
43  /*************************************************************************
44  Basic Types
45  *************************************************************************/
46  typedef uint8 utf8;
47  //typedef uint16 utf16; // removed typedef to prevent usage, as utf16 is not supported (yet)
48  typedef uint32 utf32;
49 
58 class CEGUIEXPORT String
59 {
60 public:
61  /*************************************************************************
62  Integral Types
63  *************************************************************************/
64  typedef utf32 value_type;
65  typedef size_t size_type;
66  typedef std::ptrdiff_t difference_type;
67  typedef utf32& reference;
68  typedef const utf32& const_reference;
69  typedef utf32* pointer;
70  typedef const utf32* const_pointer;
71 
72  static const size_type npos;
73 
74 private:
75  /*************************************************************************
76  Implementation data
77  *************************************************************************/
78  size_type d_cplength;
79  size_type d_reserve;
80 
81  mutable utf8* d_encodedbuff;
82  mutable size_type d_encodeddatlen;
83  mutable size_type d_encodedbufflen;
84 
85  utf32 d_quickbuff[STR_QUICKBUFF_SIZE];
86  utf32* d_buffer;
87 
88 public:
89  /*************************************************************************
90  Iterator Classes
91  *************************************************************************/
93  class iterator : public std::iterator<std::random_access_iterator_tag, utf32>
94  {
95  public:
96  iterator() : d_ptr(0) {}
97  explicit iterator(utf32* const ptr) : d_ptr(ptr) {}
98 
99  utf32& operator*() const
100  {
101  return *d_ptr;
102  }
103 
104  utf32* operator->() const
105  {
106  return &**this;
107  }
108 
109  String::iterator& operator++()
110  {
111  ++d_ptr;
112  return *this;
113  }
114 
115  String::iterator operator++(int)
116  {
117  String::iterator temp = *this;
118  ++*this;
119  return temp;
120  }
121 
122  String::iterator& operator--()
123  {
124  --d_ptr;
125  return *this;
126  }
127 
128  String::iterator operator--(int)
129  {
130  String::iterator temp = *this;
131  --*this;
132  return temp;
133  }
134 
135  String::iterator& operator+=(difference_type offset)
136  {
137  d_ptr += offset;
138  return *this;
139  }
140 
142  {
143  String::iterator temp = *this;
144  return temp += offset;
145  }
146 
147  String::iterator& operator-=(difference_type offset)
148  {
149  return *this += -offset;
150  }
151 
152  String::iterator operator-(difference_type offset) const
153  {
154  String::iterator temp = *this;
155  return temp -= offset;
156  }
157 
158  utf32& operator[](difference_type offset) const
159  {
160  return *(*this + offset);
161  }
162 
163  friend difference_type operator-(const String::iterator& lhs,
164  const String::iterator& rhs)
165  { return lhs.d_ptr - rhs.d_ptr; }
166 
167  friend String::iterator operator+(difference_type offset, const String::iterator& iter)
168  { return iter + offset; }
169 
170  friend bool operator==(const String::iterator& lhs,
171  const String::iterator& rhs)
172  { return lhs.d_ptr == rhs.d_ptr; }
173 
174  friend bool operator!=(const String::iterator& lhs,
175  const String::iterator& rhs)
176  { return lhs.d_ptr != rhs.d_ptr; }
177 
178  friend bool operator<(const String::iterator& lhs,
179  const String::iterator& rhs)
180  { return lhs.d_ptr < rhs.d_ptr; }
181 
182  friend bool operator>(const String::iterator& lhs,
183  const String::iterator& rhs)
184  { return lhs.d_ptr > rhs.d_ptr; }
185 
186  friend bool operator<=(const String::iterator& lhs,
187  const String::iterator& rhs)
188  { return lhs.d_ptr <= rhs.d_ptr; }
189 
190  friend bool operator>=(const String::iterator& lhs,
191  const String::iterator& rhs)
192  { return lhs.d_ptr >= rhs.d_ptr; }
193 
194  utf32* d_ptr;
195  };
196 
198  class const_iterator : public std::iterator<std::random_access_iterator_tag, const utf32>
199  {
200  public:
201  const_iterator() : d_ptr(0) {}
202  explicit const_iterator(const utf32* const ptr) : d_ptr(ptr) {}
203  const_iterator(const String::iterator& iter) : d_ptr(iter.d_ptr) {}
204 
205  const utf32& operator*() const
206  {
207  return *d_ptr;
208  }
209 
210  const utf32* operator->() const
211  {
212  return &**this;
213  }
214 
215  String::const_iterator& operator++()
216  {
217  ++d_ptr;
218  return *this;
219  }
220 
221  String::const_iterator operator++(int)
222  {
223  String::const_iterator temp = *this;
224  ++*this;
225  return temp;
226  }
227 
228  String::const_iterator& operator--()
229  {
230  --d_ptr;
231  return *this;
232  }
233 
234  String::const_iterator operator--(int)
235  {
236  String::const_iterator temp = *this;
237  --*this;
238  return temp;
239  }
240 
241  String::const_iterator& operator+=(difference_type offset)
242  {
243  d_ptr += offset;
244  return *this;
245  }
246 
248  {
249  String::const_iterator temp = *this;
250  return temp += offset;
251  }
252 
253  String::const_iterator& operator-=(difference_type offset)
254  {
255  return *this += -offset;
256  }
257 
258  String::const_iterator operator-(difference_type offset) const
259  {
260  String::const_iterator temp = *this;
261  return temp -= offset;
262  }
263 
264  const utf32& operator[](difference_type offset) const
265  {
266  return *(*this + offset);
267  }
268 
269  String::const_iterator& operator=(const String::iterator& iter)
270  {
271  d_ptr = iter.d_ptr;
272  return *this;
273  }
274 
276  { return iter + offset; }
277 
278  friend difference_type operator-(const String::const_iterator& lhs,
279  const String::const_iterator& rhs)
280  { return lhs.d_ptr - rhs.d_ptr; }
281 
282  friend bool operator==(const String::const_iterator& lhs,
283  const String::const_iterator& rhs)
284  { return lhs.d_ptr == rhs.d_ptr; }
285 
286  friend bool operator!=(const String::const_iterator& lhs,
287  const String::const_iterator& rhs)
288  { return lhs.d_ptr != rhs.d_ptr; }
289 
290  friend bool operator<(const String::const_iterator& lhs,
291  const String::const_iterator& rhs)
292  { return lhs.d_ptr < rhs.d_ptr; }
293 
294  friend bool operator>(const String::const_iterator& lhs,
295  const String::const_iterator& rhs)
296  { return lhs.d_ptr > rhs.d_ptr; }
297 
298  friend bool operator<=(const String::const_iterator& lhs,
299  const String::const_iterator& rhs)
300  { return lhs.d_ptr <= rhs.d_ptr; }
301 
302  friend bool operator>=(const String::const_iterator& lhs,
303  const String::const_iterator& rhs)
304  { return lhs.d_ptr >= rhs.d_ptr; }
305 
306  const utf32* d_ptr;
307  };
308 
313 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
314  typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator;
315 #else
316  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
317 #endif
318 
323 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
324  typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator;
325 #else
326  typedef std::reverse_iterator<iterator> reverse_iterator;
327 #endif
328 
329 public:
336  {
337  bool operator() (const String& a, const String& b) const
338  {
339  const size_t la = a.length();
340  const size_t lb = b.length();
341  if (la == lb)
342  return (memcmp(a.ptr(), b.ptr(), la*sizeof(utf32)) < 0);
343  return (la < lb);
344  }
345  };
346 
347 public:
349  // Default Construction and Destructor
351 
355  String(void)
356  {
357  init();
358  }
359 
364  ~String(void);
365 
367  // Construction via CEGUI::String
369 
379  String(const String& str)
380  {
381  init();
382  assign(str);
383  }
384 
385 
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 
409  // Construction via std::string
411 
427  String(const std::string& std_str)
428  {
429  init();
430  assign(std_str);
431  }
432 
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 
463  // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
465 
483  String(const utf8* utf8_str)
484  {
485  init();
486  assign(utf8_str);
487  }
488 
515  String(const utf8* utf8_str, size_type chars_len)
516  {
517  init();
518  assign(utf8_str, chars_len);
519  }
520 
522  // Construction via code-point (using a UTF-32 code unit)
524 
539  String(size_type num, utf32 code_point)
540  {
541  init();
542  assign(num, code_point);
543  }
544 
546  // Construction via iterator
548  // Create string with characters in the range [beg, end)
563  {
564  init();
565  append(iter_beg, iter_end);
566  }
567 
568 
570  // Construction via c-string
572 
584  String(const char* cstr)
585  {
586  init();
587  assign(cstr);
588  }
589 
605  String(const char* chars, size_type chars_len)
606  {
607  init();
608  assign(chars, chars_len);
609  }
610 
611 
613  // Size operations
615 
622  size_type size(void) const
623  {
624  return d_cplength;
625  }
626 
634  size_type length(void) const
635  {
636  return d_cplength;
637  }
638 
646  bool empty(void) const
647  {
648  return (d_cplength == 0);
649  }
650 
660  static size_type max_size(void)
661  {
662  return (((size_type)-1) / sizeof(utf32));
663  }
664 
666  // Capacity Operations
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()!)
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.
698  void reserve(size_type num = 0)
699  {
700  if (num == 0)
701  trim();
702  else
703  grow(num);
704  }
705 
707  // Comparisons
709 
724  int compare(const String& str) const
725  {
726  return compare(0, d_cplength, str);
727  }
728 
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  CEGUI_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 
794  int compare(const std::string& std_str) const
795  {
796  return compare(0, d_cplength, std_str);
797  }
798 
799 
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  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
837 
838  if (std_str.size() < str_idx)
839  CEGUI_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 
874  int compare(const utf8* utf8_str) const
875  {
876  return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
877  }
878 
879 
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 
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  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
951 
952  if (str_cplen == npos)
953  CEGUI_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 
979  int compare(const char* cstr) const
980  {
981  return compare(0, d_cplength, cstr, strlen(cstr));
982  }
983 
984 
1008  int compare(size_type idx, size_type len, const char* cstr) const
1009  {
1010  return compare(idx, len, cstr, strlen(cstr));
1011  }
1012 
1013 
1041  int compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
1042  {
1043  if (d_cplength < idx)
1044  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1045 
1046  if (chars_len == npos)
1047  CEGUI_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 
1059  // Character access
1061 
1075  reference operator[](size_type idx)
1076  {
1077  return (ptr()[idx]);
1078  }
1079 
1094  value_type operator[](size_type idx) const
1095  {
1096  return ptr()[idx];
1097  }
1098 
1112  {
1113  if (d_cplength <= idx)
1114  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1115 
1116  return ptr()[idx];
1117  }
1118 
1132  {
1133  if (d_cplength <= idx)
1134  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1135 
1136  return ptr()[idx];
1137  }
1138 
1139 
1141  // C-Strings and arrays
1143 
1156  const char* c_str(void) const
1157  {
1158  return (const char*)build_utf8_buff();
1159  }
1160 
1174  const utf8* data(void) const
1175  {
1176  return build_utf8_buff();
1177  }
1178 
1183  utf32* ptr(void)
1184  {
1185  return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
1186  }
1187 
1192  const utf32* ptr(void) const
1193  {
1194  return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
1195  }
1196 
1197  // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
1198  // return number of utf8 code units placed into the buffer
1219  size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const
1220  {
1221  if (d_cplength < idx)
1222  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1223 
1224  if (len == npos)
1225  len = d_cplength;
1226 
1227  return encode(&ptr()[idx], buf, npos, len);
1228  }
1229 
1231  // UTF8 Encoding length information
1233  // 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.
1249  size_type utf8_stream_len(size_type num = npos, size_type idx = 0) const
1250  {
1251  using namespace std;
1252 
1253  if (d_cplength < idx)
1254  CEGUI_THROW(out_of_range("Index was out of range for CEGUI::String object"));
1255 
1256  size_type maxlen = d_cplength - idx;
1257 
1258  return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
1259  }
1260 
1262  // Assignment Functions
1264 
1274  String& operator=(const String& str)
1275  {
1276  return assign(str);
1277  }
1278 
1297  String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
1298  {
1299  if (str.d_cplength < str_idx)
1300  CEGUI_THROW(std::out_of_range("Index was out of range for CEGUI::String object"));
1301 
1302  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
1303  str_num = str.d_cplength - str_idx;
1304 
1305  grow(str_num);
1306  setlen(str_num);
1307  memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
1308 
1309  return *this;
1310  }
1311 
1328  String& operator=(const std::string& std_str)
1329  {
1330  return assign(std_str);
1331  }
1332 
1356  String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1357  {
1358  if (std_str.size() < str_idx)
1359  CEGUI_THROW(std::out_of_range("Index was out of range for std::string object"));
1360 
1361  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
1362  str_num = (size_type)std_str.size() - str_idx;
1363 
1364  grow(str_num);
1365  setlen(str_num);
1366 
1367  while(str_num--)
1368  {
1369  ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
1370  }
1371 
1372  return *this;
1373  }
1374 
1393  String& operator=(const utf8* utf8_str)
1394  {
1395  return assign(utf8_str, utf_length(utf8_str));
1396  }
1397 
1416  String& assign(const utf8* utf8_str)
1417  {
1418  return assign(utf8_str, utf_length(utf8_str));
1419  }
1420 
1442  String& assign(const utf8* utf8_str, size_type str_num)
1443  {
1444  if (str_num == npos)
1445  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
1446 
1447  size_type enc_sze = encoded_size(utf8_str, str_num);
1448 
1449  grow(enc_sze);
1450  encode(utf8_str, ptr(), d_reserve, str_num);
1451  setlen(enc_sze);
1452  return *this;
1453  }
1454 
1465  String& operator=(utf32 code_point)
1466  {
1467  return assign(1, code_point);
1468  }
1469 
1485  String& assign(size_type num, utf32 code_point)
1486  {
1487  if (num == npos)
1488  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
1489 
1490  grow(num);
1491  setlen(num);
1492  utf32* p = ptr();
1493 
1494  while(num--)
1495  *p++ = code_point;
1496 
1497  return *this;
1498  }
1499 
1500 
1513  String& operator=(const char* cstr)
1514  {
1515  return assign(cstr, strlen(cstr));
1516  }
1517 
1518 
1531  String& assign(const char* cstr)
1532  {
1533  return assign(cstr, strlen(cstr));
1534  }
1535 
1536 
1552  String& assign(const char* chars, size_type chars_len)
1553  {
1554  grow(chars_len);
1555  utf32* pt = ptr();
1556 
1557  for (size_type i = 0; i < chars_len; ++i)
1558  {
1559  *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
1560  }
1561 
1562  setlen(chars_len);
1563  return *this;
1564  }
1565 
1566 
1577  void swap(String& str)
1578  {
1579  size_type temp_len = d_cplength;
1580  d_cplength = str.d_cplength;
1581  str.d_cplength = temp_len;
1582 
1583  size_type temp_res = d_reserve;
1584  d_reserve = str.d_reserve;
1585  str.d_reserve = temp_res;
1586 
1587  utf32* temp_buf = d_buffer;
1588  d_buffer = str.d_buffer;
1589  str.d_buffer = temp_buf;
1590 
1591  // see if we need to swap 'quick buffer' data
1592  if (temp_res <= STR_QUICKBUFF_SIZE)
1593  {
1594  utf32 temp_qbf[STR_QUICKBUFF_SIZE];
1595 
1596  memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
1597  memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
1598  memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
1599  }
1600 
1601  }
1602 
1604  // Appending Functions
1606 
1618  String& operator+=(const String& str)
1619  {
1620  return append(str);
1621  }
1622 
1642  String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
1643  {
1644  if (str.d_cplength < str_idx)
1645  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1646 
1647  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
1648  str_num = str.d_cplength - str_idx;
1649 
1650  grow(d_cplength + str_num);
1651  memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
1652  setlen(d_cplength + str_num);
1653  return *this;
1654  }
1655 
1656 
1673  String& operator+=(const std::string& std_str)
1674  {
1675  return append(std_str);
1676  }
1677 
1701  String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1702  {
1703  if (std_str.size() < str_idx)
1704  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
1705 
1706  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
1707  str_num = (size_type)std_str.size() - str_idx;
1708 
1709  size_type newsze = d_cplength + str_num;
1710 
1711  grow(newsze);
1712  utf32* pt = &ptr()[newsze-1];
1713 
1714  while(str_num--)
1715  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
1716 
1717  setlen(newsze);
1718  return *this;
1719  }
1720 
1721 
1740  String& operator+=(const utf8* utf8_str)
1741  {
1742  return append(utf8_str, utf_length(utf8_str));
1743  }
1744 
1763  String& append(const utf8* utf8_str)
1764  {
1765  return append(utf8_str, utf_length(utf8_str));
1766  }
1767 
1768 
1790  String& append(const utf8* utf8_str, size_type len)
1791  {
1792  if (len == npos)
1793  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
1794 
1795  size_type encsz = encoded_size(utf8_str, len);
1796  size_type newsz = d_cplength + encsz;
1797 
1798  grow(newsz);
1799  encode(utf8_str, &ptr()[d_cplength], encsz, len);
1800  setlen(newsz);
1801 
1802  return *this;
1803  }
1804 
1805 
1818  String& operator+=(utf32 code_point)
1819  {
1820  return append(1, code_point);
1821  }
1822 
1838  String& append(size_type num, utf32 code_point)
1839  {
1840  if (num == npos)
1841  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
1842 
1843  size_type newsz = d_cplength + num;
1844  grow(newsz);
1845 
1846  utf32* p = &ptr()[d_cplength];
1847 
1848  while(num--)
1849  *p++ = code_point;
1850 
1851  setlen(newsz);
1852 
1853  return *this;
1854  }
1855 
1868  void push_back(utf32 code_point)
1869  {
1870  append(1, code_point);
1871  }
1872 
1888  String& append(const_iterator iter_beg, const_iterator iter_end)
1889  {
1890  return replace(end(), end(), iter_beg, iter_end);
1891  }
1892 
1893 
1906  String& operator+=(const char* cstr)
1907  {
1908  return append(cstr, strlen(cstr));
1909  }
1910 
1911 
1924  String& append(const char* cstr)
1925  {
1926  return append(cstr, strlen(cstr));
1927  }
1928 
1929 
1945  String& append(const char* chars, size_type chars_len)
1946  {
1947  if (chars_len == npos)
1948  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
1949 
1950  size_type newsz = d_cplength + chars_len;
1951 
1952  grow(newsz);
1953 
1954  utf32* pt = &ptr()[newsz-1];
1955 
1956  while(chars_len--)
1957  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
1958 
1959  setlen(newsz);
1960 
1961  return *this;
1962  }
1963 
1964 
1966  // Insertion Functions
1968 
1984  String& insert(size_type idx, const String& str)
1985  {
1986  return insert(idx, str, 0, npos);
1987  }
1988 
2011  String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
2012  {
2013  if ((d_cplength < idx) || (str.d_cplength < str_idx))
2014  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2015 
2016  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
2017  str_num = str.d_cplength - str_idx;
2018 
2019  size_type newsz = d_cplength + str_num;
2020  grow(newsz);
2021  memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2022  memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2023  setlen(newsz);
2024 
2025  return *this;
2026  }
2027 
2048  String& insert(size_type idx, const std::string& std_str)
2049  {
2050  return insert(idx, std_str, 0, npos);
2051  }
2052 
2079  String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
2080  {
2081  if (d_cplength < idx)
2082  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2083 
2084  if (std_str.size() < str_idx)
2085  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
2086 
2087  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
2088  str_num = (size_type)std_str.size() - str_idx;
2089 
2090  size_type newsz = d_cplength + str_num;
2091  grow(newsz);
2092 
2093  memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2094 
2095  utf32* pt = &ptr()[idx + str_num - 1];
2096 
2097  while(str_num--)
2098  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2099 
2100  setlen(newsz);
2101 
2102  return *this;
2103  }
2104 
2127  String& insert(size_type idx, const utf8* utf8_str)
2128  {
2129  return insert(idx, utf8_str, utf_length(utf8_str));
2130  }
2131 
2157  String& insert(size_type idx, const utf8* utf8_str, size_type len)
2158  {
2159  if (d_cplength < idx)
2160  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2161 
2162  if (len == npos)
2163  CEGUI_THROW(std::length_error("Length of utf8 encoded string can not be 'npos'"));
2164 
2165  size_type encsz = encoded_size(utf8_str, len);
2166  size_type newsz = d_cplength + encsz;
2167 
2168  grow(newsz);
2169  memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2170  encode(utf8_str, &ptr()[idx], encsz, len);
2171  setlen(newsz);
2172 
2173  return *this;
2174  }
2175 
2195  String& insert(size_type idx, size_type num, utf32 code_point)
2196  {
2197  if (d_cplength < idx)
2198  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2199 
2200  if (num == npos)
2201  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
2202 
2203  size_type newsz = d_cplength + num;
2204  grow(newsz);
2205 
2206  memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2207 
2208  utf32* pt = &ptr()[idx + num - 1];
2209 
2210  while(num--)
2211  *pt-- = code_point;
2212 
2213  setlen(newsz);
2214 
2215  return *this;
2216  }
2217 
2236  void insert(iterator pos, size_type num, utf32 code_point)
2237  {
2238  insert(safe_iter_dif(pos, begin()), num, code_point);
2239  }
2240 
2256  iterator insert(iterator pos, utf32 code_point)
2257  {
2258  insert(pos, 1, code_point);
2259  return pos;
2260  }
2261 
2280  void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
2281  {
2282  replace(iter_pos, iter_pos, iter_beg, iter_end);
2283  }
2284 
2285 
2302  String& insert(size_type idx, const char* cstr)
2303  {
2304  return insert(idx, cstr, strlen(cstr));
2305  }
2306 
2307 
2327  String& insert(size_type idx, const char* chars, size_type chars_len)
2328  {
2329  if (d_cplength < idx)
2330  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2331 
2332  if (chars_len == npos)
2333  CEGUI_THROW(std::length_error("Length of char array can not be 'npos'"));
2334 
2335  size_type newsz = d_cplength + chars_len;
2336 
2337  grow(newsz);
2338  memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2339 
2340  utf32* pt = &ptr()[idx + chars_len - 1];
2341 
2342  while(chars_len--)
2343  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
2344 
2345  setlen(newsz);
2346 
2347  return *this;
2348  }
2349 
2350 
2352  // Erasing characters
2354 
2361  void clear(void)
2362  {
2363  setlen(0);
2364  trim();
2365  }
2366 
2374  String& erase(void)
2375  {
2376  clear();
2377  return *this;
2378  }
2379 
2392  String& erase(size_type idx)
2393  {
2394  return erase(idx, 1);
2395  }
2396 
2412  String& erase(size_type idx, size_type len)
2413  {
2414  // cover the no-op case.
2415  if (len == 0)
2416  return *this;
2417 
2418  if (d_cplength <= idx)
2419  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2420 
2421  if (len == npos)
2422  len = d_cplength - idx;
2423 
2424  size_type newsz = d_cplength - len;
2425 
2426  memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
2427  setlen(newsz);
2428  return *this;
2429  }
2430 
2441  String& erase(iterator pos)
2442  {
2443  return erase(safe_iter_dif(pos, begin()), 1);
2444  }
2445 
2459  String& erase(iterator iter_beg, iterator iter_end)
2460  {
2461  return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
2462  }
2463 
2465  // Resizing
2467 
2479  void resize(size_type num)
2480  {
2481  resize(num, utf32());
2482  }
2483 
2499  void resize(size_type num, utf32 code_point)
2500  {
2501  if (num < d_cplength)
2502  {
2503  setlen(num);
2504  }
2505  else
2506  {
2507  append(num - d_cplength, code_point);
2508  }
2509 
2510  }
2511 
2513  // Replacing Characters
2515 
2534  String& replace(size_type idx, size_type len, const String& str)
2535  {
2536  return replace(idx, len, str, 0, npos);
2537  }
2538 
2560  String& replace(iterator iter_beg, iterator iter_end, const String& str)
2561  {
2562  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
2563  }
2564 
2590  String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
2591  {
2592  if ((d_cplength < idx) || (str.d_cplength < str_idx))
2593  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2594 
2595  if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
2596  str_num = str.d_cplength - str_idx;
2597 
2598  if (((len + idx) > d_cplength) || (len == npos))
2599  len = d_cplength - idx;
2600 
2601  size_type newsz = d_cplength + str_num - len;
2602 
2603  grow(newsz);
2604 
2605  if ((idx + len) < d_cplength)
2606  memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2607 
2608  memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2609  setlen(newsz);
2610 
2611  return *this;
2612  }
2613 
2614 
2638  String& replace(size_type idx, size_type len, const std::string& std_str)
2639  {
2640  return replace(idx, len, std_str, 0, npos);
2641  }
2642 
2668  String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
2669  {
2670  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
2671  }
2672 
2702  String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
2703  {
2704  if (d_cplength < idx)
2705  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2706 
2707  if (std_str.size() < str_idx)
2708  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
2709 
2710  if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
2711  str_num = (size_type)std_str.size() - str_idx;
2712 
2713  if (((len + idx) > d_cplength) || (len == npos))
2714  len = d_cplength - idx;
2715 
2716  size_type newsz = d_cplength + str_num - len;
2717 
2718  grow(newsz);
2719 
2720  if ((idx + len) < d_cplength)
2721  memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2722 
2723  utf32* pt = &ptr()[idx + str_num - 1];
2724 
2725  while (str_num--)
2726  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2727 
2728  setlen(newsz);
2729 
2730  return *this;
2731  }
2732 
2733 
2759  String& replace(size_type idx, size_type len, const utf8* utf8_str)
2760  {
2761  return replace(idx, len, utf8_str, utf_length(utf8_str));
2762  }
2763 
2791  String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
2792  {
2793  return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
2794  }
2795 
2824  String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
2825  {
2826  if (d_cplength < idx)
2827  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2828 
2829  if (str_len == npos)
2830  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
2831 
2832  if (((len + idx) > d_cplength) || (len == npos))
2833  len = d_cplength - idx;
2834 
2835  size_type encsz = encoded_size(utf8_str, str_len);
2836  size_type newsz = d_cplength + encsz - len;
2837 
2838  grow(newsz);
2839 
2840  if ((idx + len) < d_cplength)
2841  memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2842 
2843  encode(utf8_str, &ptr()[idx], encsz, str_len);
2844 
2845  setlen(newsz);
2846  return *this;
2847  }
2848 
2879  String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
2880  {
2881  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
2882  }
2883 
2906  String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
2907  {
2908  if (d_cplength < idx)
2909  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2910 
2911  if (num == npos)
2912  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
2913 
2914  if (((len + idx) > d_cplength) || (len == npos))
2915  len = d_cplength - idx;
2916 
2917  size_type newsz = d_cplength + num - len;
2918 
2919  grow(newsz);
2920 
2921  if ((idx + len) < d_cplength)
2922  memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2923 
2924  utf32* pt = &ptr()[idx + num - 1];
2925 
2926  while (num--)
2927  *pt-- = code_point;
2928 
2929  setlen(newsz);
2930 
2931  return *this;
2932  }
2933 
2958  String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
2959  {
2960  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
2961  }
2962 
2963 
2988  String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
2989  {
2990  if (iter_newBeg == iter_newEnd)
2991  {
2992  erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
2993  }
2994  else
2995  {
2996  size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
2997  size_type idx = safe_iter_dif(iter_beg, begin());
2998  size_type len = safe_iter_dif(iter_end, iter_beg);
2999 
3000  if ((len + idx) > d_cplength)
3001  len = d_cplength - idx;
3002 
3003  size_type newsz = d_cplength + str_len - len;
3004 
3005  grow(newsz);
3006 
3007  if ((idx + len) < d_cplength)
3008  memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
3009 
3010  memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
3011  setlen(newsz);
3012  }
3013 
3014  return *this;
3015  }
3016 
3017 
3037  String& replace(size_type idx, size_type len, const char* cstr)
3038  {
3039  return replace(idx, len, cstr, strlen(cstr));
3040  }
3041 
3042 
3064  String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
3065  {
3066  return replace(iter_beg, iter_end, cstr, strlen(cstr));
3067  }
3068 
3069 
3092  String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
3093  {
3094  if (d_cplength < idx)
3095  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
3096 
3097  if (chars_len == npos)
3098  CEGUI_THROW(std::length_error("Length for the char array can not be 'npos'"));
3099 
3100  if (((len + idx) > d_cplength) || (len == npos))
3101  len = d_cplength - idx;
3102 
3103  size_type newsz = d_cplength + chars_len - len;
3104 
3105  grow(newsz);
3106 
3107  if ((idx + len) < d_cplength)
3108  memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
3109 
3110  utf32* pt = &ptr()[idx + chars_len - 1];
3111 
3112  while (chars_len--)
3113  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
3114 
3115  setlen(newsz);
3116  return *this;
3117  }
3118 
3119 
3144  String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
3145  {
3146  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
3147  }
3148 
3149 
3151  // Find a code point
3153 
3167  size_type find(utf32 code_point, size_type idx = 0) const
3168  {
3169  if (idx < d_cplength)
3170  {
3171  const utf32* pt = &ptr()[idx];
3172 
3173  while (idx < d_cplength)
3174  {
3175  if (*pt++ == code_point)
3176  return idx;
3177 
3178  ++idx;
3179  }
3180 
3181  }
3182 
3183  return npos;
3184  }
3185 
3200  size_type rfind(utf32 code_point, size_type idx = npos) const
3201  {
3202  if (idx >= d_cplength)
3203  idx = d_cplength - 1;
3204 
3205  if (d_cplength > 0)
3206  {
3207  const utf32* pt = &ptr()[idx];
3208 
3209  do
3210  {
3211  if (*pt-- == code_point)
3212  return idx;
3213 
3214  } while (idx-- != 0);
3215 
3216  }
3217 
3218  return npos;
3219  }
3220 
3222  // Find a substring
3224 
3238  size_type find(const String& str, size_type idx = 0) const
3239  {
3240  if ((str.d_cplength == 0) && (idx < d_cplength))
3241  return idx;
3242 
3243  if (idx < d_cplength)
3244  {
3245  // loop while search string could fit in to search area
3246  while (d_cplength - idx >= str.d_cplength)
3247  {
3248  if (0 == compare(idx, str.d_cplength, str))
3249  return idx;
3250 
3251  ++idx;
3252  }
3253 
3254  }
3255 
3256  return npos;
3257  }
3258 
3273  size_type rfind(const String& str, size_type idx = npos) const
3274  {
3275  if (str.d_cplength == 0)
3276  return (idx < d_cplength) ? idx : d_cplength;
3277 
3278  if (str.d_cplength <= d_cplength)
3279  {
3280  if (idx > (d_cplength - str.d_cplength))
3281  idx = d_cplength - str.d_cplength;
3282 
3283  do
3284  {
3285  if (0 == compare(idx, str.d_cplength, str))
3286  return idx;
3287 
3288  } while (idx-- != 0);
3289 
3290  }
3291 
3292  return npos;
3293  }
3294 
3313  size_type find(const std::string& std_str, size_type idx = 0) const
3314  {
3315  std::string::size_type sze = std_str.size();
3316 
3317  if ((sze == 0) && (idx < d_cplength))
3318  return idx;
3319 
3320  if (idx < d_cplength)
3321  {
3322  // loop while search string could fit in to search area
3323  while (d_cplength - idx >= sze)
3324  {
3325  if (0 == compare(idx, (size_type)sze, std_str))
3326  return idx;
3327 
3328  ++idx;
3329  }
3330 
3331  }
3332 
3333  return npos;
3334  }
3335 
3354  size_type rfind(const std::string& std_str, size_type idx = npos) const
3355  {
3356  std::string::size_type sze = std_str.size();
3357 
3358  if (sze == 0)
3359  return (idx < d_cplength) ? idx : d_cplength;
3360 
3361  if (sze <= d_cplength)
3362  {
3363  if (idx > (d_cplength - sze))
3364  idx = d_cplength - sze;
3365 
3366  do
3367  {
3368  if (0 == compare(idx, (size_type)sze, std_str))
3369  return idx;
3370 
3371  } while (idx-- != 0);
3372 
3373  }
3374 
3375  return npos;
3376  }
3377 
3400  size_type find(const utf8* utf8_str, size_type idx = 0) const
3401  {
3402  return find(utf8_str, idx, utf_length(utf8_str));
3403  }
3404 
3427  size_type rfind(const utf8* utf8_str, size_type idx = npos) const
3428  {
3429  return rfind(utf8_str, idx, utf_length(utf8_str));
3430  }
3431 
3457  size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const
3458  {
3459  if (str_len == npos)
3460  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3461 
3462  size_type sze = encoded_size(utf8_str, str_len);
3463 
3464  if ((sze == 0) && (idx < d_cplength))
3465  return idx;
3466 
3467  if (idx < d_cplength)
3468  {
3469  // loop while search string could fit in to search area
3470  while (d_cplength - idx >= sze)
3471  {
3472  if (0 == compare(idx, sze, utf8_str, sze))
3473  return idx;
3474 
3475  ++idx;
3476  }
3477 
3478  }
3479 
3480  return npos;
3481  }
3482 
3508  size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
3509  {
3510  if (str_len == npos)
3511  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3512 
3513  size_type sze = encoded_size(utf8_str, str_len);
3514 
3515  if (sze == 0)
3516  return (idx < d_cplength) ? idx : d_cplength;
3517 
3518  if (sze <= d_cplength)
3519  {
3520  if (idx > (d_cplength - sze))
3521  idx = d_cplength - sze;
3522 
3523  do
3524  {
3525  if (0 == compare(idx, sze, utf8_str, sze))
3526  return idx;
3527 
3528  } while (idx-- != 0);
3529 
3530  }
3531 
3532  return npos;
3533  }
3534 
3535 
3552  size_type find(const char* cstr, size_type idx = 0) const
3553  {
3554  return find(cstr, idx, strlen(cstr));
3555  }
3556 
3557 
3574  size_type rfind(const char* cstr, size_type idx = npos) const
3575  {
3576  return rfind(cstr, idx, strlen(cstr));
3577  }
3578 
3579 
3599  size_type find(const char* chars, size_type idx, size_type chars_len) const
3600  {
3601  if (chars_len == npos)
3602  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
3603 
3604  if ((chars_len == 0) && (idx < d_cplength))
3605  return idx;
3606 
3607  if (idx < d_cplength)
3608  {
3609  // loop while search string could fit in to search area
3610  while (d_cplength - idx >= chars_len)
3611  {
3612  if (0 == compare(idx, chars_len, chars, chars_len))
3613  return idx;
3614 
3615  ++idx;
3616  }
3617 
3618  }
3619 
3620  return npos;
3621  }
3622 
3623 
3643  size_type rfind(const char* chars, size_type idx, size_type chars_len) const
3644  {
3645  if (chars_len == npos)
3646  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
3647 
3648  if (chars_len == 0)
3649  return (idx < d_cplength) ? idx : d_cplength;
3650 
3651  if (chars_len <= d_cplength)
3652  {
3653  if (idx > (d_cplength - chars_len))
3654  idx = d_cplength - chars_len;
3655 
3656  do
3657  {
3658  if (0 == compare(idx, chars_len, chars, chars_len))
3659  return idx;
3660 
3661  } while (idx-- != 0);
3662 
3663  }
3664 
3665  return npos;
3666  }
3667 
3668 
3670  // Find first of different code-points
3672 
3686  size_type find_first_of(const String& str, size_type idx = 0) const
3687  {
3688  if (idx < d_cplength)
3689  {
3690  const utf32* pt = &ptr()[idx];
3691 
3692  do
3693  {
3694  if (npos != str.find(*pt++))
3695  return idx;
3696 
3697  } while (++idx != d_cplength);
3698 
3699  }
3700 
3701  return npos;
3702  }
3703 
3718  size_type find_first_not_of(const String& str, size_type idx = 0) const
3719  {
3720  if (idx < d_cplength)
3721  {
3722  const utf32* pt = &ptr()[idx];
3723 
3724  do
3725  {
3726  if (npos == str.find(*pt++))
3727  return idx;
3728 
3729  } while (++idx != d_cplength);
3730 
3731  }
3732 
3733  return npos;
3734  }
3735 
3736 
3755  size_type find_first_of(const std::string& std_str, size_type idx = 0) const
3756  {
3757  if (idx < d_cplength)
3758  {
3759  const utf32* pt = &ptr()[idx];
3760 
3761  do
3762  {
3763  if (npos != find_codepoint(std_str, *pt++))
3764  return idx;
3765 
3766  } while (++idx != d_cplength);
3767 
3768  }
3769 
3770  return npos;
3771  }
3772 
3791  size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const
3792  {
3793  if (idx < d_cplength)
3794  {
3795  const utf32* pt = &ptr()[idx];
3796 
3797  do
3798  {
3799  if (npos == find_codepoint(std_str, *pt++))
3800  return idx;
3801 
3802  } while (++idx != d_cplength);
3803 
3804  }
3805 
3806  return npos;
3807  }
3808 
3809 
3832  size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const
3833  {
3834  return find_first_of(utf8_str, idx, utf_length(utf8_str));
3835  }
3836 
3859  size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
3860  {
3861  return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
3862  }
3863 
3889  size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3890  {
3891  if (str_len == npos)
3892  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3893 
3894  if (idx < d_cplength)
3895  {
3896  size_type encsze = encoded_size(utf8_str, str_len);
3897 
3898  const utf32* pt = &ptr()[idx];
3899 
3900  do
3901  {
3902  if (npos != find_codepoint(utf8_str, encsze, *pt++))
3903  return idx;
3904 
3905  } while (++idx != d_cplength);
3906 
3907  }
3908 
3909  return npos;
3910  }
3911 
3937  size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3938  {
3939  if (str_len == npos)
3940  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3941 
3942  if (idx < d_cplength)
3943  {
3944  size_type encsze = encoded_size(utf8_str, str_len);
3945 
3946  const utf32* pt = &ptr()[idx];
3947 
3948  do
3949  {
3950  if (npos == find_codepoint(utf8_str, encsze, *pt++))
3951  return idx;
3952 
3953  } while (++idx != d_cplength);
3954 
3955  }
3956 
3957  return npos;
3958  }
3959 
3960 
3975  size_type find_first_of(utf32 code_point, size_type idx = 0) const
3976  {
3977  return find(code_point, idx);
3978  }
3979 
3996  size_type find_first_not_of(utf32 code_point, size_type idx = 0) const
3997  {
3998  if (idx < d_cplength)
3999  {
4000  do
4001  {
4002  if ((*this)[idx] != code_point)
4003  return idx;
4004 
4005  } while(idx++ < d_cplength);
4006 
4007  }
4008 
4009  return npos;
4010  }
4011 
4012 
4029  size_type find_first_of(const char* cstr, size_type idx = 0) const
4030  {
4031  return find_first_of(cstr, idx, strlen(cstr));
4032  }
4033 
4034 
4051  size_type find_first_not_of(const char* cstr, size_type idx = 0) const
4052  {
4053  return find_first_not_of(cstr, idx, strlen(cstr));
4054  }
4055 
4056 
4076  size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const
4077  {
4078  if (chars_len == npos)
4079  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4080 
4081  if (idx < d_cplength)
4082  {
4083  const utf32* pt = &ptr()[idx];
4084 
4085  do
4086  {
4087  if (npos != find_codepoint(chars, chars_len, *pt++))
4088  return idx;
4089 
4090  } while (++idx != d_cplength);
4091 
4092  }
4093 
4094  return npos;
4095  }
4096 
4097 
4117  size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
4118  {
4119  if (chars_len == npos)
4120  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4121 
4122  if (idx < d_cplength)
4123  {
4124  const utf32* pt = &ptr()[idx];
4125 
4126  do
4127  {
4128  if (npos == find_codepoint(chars, chars_len, *pt++))
4129  return idx;
4130 
4131  } while (++idx != d_cplength);
4132 
4133  }
4134 
4135  return npos;
4136  }
4137 
4138 
4140  // Find last of different code-points
4142 
4156  size_type find_last_of(const String& str, size_type idx = npos) const
4157  {
4158  if (d_cplength > 0)
4159  {
4160  if (idx >= d_cplength)
4161  idx = d_cplength - 1;
4162 
4163  const utf32* pt = &ptr()[idx];
4164 
4165  do
4166  {
4167  if (npos != str.find(*pt--))
4168  return idx;
4169 
4170  } while (idx-- != 0);
4171 
4172  }
4173 
4174  return npos;
4175  }
4176 
4191  size_type find_last_not_of(const String& str, size_type idx = npos) const
4192  {
4193  if (d_cplength > 0)
4194  {
4195  if (idx >= d_cplength)
4196  idx = d_cplength - 1;
4197 
4198  const utf32* pt = &ptr()[idx];
4199 
4200  do
4201  {
4202  if (npos == str.find(*pt--))
4203  return idx;
4204 
4205  } while (idx-- != 0);
4206 
4207  }
4208 
4209  return npos;
4210  }
4211 
4212 
4231  size_type find_last_of(const std::string& std_str, size_type idx = npos) const
4232  {
4233  if (d_cplength > 0)
4234  {
4235  if (idx >= d_cplength)
4236  idx = d_cplength - 1;
4237 
4238  const utf32* pt = &ptr()[idx];
4239 
4240  do
4241  {
4242  if (npos != find_codepoint(std_str, *pt--))
4243  return idx;
4244 
4245  } while (idx-- != 0);
4246 
4247  }
4248 
4249  return npos;
4250  }
4251 
4270  size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const
4271  {
4272  if (d_cplength > 0)
4273  {
4274  if (idx >= d_cplength)
4275  idx = d_cplength - 1;
4276 
4277  const utf32* pt = &ptr()[idx];
4278 
4279  do
4280  {
4281  if (npos == find_codepoint(std_str, *pt--))
4282  return idx;
4283 
4284  } while (idx-- != 0);
4285 
4286  }
4287 
4288  return npos;
4289  }
4290 
4291 
4314  size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const
4315  {
4316  return find_last_of(utf8_str, idx, utf_length(utf8_str));
4317  }
4318 
4341  size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
4342  {
4343  return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
4344  }
4345 
4371  size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4372  {
4373  if (str_len == npos)
4374  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
4375 
4376  if (d_cplength > 0)
4377  {
4378  if (idx >= d_cplength)
4379  idx = d_cplength - 1;
4380 
4381  size_type encsze = encoded_size(utf8_str, str_len);
4382 
4383  const utf32* pt = &ptr()[idx];
4384 
4385  do
4386  {
4387  if (npos != find_codepoint(utf8_str, encsze, *pt--))
4388  return idx;
4389 
4390  } while (idx-- != 0);
4391 
4392  }
4393 
4394  return npos;
4395  }
4396 
4422  size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4423  {
4424  if (str_len == npos)
4425  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
4426 
4427  if (d_cplength > 0)
4428  {
4429  if (idx >= d_cplength)
4430  idx = d_cplength - 1;
4431 
4432  size_type encsze = encoded_size(utf8_str, str_len);
4433 
4434  const utf32* pt = &ptr()[idx];
4435 
4436  do
4437  {
4438  if (npos == find_codepoint(utf8_str, encsze, *pt--))
4439  return idx;
4440 
4441  } while (idx-- != 0);
4442 
4443  }
4444 
4445  return npos;
4446  }
4447 
4448 
4463  size_type find_last_of(utf32 code_point, size_type idx = npos) const
4464  {
4465  return rfind(code_point, idx);
4466  }
4467 
4482  size_type find_last_not_of(utf32 code_point, size_type idx = npos) const
4483  {
4484  if (d_cplength > 0)
4485  {
4486  if (idx >= d_cplength)
4487  idx = d_cplength - 1;
4488 
4489  do
4490  {
4491  if ((*this)[idx] != code_point)
4492  return idx;
4493 
4494  } while(idx-- != 0);
4495 
4496  }
4497 
4498  return npos;
4499  }
4500 
4501 
4518  size_type find_last_of(const char* cstr, size_type idx = npos) const
4519  {
4520  return find_last_of(cstr, idx, strlen(cstr));
4521  }
4522 
4523 
4540  size_type find_last_not_of(const char* cstr, size_type idx = npos) const
4541  {
4542  return find_last_not_of(cstr, idx, strlen(cstr));
4543  }
4544 
4545 
4565  size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const
4566  {
4567  if (chars_len == npos)
4568  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4569 
4570  if (d_cplength > 0)
4571  {
4572  if (idx >= d_cplength)
4573  idx = d_cplength - 1;
4574 
4575  const utf32* pt = &ptr()[idx];
4576 
4577  do
4578  {
4579  if (npos != find_codepoint(chars, chars_len, *pt--))
4580  return idx;
4581 
4582  } while (idx-- != 0);
4583 
4584  }
4585 
4586  return npos;
4587  }
4588 
4589 
4609  size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
4610  {
4611  if (chars_len == npos)
4612  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4613 
4614  if (d_cplength > 0)
4615  {
4616  if (idx >= d_cplength)
4617  idx = d_cplength - 1;
4618 
4619  const utf32* pt = &ptr()[idx];
4620 
4621  do
4622  {
4623  if (npos == find_codepoint(chars, chars_len, *pt--))
4624  return idx;
4625 
4626  } while (idx-- != 0);
4627 
4628  }
4629 
4630  return npos;
4631  }
4632 
4633 
4635  // Substring
4637 
4652  String substr(size_type idx = 0, size_type len = npos) const
4653  {
4654  if (d_cplength < idx)
4655  CEGUI_THROW(std::out_of_range("Index is out of range for this CEGUI::String"));
4656 
4657  return String(*this, idx, len);
4658  }
4659 
4661  // Iterator creation
4663 
4670  iterator begin(void)
4671  {
4672  return iterator(ptr());
4673  }
4674 
4682  const_iterator begin(void) const
4683  {
4684  return const_iterator(ptr());
4685  }
4686 
4694  iterator end(void)
4695  {
4696  return iterator(&ptr()[d_cplength]);
4697  }
4698 
4706  const_iterator end(void) const
4707  {
4708  return const_iterator(&ptr()[d_cplength]);
4709  }
4710 
4718  reverse_iterator rbegin(void)
4719  {
4720  return reverse_iterator(end());
4721  }
4722 
4730  const_reverse_iterator rbegin(void) const
4731  {
4732  return const_reverse_iterator(end());
4733  }
4734 
4742  reverse_iterator rend(void)
4743  {
4744  return reverse_iterator(begin());
4745  }
4746 
4754  const_reverse_iterator rend(void) const
4755  {
4756  return const_reverse_iterator(begin());
4757  }
4758 
4759 private:
4760  /*************************************************************************
4761  Implementation Functions
4762  *************************************************************************/
4763  // string management
4764 
4765  // change size of allocated buffer so it is at least 'new_size'.
4766  // May or may not cause re-allocation and copy of buffer if size is larger
4767  // will never re-allocate to make size smaller. (see trim())
4768  bool grow(size_type new_size);
4769 
4770  // perform re-allocation to remove wasted space.
4771  void trim(void);
4772 
4773  // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
4774  void setlen(size_type len)
4775  {
4776  d_cplength = len;
4777  ptr()[len] = (utf32)(0);
4778  }
4779 
4780  // initialise string object
4781  void init(void)
4782  {
4783  d_reserve = STR_QUICKBUFF_SIZE;
4784  d_encodedbuff = 0;
4785  d_encodedbufflen = 0;
4786  d_encodeddatlen = 0;
4787  d_buffer = 0;
4788  setlen(0);
4789  }
4790 
4791  // return true if the given pointer is inside the string data
4792  bool inside(utf32* inptr)
4793  {
4794  if (inptr < ptr() || ptr() + d_cplength <= inptr)
4795  return false;
4796  else
4797  return true;
4798  }
4799 
4800  // compute distance between two iterators, returning a 'safe' value
4801  size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
4802  {
4803  return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
4804  }
4805 
4806  // encoding functions
4807  // for all:
4808  // src_len is in code units, or 0 for null terminated string.
4809  // dest_len is in code units.
4810  // returns number of code units put into dest buffer.
4811  size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
4812  {
4813  // count length for null terminated source...
4814  if (src_len == 0)
4815  {
4816  src_len = utf_length(src);
4817  }
4818 
4819  size_type destCapacity = dest_len;
4820 
4821  // while there is data in the source buffer,
4822  for (uint idx = 0; idx < src_len; ++idx)
4823  {
4824  utf32 cp = src[idx];
4825 
4826  // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
4827  if (destCapacity < encoded_size(cp))
4828  {
4829  break;
4830  }
4831 
4832  if (cp < 0x80)
4833  {
4834  *dest++ = (utf8)cp;
4835  --destCapacity;
4836  }
4837  else if (cp < 0x0800)
4838  {
4839  *dest++ = (utf8)((cp >> 6) | 0xC0);
4840  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4841  destCapacity -= 2;
4842  }
4843  else if (cp < 0x10000)
4844  {
4845  *dest++ = (utf8)((cp >> 12) | 0xE0);
4846  *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4847  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4848  destCapacity -= 3;
4849  }
4850  else
4851  {
4852  *dest++ = (utf8)((cp >> 18) | 0xF0);
4853  *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
4854  *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4855  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4856  destCapacity -= 4;
4857  }
4858 
4859  }
4860 
4861  return dest_len - destCapacity;
4862  }
4863 
4864  size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
4865  {
4866  // count length for null terminated source...
4867  if (src_len == 0)
4868  {
4869  src_len = utf_length(src);
4870  }
4871 
4872  size_type destCapacity = dest_len;
4873 
4874  // while there is data in the source buffer, and space in the dest buffer
4875  for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
4876  {
4877  utf32 cp;
4878  utf8 cu = src[idx++];
4879 
4880  if (cu < 0x80)
4881  {
4882  cp = (utf32)(cu);
4883  }
4884  else if (cu < 0xE0)
4885  {
4886  cp = ((cu & 0x1F) << 6);
4887  cp |= (src[idx++] & 0x3F);
4888  }
4889  else if (cu < 0xF0)
4890  {
4891  cp = ((cu & 0x0F) << 12);
4892  cp |= ((src[idx++] & 0x3F) << 6);
4893  cp |= (src[idx++] & 0x3F);
4894  }
4895  else
4896  {
4897  cp = ((cu & 0x07) << 18);
4898  cp |= ((src[idx++] & 0x3F) << 12);
4899  cp |= ((src[idx++] & 0x3F) << 6);
4900  cp |= (src[idx++] & 0x3F);
4901  }
4902 
4903  *dest++ = cp;
4904  --destCapacity;
4905  }
4906 
4907  return dest_len - destCapacity;
4908  }
4909 
4910  // return the number of utf8 code units required to encode the given utf32 code point
4911  size_type encoded_size(utf32 code_point) const
4912  {
4913  if (code_point < 0x80)
4914  return 1;
4915  else if (code_point < 0x0800)
4916  return 2;
4917  else if (code_point < 0x10000)
4918  return 3;
4919  else
4920  return 4;
4921  }
4922 
4923  // return number of code units required to re-encode given null-terminated utf32 data as utf8. return does not include terminating null.
4924  size_type encoded_size(const utf32* buf) const
4925  {
4926  return encoded_size(buf, utf_length(buf));
4927  }
4928 
4929  // return number of code units required to re-encode given utf32 data as utf8. len is number of code units in 'buf'.
4930  size_type encoded_size(const utf32* buf, size_type len) const
4931  {
4932  size_type count = 0;
4933 
4934  while (len--)
4935  {
4936  count += encoded_size(*buf++);
4937  }
4938 
4939  return count;
4940  }
4941 
4942  // return number of utf32 code units required to re-encode given utf8 data as utf32. return does not include terminating null.
4943  size_type encoded_size(const utf8* buf) const
4944  {
4945  return encoded_size(buf, utf_length(buf));
4946  }
4947 
4948  // return number of utf32 code units required to re-encode given utf8 data as utf32. len is number of code units in 'buf'.
4949  size_type encoded_size(const utf8* buf, size_type len) const
4950  {
4951  utf8 tcp;
4952  size_type count = 0;
4953 
4954  while (len--)
4955  {
4956  tcp = *buf++;
4957  ++count;
4958  size_type size = 0;
4959 
4960  if (tcp < 0x80)
4961  {
4962  }
4963  else if (tcp < 0xE0)
4964  {
4965  size = 1;
4966  ++buf;
4967  }
4968  else if (tcp < 0xF0)
4969  {
4970  size = 2;
4971  buf += 2;
4972  }
4973  else
4974  {
4975  size = 3;
4976  buf += 3;
4977  }
4978 
4979  if (len >= size)
4980  len -= size;
4981  else
4982  break;
4983  }
4984 
4985  return count;
4986  }
4987 
4988  // return number of code units in a null terminated string
4989  size_type utf_length(const utf8* utf8_str) const
4990  {
4991  size_type cnt = 0;
4992  while (*utf8_str++)
4993  cnt++;
4994 
4995  return cnt;
4996  }
4997 
4998  // return number of code units in a null terminated string
4999  size_type utf_length(const utf32* utf32_str) const
5000  {
5001  size_type cnt = 0;
5002  while (*utf32_str++)
5003  cnt++;
5004 
5005  return cnt;
5006  }
5007 
5008  // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
5009  utf8* build_utf8_buff(void) const;
5010 
5011  // compare two utf32 buffers
5012  int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
5013  {
5014  if (!cp_count)
5015  return 0;
5016 
5017  while ((--cp_count) && (*buf1 == *buf2))
5018  buf1++, buf2++;
5019 
5020  return *buf1 - *buf2;
5021  }
5022 
5023  // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
5024  int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
5025  {
5026  if (!cp_count)
5027  return 0;
5028 
5029  while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
5030  buf1++, buf2++;
5031 
5032  return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
5033  }
5034 
5035  // compare utf32 buffer with encoded utf8 data
5036  int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
5037  {
5038  if (!cp_count)
5039  return 0;
5040 
5041  utf32 cp;
5042  utf8 cu;
5043 
5044  do
5045  {
5046  cu = *buf2++;
5047 
5048  if (cu < 0x80)
5049  {
5050  cp = (utf32)(cu);
5051  }
5052  else if (cu < 0xE0)
5053  {
5054  cp = ((cu & 0x1F) << 6);
5055  cp |= (*buf2++ & 0x3F);
5056  }
5057  else if (cu < 0xF0)
5058  {
5059  cp = ((cu & 0x0F) << 12);
5060  cp |= ((*buf2++ & 0x3F) << 6);
5061  cp |= (*buf2++ & 0x3F);
5062  }
5063  else
5064  {
5065  cp = ((cu & 0x07) << 18);
5066  cp |= ((*buf2++ & 0x3F) << 12);
5067  cp |= ((*buf2++ & 0x3F) << 6);
5068  cp |= (*buf2++ & 0x3F);
5069  }
5070 
5071  } while ((*buf1++ == cp) && (--cp_count));
5072 
5073  return (*--buf1) - cp;
5074  }
5075 
5076  // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
5077  size_type find_codepoint(const std::string& str, utf32 code_point) const
5078  {
5079  size_type idx = 0, sze = (size_type)str.size();
5080 
5081  while (idx != sze)
5082  {
5083  if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
5084  return idx;
5085 
5086  ++idx;
5087  }
5088 
5089  return npos;
5090  }
5091 
5092  // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none. len is in code points.
5093  size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
5094  {
5095  size_type idx = 0;
5096 
5097  utf32 cp;
5098  utf8 cu;
5099 
5100  while (idx != len) {
5101  cu = *str++;
5102 
5103  if (cu < 0x80)
5104  {
5105  cp = (utf32)(cu);
5106  }
5107  else if (cu < 0xE0)
5108  {
5109  cp = ((cu & 0x1F) << 6);
5110  cp |= (*str++ & 0x3F);
5111  }
5112  else if (cu < 0xF0)
5113  {
5114  cp = ((cu & 0x0F) << 12);
5115  cp |= ((*str++ & 0x3F) << 6);
5116  cp |= (*str++ & 0x3F);
5117  }
5118  else
5119  {
5120  cp = ((cu & 0x07) << 18);
5121  cp |= ((*str++ & 0x3F) << 12);
5122  cp |= ((*str++ & 0x3F) << 6);
5123  cp |= (*str++ & 0x3F);
5124  }
5125 
5126  if (code_point == cp)
5127  return idx;
5128 
5129  ++idx;
5130  }
5131 
5132  return npos;
5133  }
5134 
5135 
5136  // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
5137  size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
5138  {
5139  for (size_type idx = 0; idx != chars_len; ++idx)
5140  {
5141  if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
5142  return idx;
5143  }
5144 
5145  return npos;
5146  }
5147 
5148 };
5149 
5150 
5152 // Comparison operators
5154 
5158 bool CEGUIEXPORT operator==(const String& str1, const String& str2);
5159 
5164 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str);
5165 
5170 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str);
5171 
5176 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str);
5177 
5182 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str);
5183 
5188 bool CEGUIEXPORT operator!=(const String& str1, const String& str2);
5189 
5194 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str);
5195 
5200 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str);
5201 
5206 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str);
5207 
5212 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str);
5213 
5218 bool CEGUIEXPORT operator<(const String& str1, const String& str2);
5219 
5224 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str);
5225 
5230 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str);
5231 
5236 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str);
5237 
5242 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str);
5243 
5248 bool CEGUIEXPORT operator>(const String& str1, const String& str2);
5249 
5254 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str);
5255 
5260 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str);
5261 
5266 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str);
5267 
5272 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str);
5273 
5278 bool CEGUIEXPORT operator<=(const String& str1, const String& str2);
5279 
5284 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str);
5285 
5290 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str);
5291 
5296 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str);
5297 
5302 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str);
5303 
5308 bool CEGUIEXPORT operator>=(const String& str1, const String& str2);
5309 
5314 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str);
5315 
5320 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str);
5321 
5326 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str);
5327 
5332 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str);
5333 
5338 bool CEGUIEXPORT operator==(const String& str, const char* c_str);
5339 
5344 bool CEGUIEXPORT operator==(const char* c_str, const String& str);
5345 
5350 bool CEGUIEXPORT operator!=(const String& str, const char* c_str);
5351 
5356 bool CEGUIEXPORT operator!=(const char* c_str, const String& str);
5357 
5362 bool CEGUIEXPORT operator<(const String& str, const char* c_str);
5363 
5368 bool CEGUIEXPORT operator<(const char* c_str, const String& str);
5369 
5374 bool CEGUIEXPORT operator>(const String& str, const char* c_str);
5375 
5380 bool CEGUIEXPORT operator>(const char* c_str, const String& str);
5381 
5386 bool CEGUIEXPORT operator<=(const String& str, const char* c_str);
5387 
5392 bool CEGUIEXPORT operator<=(const char* c_str, const String& str);
5393 
5398 bool CEGUIEXPORT operator>=(const String& str, const char* c_str);
5399 
5404 bool CEGUIEXPORT operator>=(const char* c_str, const String& str);
5405 
5407 // Concatenation operator functions
5409 
5424 String CEGUIEXPORT operator+(const String& str1, const String& str2);
5425 
5441 String CEGUIEXPORT operator+(const String& str, const std::string& std_str);
5442 
5458 String CEGUIEXPORT operator+(const std::string& std_str, const String& str);
5459 
5475 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str);
5476 
5492 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str);
5493 
5509 String CEGUIEXPORT operator+(const String& str, utf32 code_point);
5510 
5526 String CEGUIEXPORT operator+(utf32 code_point, const String& str);
5527 
5543 String CEGUIEXPORT operator+(const String& str, const char* c_str);
5544 
5560 String CEGUIEXPORT operator+(const char* c_str, const String& str);
5561 
5562 
5564 // Output (stream) functions
5566 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
5567 
5568 
5570 // Modifying operations
5572 
5585 void CEGUIEXPORT swap(String& str1, String& str2);
5586 
5587 
5588 } // End of CEGUI namespace section
5589 
5590 
5591 #endif // end of guard _CEGUIString_h_