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 <string.h>
35 #include <stdexcept>
36 #include <cstddef>
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 std::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  *************************************************************************/
92  class iterator : public std::iterator<std::random_access_iterator_tag, utf32>
93  {
94  public:
95  iterator() : d_ptr(0) {}
96  explicit iterator(utf32* const ptr) : d_ptr(ptr) {}
97 
98  utf32& operator*() const
99  {
100  return *d_ptr;
101  }
102 
103  utf32* operator->() const
104  {
105  return &**this;
106  }
107 
108  String::iterator& operator++()
109  {
110  ++d_ptr;
111  return *this;
112  }
113 
114  String::iterator operator++(int)
115  {
116  String::iterator temp = *this;
117  ++*this;
118  return temp;
119  }
120 
121  String::iterator& operator--()
122  {
123  --d_ptr;
124  return *this;
125  }
126 
127  String::iterator operator--(int)
128  {
129  String::iterator temp = *this;
130  --*this;
131  return temp;
132  }
133 
134  String::iterator& operator+=(difference_type offset)
135  {
136  d_ptr += offset;
137  return *this;
138  }
139 
141  {
142  String::iterator temp = *this;
143  return temp += offset;
144  }
145 
146  String::iterator& operator-=(difference_type offset)
147  {
148  return *this += -offset;
149  }
150 
151  String::iterator operator-(difference_type offset) const
152  {
153  String::iterator temp = *this;
154  return temp -= offset;
155  }
156 
157  utf32& operator[](difference_type offset) const
158  {
159  return *(*this + offset);
160  }
161 
162  friend difference_type operator-(const String::iterator& lhs,
163  const String::iterator& rhs)
164  { return lhs.d_ptr - rhs.d_ptr; }
165 
166  friend String::iterator operator+(difference_type offset, const String::iterator& iter)
167  { return iter + offset; }
168 
169  friend bool operator==(const String::iterator& lhs,
170  const String::iterator& rhs)
171  { return lhs.d_ptr == rhs.d_ptr; }
172 
173  friend bool operator!=(const String::iterator& lhs,
174  const String::iterator& rhs)
175  { return lhs.d_ptr != rhs.d_ptr; }
176 
177  friend bool operator<(const String::iterator& lhs,
178  const String::iterator& rhs)
179  { return lhs.d_ptr < rhs.d_ptr; }
180 
181  friend bool operator>(const String::iterator& lhs,
182  const String::iterator& rhs)
183  { return lhs.d_ptr > rhs.d_ptr; }
184 
185  friend bool operator<=(const String::iterator& lhs,
186  const String::iterator& rhs)
187  { return lhs.d_ptr <= rhs.d_ptr; }
188 
189  friend bool operator>=(const String::iterator& lhs,
190  const String::iterator& rhs)
191  { return lhs.d_ptr >= rhs.d_ptr; }
192 
193  utf32* d_ptr;
194  };
195 
197  class const_iterator : public std::iterator<std::random_access_iterator_tag, const utf32>
198  {
199  public:
200  const_iterator() : d_ptr(0) {}
201  explicit const_iterator(const utf32* const ptr) : d_ptr(ptr) {}
202  const_iterator(const String::iterator& iter) : d_ptr(iter.d_ptr) {}
203 
204  const utf32& operator*() const
205  {
206  return *d_ptr;
207  }
208 
209  const utf32* operator->() const
210  {
211  return &**this;
212  }
213 
214  String::const_iterator& operator++()
215  {
216  ++d_ptr;
217  return *this;
218  }
219 
220  String::const_iterator operator++(int)
221  {
222  String::const_iterator temp = *this;
223  ++*this;
224  return temp;
225  }
226 
227  String::const_iterator& operator--()
228  {
229  --d_ptr;
230  return *this;
231  }
232 
233  String::const_iterator operator--(int)
234  {
235  String::const_iterator temp = *this;
236  --*this;
237  return temp;
238  }
239 
240  String::const_iterator& operator+=(difference_type offset)
241  {
242  d_ptr += offset;
243  return *this;
244  }
245 
247  {
248  String::const_iterator temp = *this;
249  return temp += offset;
250  }
251 
252  String::const_iterator& operator-=(difference_type offset)
253  {
254  return *this += -offset;
255  }
256 
257  String::const_iterator operator-(difference_type offset) const
258  {
259  String::const_iterator temp = *this;
260  return temp -= offset;
261  }
262 
263  const utf32& operator[](difference_type offset) const
264  {
265  return *(*this + offset);
266  }
267 
268  String::const_iterator& operator=(const String::iterator& iter)
269  {
270  d_ptr = iter.d_ptr;
271  return *this;
272  }
273 
275  { return iter + offset; }
276 
277  friend difference_type operator-(const String::const_iterator& lhs,
278  const String::const_iterator& rhs)
279  { return lhs.d_ptr - rhs.d_ptr; }
280 
281  friend bool operator==(const String::const_iterator& lhs,
282  const String::const_iterator& rhs)
283  { return lhs.d_ptr == rhs.d_ptr; }
284 
285  friend bool operator!=(const String::const_iterator& lhs,
286  const String::const_iterator& rhs)
287  { return lhs.d_ptr != rhs.d_ptr; }
288 
289  friend bool operator<(const String::const_iterator& lhs,
290  const String::const_iterator& rhs)
291  { return lhs.d_ptr < rhs.d_ptr; }
292 
293  friend bool operator>(const String::const_iterator& lhs,
294  const String::const_iterator& rhs)
295  { return lhs.d_ptr > rhs.d_ptr; }
296 
297  friend bool operator<=(const String::const_iterator& lhs,
298  const String::const_iterator& rhs)
299  { return lhs.d_ptr <= rhs.d_ptr; }
300 
301  friend bool operator>=(const String::const_iterator& lhs,
302  const String::const_iterator& rhs)
303  { return lhs.d_ptr >= rhs.d_ptr; }
304 
305  const utf32* d_ptr;
306  };
307 
312 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
313  typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator;
314 #else
315  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
316 #endif
317 
322 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
323  typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator;
324 #else
325  typedef std::reverse_iterator<iterator> reverse_iterator;
326 #endif
327 
328 public:
335  {
336  bool operator() (const String& a, const String& b) const
337  {
338  const size_t la = a.length();
339  const size_t lb = b.length();
340  if (la == lb)
341  return (memcmp(a.ptr(), b.ptr(), la*sizeof(utf32)) < 0);
342  return (la < lb);
343  }
344  };
345 
346 public:
348  // Default Construction and Destructor
350 
354  String(void)
355  {
356  init();
357  }
358 
363  ~String(void);
364 
366  // Construction via CEGUI::String
368 
378  String(const String& str)
379  {
380  init();
381  assign(str);
382  }
383 
384 
401  String(const String& str, size_type str_idx, size_type str_num = npos)
402  {
403  init();
404  assign(str, str_idx, str_num);
405  }
406 
408  // Construction via std::string
410 
426  String(const std::string& std_str)
427  {
428  init();
429  assign(std_str);
430  }
431 
454  String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
455  {
456  init();
457  assign(std_str, str_idx, str_num);
458  }
459 
460 
462  // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
464 
482  String(const utf8* utf8_str)
483  {
484  init();
485  assign(utf8_str);
486  }
487 
514  String(const utf8* utf8_str, size_type chars_len)
515  {
516  init();
517  assign(utf8_str, chars_len);
518  }
519 
521  // Construction via code-point (using a UTF-32 code unit)
523 
538  String(size_type num, utf32 code_point)
539  {
540  init();
541  assign(num, code_point);
542  }
543 
545  // Construction via iterator
547  // Create string with characters in the range [beg, end)
562  {
563  init();
564  append(iter_beg, iter_end);
565  }
566 
567 
569  // Construction via c-string
571 
583  String(const char* cstr)
584  {
585  init();
586  assign(cstr);
587  }
588 
604  String(const char* chars, size_type chars_len)
605  {
606  init();
607  assign(chars, chars_len);
608  }
609 
610 
612  // Size operations
614 
621  size_type size(void) const
622  {
623  return d_cplength;
624  }
625 
633  size_type length(void) const
634  {
635  return d_cplength;
636  }
637 
645  bool empty(void) const
646  {
647  return (d_cplength == 0);
648  }
649 
659  static size_type max_size(void)
660  {
661  return (((size_type)-1) / sizeof(utf32));
662  }
663 
665  // Capacity Operations
667  // return the number of code points the string could hold without re-allocation
668  // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
677  size_type capacity(void) const
678  {
679  return d_reserve - 1;
680  }
681 
682  // reserve internal memory for at-least 'num' code-points (characters). if num is 0, request is shrink-to-fit.
697  void reserve(size_type num = 0)
698  {
699  if (num == 0)
700  trim();
701  else
702  grow(num);
703  }
704 
706  // Comparisons
708 
723  int compare(const String& str) const
724  {
725  return compare(0, d_cplength, str);
726  }
727 
757  int compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
758  {
759  if ((d_cplength < idx) || (str.d_cplength < str_idx))
760  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
761 
762  if ((len == npos) || (idx + len > d_cplength))
763  len = d_cplength - idx;
764 
765  if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
766  str_len = str.d_cplength - str_idx;
767 
768  int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
769 
770  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
771  }
772 
773 
793  int compare(const std::string& std_str) const
794  {
795  return compare(0, d_cplength, std_str);
796  }
797 
798 
832  int compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
833  {
834  if (d_cplength < idx)
835  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
836 
837  if (std_str.size() < str_idx)
838  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
839 
840  if ((len == npos) || (idx + len > d_cplength))
841  len = d_cplength - idx;
842 
843  if ((str_len == npos) || (str_idx + str_len > std_str.size()))
844  str_len = (size_type)std_str.size() - str_idx;
845 
846  int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
847 
848  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
849  }
850 
851 
873  int compare(const utf8* utf8_str) const
874  {
875  return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
876  }
877 
878 
908  int compare(size_type idx, size_type len, const utf8* utf8_str) const
909  {
910  return compare(idx, len, utf8_str, encoded_size(utf8_str));
911  }
912 
946  int compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
947  {
948  if (d_cplength < idx)
949  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
950 
951  if (str_cplen == npos)
952  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
953 
954  if ((len == npos) || (idx + len > d_cplength))
955  len = d_cplength - idx;
956 
957  int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
958 
959  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
960  }
961 
962 
978  int compare(const char* cstr) const
979  {
980  return compare(0, d_cplength, cstr, strlen(cstr));
981  }
982 
983 
1007  int compare(size_type idx, size_type len, const char* cstr) const
1008  {
1009  return compare(idx, len, cstr, strlen(cstr));
1010  }
1011 
1012 
1040  int compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
1041  {
1042  if (d_cplength < idx)
1043  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1044 
1045  if (chars_len == npos)
1046  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
1047 
1048  if ((len == npos) || (idx + len > d_cplength))
1049  len = d_cplength - idx;
1050 
1051  int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
1052 
1053  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
1054  }
1055 
1056 
1058  // Character access
1060 
1074  reference operator[](size_type idx)
1075  {
1076  return (ptr()[idx]);
1077  }
1078 
1093  value_type operator[](size_type idx) const
1094  {
1095  return ptr()[idx];
1096  }
1097 
1111  {
1112  if (d_cplength <= idx)
1113  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1114 
1115  return ptr()[idx];
1116  }
1117 
1131  {
1132  if (d_cplength <= idx)
1133  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1134 
1135  return ptr()[idx];
1136  }
1137 
1138 
1140  // C-Strings and arrays
1142 
1155  const char* c_str(void) const
1156  {
1157  return (const char*)build_utf8_buff();
1158  }
1159 
1173  const utf8* data(void) const
1174  {
1175  return build_utf8_buff();
1176  }
1177 
1182  utf32* ptr(void)
1183  {
1184  return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
1185  }
1186 
1191  const utf32* ptr(void) const
1192  {
1193  return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
1194  }
1195 
1196  // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
1197  // return number of utf8 code units placed into the buffer
1218  size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const
1219  {
1220  if (d_cplength < idx)
1221  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1222 
1223  if (len == npos)
1224  len = d_cplength;
1225 
1226  return encode(&ptr()[idx], buf, npos, len);
1227  }
1228 
1230  // UTF8 Encoding length information
1232  // 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.
1248  size_type utf8_stream_len(size_type num = npos, size_type idx = 0) const
1249  {
1250  using namespace std;
1251 
1252  if (d_cplength < idx)
1253  CEGUI_THROW(out_of_range("Index was out of range for CEGUI::String object"));
1254 
1255  size_type maxlen = d_cplength - idx;
1256 
1257  return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
1258  }
1259 
1261  // Assignment Functions
1263 
1273  String& operator=(const String& str)
1274  {
1275  return assign(str);
1276  }
1277 
1296  String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
1297  {
1298  if (str.d_cplength < str_idx)
1299  CEGUI_THROW(std::out_of_range("Index was out of range for CEGUI::String object"));
1300 
1301  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
1302  str_num = str.d_cplength - str_idx;
1303 
1304  grow(str_num);
1305  setlen(str_num);
1306  memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
1307 
1308  return *this;
1309  }
1310 
1327  String& operator=(const std::string& std_str)
1328  {
1329  return assign(std_str);
1330  }
1331 
1355  String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1356  {
1357  if (std_str.size() < str_idx)
1358  CEGUI_THROW(std::out_of_range("Index was out of range for std::string object"));
1359 
1360  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
1361  str_num = (size_type)std_str.size() - str_idx;
1362 
1363  grow(str_num);
1364  setlen(str_num);
1365 
1366  while(str_num--)
1367  {
1368  ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
1369  }
1370 
1371  return *this;
1372  }
1373 
1392  String& operator=(const utf8* utf8_str)
1393  {
1394  return assign(utf8_str, utf_length(utf8_str));
1395  }
1396 
1415  String& assign(const utf8* utf8_str)
1416  {
1417  return assign(utf8_str, utf_length(utf8_str));
1418  }
1419 
1441  String& assign(const utf8* utf8_str, size_type str_num)
1442  {
1443  if (str_num == npos)
1444  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
1445 
1446  size_type enc_sze = encoded_size(utf8_str, str_num);
1447 
1448  grow(enc_sze);
1449  encode(utf8_str, ptr(), d_reserve, str_num);
1450  setlen(enc_sze);
1451  return *this;
1452  }
1453 
1464  String& operator=(utf32 code_point)
1465  {
1466  return assign(1, code_point);
1467  }
1468 
1484  String& assign(size_type num, utf32 code_point)
1485  {
1486  if (num == npos)
1487  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
1488 
1489  grow(num);
1490  setlen(num);
1491  utf32* p = ptr();
1492 
1493  while(num--)
1494  *p++ = code_point;
1495 
1496  return *this;
1497  }
1498 
1499 
1512  String& operator=(const char* cstr)
1513  {
1514  return assign(cstr, strlen(cstr));
1515  }
1516 
1517 
1530  String& assign(const char* cstr)
1531  {
1532  return assign(cstr, strlen(cstr));
1533  }
1534 
1535 
1551  String& assign(const char* chars, size_type chars_len)
1552  {
1553  grow(chars_len);
1554  utf32* pt = ptr();
1555 
1556  for (size_type i = 0; i < chars_len; ++i)
1557  {
1558  *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
1559  }
1560 
1561  setlen(chars_len);
1562  return *this;
1563  }
1564 
1565 
1576  void swap(String& str)
1577  {
1578  size_type temp_len = d_cplength;
1579  d_cplength = str.d_cplength;
1580  str.d_cplength = temp_len;
1581 
1582  size_type temp_res = d_reserve;
1583  d_reserve = str.d_reserve;
1584  str.d_reserve = temp_res;
1585 
1586  utf32* temp_buf = d_buffer;
1587  d_buffer = str.d_buffer;
1588  str.d_buffer = temp_buf;
1589 
1590  // see if we need to swap 'quick buffer' data
1591  if (temp_res <= STR_QUICKBUFF_SIZE)
1592  {
1593  utf32 temp_qbf[STR_QUICKBUFF_SIZE];
1594 
1595  memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
1596  memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
1597  memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
1598  }
1599 
1600  }
1601 
1603  // Appending Functions
1605 
1617  String& operator+=(const String& str)
1618  {
1619  return append(str);
1620  }
1621 
1641  String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
1642  {
1643  if (str.d_cplength < str_idx)
1644  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1645 
1646  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
1647  str_num = str.d_cplength - str_idx;
1648 
1649  grow(d_cplength + str_num);
1650  memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
1651  setlen(d_cplength + str_num);
1652  return *this;
1653  }
1654 
1655 
1672  String& operator+=(const std::string& std_str)
1673  {
1674  return append(std_str);
1675  }
1676 
1700  String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1701  {
1702  if (std_str.size() < str_idx)
1703  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
1704 
1705  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
1706  str_num = (size_type)std_str.size() - str_idx;
1707 
1708  size_type newsze = d_cplength + str_num;
1709 
1710  grow(newsze);
1711  utf32* pt = &ptr()[newsze-1];
1712 
1713  while(str_num--)
1714  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
1715 
1716  setlen(newsze);
1717  return *this;
1718  }
1719 
1720 
1739  String& operator+=(const utf8* utf8_str)
1740  {
1741  return append(utf8_str, utf_length(utf8_str));
1742  }
1743 
1762  String& append(const utf8* utf8_str)
1763  {
1764  return append(utf8_str, utf_length(utf8_str));
1765  }
1766 
1767 
1789  String& append(const utf8* utf8_str, size_type len)
1790  {
1791  if (len == npos)
1792  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
1793 
1794  size_type encsz = encoded_size(utf8_str, len);
1795  size_type newsz = d_cplength + encsz;
1796 
1797  grow(newsz);
1798  encode(utf8_str, &ptr()[d_cplength], encsz, len);
1799  setlen(newsz);
1800 
1801  return *this;
1802  }
1803 
1804 
1817  String& operator+=(utf32 code_point)
1818  {
1819  return append(1, code_point);
1820  }
1821 
1837  String& append(size_type num, utf32 code_point)
1838  {
1839  if (num == npos)
1840  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
1841 
1842  size_type newsz = d_cplength + num;
1843  grow(newsz);
1844 
1845  utf32* p = &ptr()[d_cplength];
1846 
1847  while(num--)
1848  *p++ = code_point;
1849 
1850  setlen(newsz);
1851 
1852  return *this;
1853  }
1854 
1867  void push_back(utf32 code_point)
1868  {
1869  append(1, code_point);
1870  }
1871 
1887  String& append(const_iterator iter_beg, const_iterator iter_end)
1888  {
1889  return replace(end(), end(), iter_beg, iter_end);
1890  }
1891 
1892 
1905  String& operator+=(const char* cstr)
1906  {
1907  return append(cstr, strlen(cstr));
1908  }
1909 
1910 
1923  String& append(const char* cstr)
1924  {
1925  return append(cstr, strlen(cstr));
1926  }
1927 
1928 
1944  String& append(const char* chars, size_type chars_len)
1945  {
1946  if (chars_len == npos)
1947  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
1948 
1949  size_type newsz = d_cplength + chars_len;
1950 
1951  grow(newsz);
1952 
1953  utf32* pt = &ptr()[newsz-1];
1954 
1955  while(chars_len--)
1956  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
1957 
1958  setlen(newsz);
1959 
1960  return *this;
1961  }
1962 
1963 
1965  // Insertion Functions
1967 
1983  String& insert(size_type idx, const String& str)
1984  {
1985  return insert(idx, str, 0, npos);
1986  }
1987 
2010  String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
2011  {
2012  if ((d_cplength < idx) || (str.d_cplength < str_idx))
2013  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2014 
2015  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
2016  str_num = str.d_cplength - str_idx;
2017 
2018  size_type newsz = d_cplength + str_num;
2019  grow(newsz);
2020  memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2021  memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2022  setlen(newsz);
2023 
2024  return *this;
2025  }
2026 
2047  String& insert(size_type idx, const std::string& std_str)
2048  {
2049  return insert(idx, std_str, 0, npos);
2050  }
2051 
2078  String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
2079  {
2080  if (d_cplength < idx)
2081  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2082 
2083  if (std_str.size() < str_idx)
2084  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
2085 
2086  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
2087  str_num = (size_type)std_str.size() - str_idx;
2088 
2089  size_type newsz = d_cplength + str_num;
2090  grow(newsz);
2091 
2092  memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2093 
2094  utf32* pt = &ptr()[idx + str_num - 1];
2095 
2096  while(str_num--)
2097  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2098 
2099  setlen(newsz);
2100 
2101  return *this;
2102  }
2103 
2126  String& insert(size_type idx, const utf8* utf8_str)
2127  {
2128  return insert(idx, utf8_str, utf_length(utf8_str));
2129  }
2130 
2156  String& insert(size_type idx, const utf8* utf8_str, size_type len)
2157  {
2158  if (d_cplength < idx)
2159  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2160 
2161  if (len == npos)
2162  CEGUI_THROW(std::length_error("Length of utf8 encoded string can not be 'npos'"));
2163 
2164  size_type encsz = encoded_size(utf8_str, len);
2165  size_type newsz = d_cplength + encsz;
2166 
2167  grow(newsz);
2168  memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2169  encode(utf8_str, &ptr()[idx], encsz, len);
2170  setlen(newsz);
2171 
2172  return *this;
2173  }
2174 
2194  String& insert(size_type idx, size_type num, utf32 code_point)
2195  {
2196  if (d_cplength < idx)
2197  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2198 
2199  if (num == npos)
2200  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
2201 
2202  size_type newsz = d_cplength + num;
2203  grow(newsz);
2204 
2205  memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2206 
2207  utf32* pt = &ptr()[idx + num - 1];
2208 
2209  while(num--)
2210  *pt-- = code_point;
2211 
2212  setlen(newsz);
2213 
2214  return *this;
2215  }
2216 
2235  void insert(iterator pos, size_type num, utf32 code_point)
2236  {
2237  insert(safe_iter_dif(pos, begin()), num, code_point);
2238  }
2239 
2255  iterator insert(iterator pos, utf32 code_point)
2256  {
2257  insert(pos, 1, code_point);
2258  return pos;
2259  }
2260 
2279  void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
2280  {
2281  replace(iter_pos, iter_pos, iter_beg, iter_end);
2282  }
2283 
2284 
2301  String& insert(size_type idx, const char* cstr)
2302  {
2303  return insert(idx, cstr, strlen(cstr));
2304  }
2305 
2306 
2326  String& insert(size_type idx, const char* chars, size_type chars_len)
2327  {
2328  if (d_cplength < idx)
2329  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2330 
2331  if (chars_len == npos)
2332  CEGUI_THROW(std::length_error("Length of char array can not be 'npos'"));
2333 
2334  size_type newsz = d_cplength + chars_len;
2335 
2336  grow(newsz);
2337  memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2338 
2339  utf32* pt = &ptr()[idx + chars_len - 1];
2340 
2341  while(chars_len--)
2342  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
2343 
2344  setlen(newsz);
2345 
2346  return *this;
2347  }
2348 
2349 
2351  // Erasing characters
2353 
2360  void clear(void)
2361  {
2362  setlen(0);
2363  trim();
2364  }
2365 
2373  String& erase(void)
2374  {
2375  clear();
2376  return *this;
2377  }
2378 
2391  String& erase(size_type idx)
2392  {
2393  return erase(idx, 1);
2394  }
2395 
2411  String& erase(size_type idx, size_type len)
2412  {
2413  // cover the no-op case.
2414  if (len == 0)
2415  return *this;
2416 
2417  if (d_cplength <= idx)
2418  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2419 
2420  if (len == npos)
2421  len = d_cplength - idx;
2422 
2423  size_type newsz = d_cplength - len;
2424 
2425  memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
2426  setlen(newsz);
2427  return *this;
2428  }
2429 
2440  String& erase(iterator pos)
2441  {
2442  return erase(safe_iter_dif(pos, begin()), 1);
2443  }
2444 
2458  String& erase(iterator iter_beg, iterator iter_end)
2459  {
2460  return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
2461  }
2462 
2464  // Resizing
2466 
2478  void resize(size_type num)
2479  {
2480  resize(num, utf32());
2481  }
2482 
2498  void resize(size_type num, utf32 code_point)
2499  {
2500  if (num < d_cplength)
2501  {
2502  setlen(num);
2503  }
2504  else
2505  {
2506  append(num - d_cplength, code_point);
2507  }
2508 
2509  }
2510 
2512  // Replacing Characters
2514 
2533  String& replace(size_type idx, size_type len, const String& str)
2534  {
2535  return replace(idx, len, str, 0, npos);
2536  }
2537 
2559  String& replace(iterator iter_beg, iterator iter_end, const String& str)
2560  {
2561  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
2562  }
2563 
2589  String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
2590  {
2591  if ((d_cplength < idx) || (str.d_cplength < str_idx))
2592  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2593 
2594  if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
2595  str_num = str.d_cplength - str_idx;
2596 
2597  if (((len + idx) > d_cplength) || (len == npos))
2598  len = d_cplength - idx;
2599 
2600  size_type newsz = d_cplength + str_num - len;
2601 
2602  grow(newsz);
2603 
2604  if ((idx + len) < d_cplength)
2605  memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2606 
2607  memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2608  setlen(newsz);
2609 
2610  return *this;
2611  }
2612 
2613 
2637  String& replace(size_type idx, size_type len, const std::string& std_str)
2638  {
2639  return replace(idx, len, std_str, 0, npos);
2640  }
2641 
2667  String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
2668  {
2669  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
2670  }
2671 
2701  String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
2702  {
2703  if (d_cplength < idx)
2704  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2705 
2706  if (std_str.size() < str_idx)
2707  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
2708 
2709  if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
2710  str_num = (size_type)std_str.size() - str_idx;
2711 
2712  if (((len + idx) > d_cplength) || (len == npos))
2713  len = d_cplength - idx;
2714 
2715  size_type newsz = d_cplength + str_num - len;
2716 
2717  grow(newsz);
2718 
2719  if ((idx + len) < d_cplength)
2720  memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2721 
2722  utf32* pt = &ptr()[idx + str_num - 1];
2723 
2724  while (str_num--)
2725  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2726 
2727  setlen(newsz);
2728 
2729  return *this;
2730  }
2731 
2732 
2758  String& replace(size_type idx, size_type len, const utf8* utf8_str)
2759  {
2760  return replace(idx, len, utf8_str, utf_length(utf8_str));
2761  }
2762 
2790  String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
2791  {
2792  return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
2793  }
2794 
2823  String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
2824  {
2825  if (d_cplength < idx)
2826  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2827 
2828  if (str_len == npos)
2829  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
2830 
2831  if (((len + idx) > d_cplength) || (len == npos))
2832  len = d_cplength - idx;
2833 
2834  size_type encsz = encoded_size(utf8_str, str_len);
2835  size_type newsz = d_cplength + encsz - len;
2836 
2837  grow(newsz);
2838 
2839  if ((idx + len) < d_cplength)
2840  memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2841 
2842  encode(utf8_str, &ptr()[idx], encsz, str_len);
2843 
2844  setlen(newsz);
2845  return *this;
2846  }
2847 
2878  String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
2879  {
2880  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
2881  }
2882 
2905  String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
2906  {
2907  if (d_cplength < idx)
2908  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2909 
2910  if (num == npos)
2911  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
2912 
2913  if (((len + idx) > d_cplength) || (len == npos))
2914  len = d_cplength - idx;
2915 
2916  size_type newsz = d_cplength + num - len;
2917 
2918  grow(newsz);
2919 
2920  if ((idx + len) < d_cplength)
2921  memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2922 
2923  utf32* pt = &ptr()[idx + num - 1];
2924 
2925  while (num--)
2926  *pt-- = code_point;
2927 
2928  setlen(newsz);
2929 
2930  return *this;
2931  }
2932 
2957  String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
2958  {
2959  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
2960  }
2961 
2962 
2987  String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
2988  {
2989  if (iter_newBeg == iter_newEnd)
2990  {
2991  erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
2992  }
2993  else
2994  {
2995  size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
2996  size_type idx = safe_iter_dif(iter_beg, begin());
2997  size_type len = safe_iter_dif(iter_end, iter_beg);
2998 
2999  if ((len + idx) > d_cplength)
3000  len = d_cplength - idx;
3001 
3002  size_type newsz = d_cplength + str_len - len;
3003 
3004  grow(newsz);
3005 
3006  if ((idx + len) < d_cplength)
3007  memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
3008 
3009  memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
3010  setlen(newsz);
3011  }
3012 
3013  return *this;
3014  }
3015 
3016 
3036  String& replace(size_type idx, size_type len, const char* cstr)
3037  {
3038  return replace(idx, len, cstr, strlen(cstr));
3039  }
3040 
3041 
3063  String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
3064  {
3065  return replace(iter_beg, iter_end, cstr, strlen(cstr));
3066  }
3067 
3068 
3091  String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
3092  {
3093  if (d_cplength < idx)
3094  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
3095 
3096  if (chars_len == npos)
3097  CEGUI_THROW(std::length_error("Length for the char array can not be 'npos'"));
3098 
3099  if (((len + idx) > d_cplength) || (len == npos))
3100  len = d_cplength - idx;
3101 
3102  size_type newsz = d_cplength + chars_len - len;
3103 
3104  grow(newsz);
3105 
3106  if ((idx + len) < d_cplength)
3107  memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
3108 
3109  utf32* pt = &ptr()[idx + chars_len - 1];
3110 
3111  while (chars_len--)
3112  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
3113 
3114  setlen(newsz);
3115  return *this;
3116  }
3117 
3118 
3143  String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
3144  {
3145  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
3146  }
3147 
3148 
3150  // Find a code point
3152 
3166  size_type find(utf32 code_point, size_type idx = 0) const
3167  {
3168  if (idx < d_cplength)
3169  {
3170  const utf32* pt = &ptr()[idx];
3171 
3172  while (idx < d_cplength)
3173  {
3174  if (*pt++ == code_point)
3175  return idx;
3176 
3177  ++idx;
3178  }
3179 
3180  }
3181 
3182  return npos;
3183  }
3184 
3199  size_type rfind(utf32 code_point, size_type idx = npos) const
3200  {
3201  if (idx >= d_cplength)
3202  idx = d_cplength - 1;
3203 
3204  if (d_cplength > 0)
3205  {
3206  const utf32* pt = &ptr()[idx];
3207 
3208  do
3209  {
3210  if (*pt-- == code_point)
3211  return idx;
3212 
3213  } while (idx-- != 0);
3214 
3215  }
3216 
3217  return npos;
3218  }
3219 
3221  // Find a substring
3223 
3237  size_type find(const String& str, size_type idx = 0) const
3238  {
3239  if ((str.d_cplength == 0) && (idx < d_cplength))
3240  return idx;
3241 
3242  if (idx < d_cplength)
3243  {
3244  // loop while search string could fit in to search area
3245  while (d_cplength - idx >= str.d_cplength)
3246  {
3247  if (0 == compare(idx, str.d_cplength, str))
3248  return idx;
3249 
3250  ++idx;
3251  }
3252 
3253  }
3254 
3255  return npos;
3256  }
3257 
3272  size_type rfind(const String& str, size_type idx = npos) const
3273  {
3274  if (str.d_cplength == 0)
3275  return (idx < d_cplength) ? idx : d_cplength;
3276 
3277  if (str.d_cplength <= d_cplength)
3278  {
3279  if (idx > (d_cplength - str.d_cplength))
3280  idx = d_cplength - str.d_cplength;
3281 
3282  do
3283  {
3284  if (0 == compare(idx, str.d_cplength, str))
3285  return idx;
3286 
3287  } while (idx-- != 0);
3288 
3289  }
3290 
3291  return npos;
3292  }
3293 
3312  size_type find(const std::string& std_str, size_type idx = 0) const
3313  {
3314  std::string::size_type sze = std_str.size();
3315 
3316  if ((sze == 0) && (idx < d_cplength))
3317  return idx;
3318 
3319  if (idx < d_cplength)
3320  {
3321  // loop while search string could fit in to search area
3322  while (d_cplength - idx >= sze)
3323  {
3324  if (0 == compare(idx, (size_type)sze, std_str))
3325  return idx;
3326 
3327  ++idx;
3328  }
3329 
3330  }
3331 
3332  return npos;
3333  }
3334 
3353  size_type rfind(const std::string& std_str, size_type idx = npos) const
3354  {
3355  std::string::size_type sze = std_str.size();
3356 
3357  if (sze == 0)
3358  return (idx < d_cplength) ? idx : d_cplength;
3359 
3360  if (sze <= d_cplength)
3361  {
3362  if (idx > (d_cplength - sze))
3363  idx = d_cplength - sze;
3364 
3365  do
3366  {
3367  if (0 == compare(idx, (size_type)sze, std_str))
3368  return idx;
3369 
3370  } while (idx-- != 0);
3371 
3372  }
3373 
3374  return npos;
3375  }
3376 
3399  size_type find(const utf8* utf8_str, size_type idx = 0) const
3400  {
3401  return find(utf8_str, idx, utf_length(utf8_str));
3402  }
3403 
3426  size_type rfind(const utf8* utf8_str, size_type idx = npos) const
3427  {
3428  return rfind(utf8_str, idx, utf_length(utf8_str));
3429  }
3430 
3456  size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const
3457  {
3458  if (str_len == npos)
3459  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3460 
3461  size_type sze = encoded_size(utf8_str, str_len);
3462 
3463  if ((sze == 0) && (idx < d_cplength))
3464  return idx;
3465 
3466  if (idx < d_cplength)
3467  {
3468  // loop while search string could fit in to search area
3469  while (d_cplength - idx >= sze)
3470  {
3471  if (0 == compare(idx, sze, utf8_str, sze))
3472  return idx;
3473 
3474  ++idx;
3475  }
3476 
3477  }
3478 
3479  return npos;
3480  }
3481 
3507  size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
3508  {
3509  if (str_len == npos)
3510  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3511 
3512  size_type sze = encoded_size(utf8_str, str_len);
3513 
3514  if (sze == 0)
3515  return (idx < d_cplength) ? idx : d_cplength;
3516 
3517  if (sze <= d_cplength)
3518  {
3519  if (idx > (d_cplength - sze))
3520  idx = d_cplength - sze;
3521 
3522  do
3523  {
3524  if (0 == compare(idx, sze, utf8_str, sze))
3525  return idx;
3526 
3527  } while (idx-- != 0);
3528 
3529  }
3530 
3531  return npos;
3532  }
3533 
3534 
3551  size_type find(const char* cstr, size_type idx = 0) const
3552  {
3553  return find(cstr, idx, strlen(cstr));
3554  }
3555 
3556 
3573  size_type rfind(const char* cstr, size_type idx = npos) const
3574  {
3575  return rfind(cstr, idx, strlen(cstr));
3576  }
3577 
3578 
3598  size_type find(const char* chars, size_type idx, size_type chars_len) const
3599  {
3600  if (chars_len == npos)
3601  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
3602 
3603  if ((chars_len == 0) && (idx < d_cplength))
3604  return idx;
3605 
3606  if (idx < d_cplength)
3607  {
3608  // loop while search string could fit in to search area
3609  while (d_cplength - idx >= chars_len)
3610  {
3611  if (0 == compare(idx, chars_len, chars, chars_len))
3612  return idx;
3613 
3614  ++idx;
3615  }
3616 
3617  }
3618 
3619  return npos;
3620  }
3621 
3622 
3642  size_type rfind(const char* chars, size_type idx, size_type chars_len) const
3643  {
3644  if (chars_len == npos)
3645  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
3646 
3647  if (chars_len == 0)
3648  return (idx < d_cplength) ? idx : d_cplength;
3649 
3650  if (chars_len <= d_cplength)
3651  {
3652  if (idx > (d_cplength - chars_len))
3653  idx = d_cplength - chars_len;
3654 
3655  do
3656  {
3657  if (0 == compare(idx, chars_len, chars, chars_len))
3658  return idx;
3659 
3660  } while (idx-- != 0);
3661 
3662  }
3663 
3664  return npos;
3665  }
3666 
3667 
3669  // Find first of different code-points
3671 
3685  size_type find_first_of(const String& str, size_type idx = 0) const
3686  {
3687  if (idx < d_cplength)
3688  {
3689  const utf32* pt = &ptr()[idx];
3690 
3691  do
3692  {
3693  if (npos != str.find(*pt++))
3694  return idx;
3695 
3696  } while (++idx != d_cplength);
3697 
3698  }
3699 
3700  return npos;
3701  }
3702 
3717  size_type find_first_not_of(const String& str, size_type idx = 0) const
3718  {
3719  if (idx < d_cplength)
3720  {
3721  const utf32* pt = &ptr()[idx];
3722 
3723  do
3724  {
3725  if (npos == str.find(*pt++))
3726  return idx;
3727 
3728  } while (++idx != d_cplength);
3729 
3730  }
3731 
3732  return npos;
3733  }
3734 
3735 
3754  size_type find_first_of(const std::string& std_str, size_type idx = 0) const
3755  {
3756  if (idx < d_cplength)
3757  {
3758  const utf32* pt = &ptr()[idx];
3759 
3760  do
3761  {
3762  if (npos != find_codepoint(std_str, *pt++))
3763  return idx;
3764 
3765  } while (++idx != d_cplength);
3766 
3767  }
3768 
3769  return npos;
3770  }
3771 
3790  size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const
3791  {
3792  if (idx < d_cplength)
3793  {
3794  const utf32* pt = &ptr()[idx];
3795 
3796  do
3797  {
3798  if (npos == find_codepoint(std_str, *pt++))
3799  return idx;
3800 
3801  } while (++idx != d_cplength);
3802 
3803  }
3804 
3805  return npos;
3806  }
3807 
3808 
3831  size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const
3832  {
3833  return find_first_of(utf8_str, idx, utf_length(utf8_str));
3834  }
3835 
3858  size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
3859  {
3860  return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
3861  }
3862 
3888  size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3889  {
3890  if (str_len == npos)
3891  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3892 
3893  if (idx < d_cplength)
3894  {
3895  size_type encsze = encoded_size(utf8_str, str_len);
3896 
3897  const utf32* pt = &ptr()[idx];
3898 
3899  do
3900  {
3901  if (npos != find_codepoint(utf8_str, encsze, *pt++))
3902  return idx;
3903 
3904  } while (++idx != d_cplength);
3905 
3906  }
3907 
3908  return npos;
3909  }
3910 
3936  size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3937  {
3938  if (str_len == npos)
3939  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3940 
3941  if (idx < d_cplength)
3942  {
3943  size_type encsze = encoded_size(utf8_str, str_len);
3944 
3945  const utf32* pt = &ptr()[idx];
3946 
3947  do
3948  {
3949  if (npos == find_codepoint(utf8_str, encsze, *pt++))
3950  return idx;
3951 
3952  } while (++idx != d_cplength);
3953 
3954  }
3955 
3956  return npos;
3957  }
3958 
3959 
3974  size_type find_first_of(utf32 code_point, size_type idx = 0) const
3975  {
3976  return find(code_point, idx);
3977  }
3978 
3995  size_type find_first_not_of(utf32 code_point, size_type idx = 0) const
3996  {
3997  if (idx < d_cplength)
3998  {
3999  do
4000  {
4001  if ((*this)[idx] != code_point)
4002  return idx;
4003 
4004  } while(idx++ < d_cplength);
4005 
4006  }
4007 
4008  return npos;
4009  }
4010 
4011 
4028  size_type find_first_of(const char* cstr, size_type idx = 0) const
4029  {
4030  return find_first_of(cstr, idx, strlen(cstr));
4031  }
4032 
4033 
4050  size_type find_first_not_of(const char* cstr, size_type idx = 0) const
4051  {
4052  return find_first_not_of(cstr, idx, strlen(cstr));
4053  }
4054 
4055 
4075  size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const
4076  {
4077  if (chars_len == npos)
4078  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4079 
4080  if (idx < d_cplength)
4081  {
4082  const utf32* pt = &ptr()[idx];
4083 
4084  do
4085  {
4086  if (npos != find_codepoint(chars, chars_len, *pt++))
4087  return idx;
4088 
4089  } while (++idx != d_cplength);
4090 
4091  }
4092 
4093  return npos;
4094  }
4095 
4096 
4116  size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
4117  {
4118  if (chars_len == npos)
4119  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4120 
4121  if (idx < d_cplength)
4122  {
4123  const utf32* pt = &ptr()[idx];
4124 
4125  do
4126  {
4127  if (npos == find_codepoint(chars, chars_len, *pt++))
4128  return idx;
4129 
4130  } while (++idx != d_cplength);
4131 
4132  }
4133 
4134  return npos;
4135  }
4136 
4137 
4139  // Find last of different code-points
4141 
4155  size_type find_last_of(const String& str, size_type idx = npos) const
4156  {
4157  if (d_cplength > 0)
4158  {
4159  if (idx >= d_cplength)
4160  idx = d_cplength - 1;
4161 
4162  const utf32* pt = &ptr()[idx];
4163 
4164  do
4165  {
4166  if (npos != str.find(*pt--))
4167  return idx;
4168 
4169  } while (idx-- != 0);
4170 
4171  }
4172 
4173  return npos;
4174  }
4175 
4190  size_type find_last_not_of(const String& str, size_type idx = npos) const
4191  {
4192  if (d_cplength > 0)
4193  {
4194  if (idx >= d_cplength)
4195  idx = d_cplength - 1;
4196 
4197  const utf32* pt = &ptr()[idx];
4198 
4199  do
4200  {
4201  if (npos == str.find(*pt--))
4202  return idx;
4203 
4204  } while (idx-- != 0);
4205 
4206  }
4207 
4208  return npos;
4209  }
4210 
4211 
4230  size_type find_last_of(const std::string& std_str, size_type idx = npos) const
4231  {
4232  if (d_cplength > 0)
4233  {
4234  if (idx >= d_cplength)
4235  idx = d_cplength - 1;
4236 
4237  const utf32* pt = &ptr()[idx];
4238 
4239  do
4240  {
4241  if (npos != find_codepoint(std_str, *pt--))
4242  return idx;
4243 
4244  } while (idx-- != 0);
4245 
4246  }
4247 
4248  return npos;
4249  }
4250 
4269  size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const
4270  {
4271  if (d_cplength > 0)
4272  {
4273  if (idx >= d_cplength)
4274  idx = d_cplength - 1;
4275 
4276  const utf32* pt = &ptr()[idx];
4277 
4278  do
4279  {
4280  if (npos == find_codepoint(std_str, *pt--))
4281  return idx;
4282 
4283  } while (idx-- != 0);
4284 
4285  }
4286 
4287  return npos;
4288  }
4289 
4290 
4313  size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const
4314  {
4315  return find_last_of(utf8_str, idx, utf_length(utf8_str));
4316  }
4317 
4340  size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
4341  {
4342  return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
4343  }
4344 
4370  size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4371  {
4372  if (str_len == npos)
4373  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
4374 
4375  if (d_cplength > 0)
4376  {
4377  if (idx >= d_cplength)
4378  idx = d_cplength - 1;
4379 
4380  size_type encsze = encoded_size(utf8_str, str_len);
4381 
4382  const utf32* pt = &ptr()[idx];
4383 
4384  do
4385  {
4386  if (npos != find_codepoint(utf8_str, encsze, *pt--))
4387  return idx;
4388 
4389  } while (idx-- != 0);
4390 
4391  }
4392 
4393  return npos;
4394  }
4395 
4421  size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4422  {
4423  if (str_len == npos)
4424  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
4425 
4426  if (d_cplength > 0)
4427  {
4428  if (idx >= d_cplength)
4429  idx = d_cplength - 1;
4430 
4431  size_type encsze = encoded_size(utf8_str, str_len);
4432 
4433  const utf32* pt = &ptr()[idx];
4434 
4435  do
4436  {
4437  if (npos == find_codepoint(utf8_str, encsze, *pt--))
4438  return idx;
4439 
4440  } while (idx-- != 0);
4441 
4442  }
4443 
4444  return npos;
4445  }
4446 
4447 
4462  size_type find_last_of(utf32 code_point, size_type idx = npos) const
4463  {
4464  return rfind(code_point, idx);
4465  }
4466 
4481  size_type find_last_not_of(utf32 code_point, size_type idx = npos) const
4482  {
4483  if (d_cplength > 0)
4484  {
4485  if (idx >= d_cplength)
4486  idx = d_cplength - 1;
4487 
4488  do
4489  {
4490  if ((*this)[idx] != code_point)
4491  return idx;
4492 
4493  } while(idx-- != 0);
4494 
4495  }
4496 
4497  return npos;
4498  }
4499 
4500 
4517  size_type find_last_of(const char* cstr, size_type idx = npos) const
4518  {
4519  return find_last_of(cstr, idx, strlen(cstr));
4520  }
4521 
4522 
4539  size_type find_last_not_of(const char* cstr, size_type idx = npos) const
4540  {
4541  return find_last_not_of(cstr, idx, strlen(cstr));
4542  }
4543 
4544 
4564  size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const
4565  {
4566  if (chars_len == npos)
4567  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4568 
4569  if (d_cplength > 0)
4570  {
4571  if (idx >= d_cplength)
4572  idx = d_cplength - 1;
4573 
4574  const utf32* pt = &ptr()[idx];
4575 
4576  do
4577  {
4578  if (npos != find_codepoint(chars, chars_len, *pt--))
4579  return idx;
4580 
4581  } while (idx-- != 0);
4582 
4583  }
4584 
4585  return npos;
4586  }
4587 
4588 
4608  size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
4609  {
4610  if (chars_len == npos)
4611  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4612 
4613  if (d_cplength > 0)
4614  {
4615  if (idx >= d_cplength)
4616  idx = d_cplength - 1;
4617 
4618  const utf32* pt = &ptr()[idx];
4619 
4620  do
4621  {
4622  if (npos == find_codepoint(chars, chars_len, *pt--))
4623  return idx;
4624 
4625  } while (idx-- != 0);
4626 
4627  }
4628 
4629  return npos;
4630  }
4631 
4632 
4634  // Substring
4636 
4651  String substr(size_type idx = 0, size_type len = npos) const
4652  {
4653  if (d_cplength < idx)
4654  CEGUI_THROW(std::out_of_range("Index is out of range for this CEGUI::String"));
4655 
4656  return String(*this, idx, len);
4657  }
4658 
4660  // Iterator creation
4662 
4669  iterator begin(void)
4670  {
4671  return iterator(ptr());
4672  }
4673 
4681  const_iterator begin(void) const
4682  {
4683  return const_iterator(ptr());
4684  }
4685 
4693  iterator end(void)
4694  {
4695  return iterator(&ptr()[d_cplength]);
4696  }
4697 
4705  const_iterator end(void) const
4706  {
4707  return const_iterator(&ptr()[d_cplength]);
4708  }
4709 
4717  reverse_iterator rbegin(void)
4718  {
4719  return reverse_iterator(end());
4720  }
4721 
4729  const_reverse_iterator rbegin(void) const
4730  {
4731  return const_reverse_iterator(end());
4732  }
4733 
4741  reverse_iterator rend(void)
4742  {
4743  return reverse_iterator(begin());
4744  }
4745 
4753  const_reverse_iterator rend(void) const
4754  {
4755  return const_reverse_iterator(begin());
4756  }
4757 
4758 private:
4759  /*************************************************************************
4760  Implementation Functions
4761  *************************************************************************/
4762  // string management
4763 
4764  // change size of allocated buffer so it is at least 'new_size'.
4765  // May or may not cause re-allocation and copy of buffer if size is larger
4766  // will never re-allocate to make size smaller. (see trim())
4767  bool grow(size_type new_size);
4768 
4769  // perform re-allocation to remove wasted space.
4770  void trim(void);
4771 
4772  // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
4773  void setlen(size_type len)
4774  {
4775  d_cplength = len;
4776  ptr()[len] = (utf32)(0);
4777  }
4778 
4779  // initialise string object
4780  void init(void)
4781  {
4782  d_reserve = STR_QUICKBUFF_SIZE;
4783  d_encodedbuff = 0;
4784  d_encodedbufflen = 0;
4785  d_encodeddatlen = 0;
4786  d_buffer = 0;
4787  setlen(0);
4788  }
4789 
4790  // return true if the given pointer is inside the string data
4791  bool inside(utf32* inptr)
4792  {
4793  if (inptr < ptr() || ptr() + d_cplength <= inptr)
4794  return false;
4795  else
4796  return true;
4797  }
4798 
4799  // compute distance between two iterators, returning a 'safe' value
4800  size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
4801  {
4802  return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
4803  }
4804 
4805  // encoding functions
4806  // for all:
4807  // src_len is in code units, or 0 for null terminated string.
4808  // dest_len is in code units.
4809  // returns number of code units put into dest buffer.
4810  size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
4811  {
4812  // count length for null terminated source...
4813  if (src_len == 0)
4814  {
4815  src_len = utf_length(src);
4816  }
4817 
4818  size_type destCapacity = dest_len;
4819 
4820  // while there is data in the source buffer,
4821  for (uint idx = 0; idx < src_len; ++idx)
4822  {
4823  utf32 cp = src[idx];
4824 
4825  // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
4826  if (destCapacity < encoded_size(cp))
4827  {
4828  break;
4829  }
4830 
4831  if (cp < 0x80)
4832  {
4833  *dest++ = (utf8)cp;
4834  --destCapacity;
4835  }
4836  else if (cp < 0x0800)
4837  {
4838  *dest++ = (utf8)((cp >> 6) | 0xC0);
4839  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4840  destCapacity -= 2;
4841  }
4842  else if (cp < 0x10000)
4843  {
4844  *dest++ = (utf8)((cp >> 12) | 0xE0);
4845  *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4846  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4847  destCapacity -= 3;
4848  }
4849  else
4850  {
4851  *dest++ = (utf8)((cp >> 18) | 0xF0);
4852  *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
4853  *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4854  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4855  destCapacity -= 4;
4856  }
4857 
4858  }
4859 
4860  return dest_len - destCapacity;
4861  }
4862 
4863  size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
4864  {
4865  // count length for null terminated source...
4866  if (src_len == 0)
4867  {
4868  src_len = utf_length(src);
4869  }
4870 
4871  size_type destCapacity = dest_len;
4872 
4873  // while there is data in the source buffer, and space in the dest buffer
4874  for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
4875  {
4876  utf32 cp;
4877  utf8 cu = src[idx++];
4878 
4879  if (cu < 0x80)
4880  {
4881  cp = (utf32)(cu);
4882  }
4883  else if (cu < 0xE0)
4884  {
4885  cp = ((cu & 0x1F) << 6);
4886  cp |= (src[idx++] & 0x3F);
4887  }
4888  else if (cu < 0xF0)
4889  {
4890  cp = ((cu & 0x0F) << 12);
4891  cp |= ((src[idx++] & 0x3F) << 6);
4892  cp |= (src[idx++] & 0x3F);
4893  }
4894  else
4895  {
4896  cp = ((cu & 0x07) << 18);
4897  cp |= ((src[idx++] & 0x3F) << 12);
4898  cp |= ((src[idx++] & 0x3F) << 6);
4899  cp |= (src[idx++] & 0x3F);
4900  }
4901 
4902  *dest++ = cp;
4903  --destCapacity;
4904  }
4905 
4906  return dest_len - destCapacity;
4907  }
4908 
4909  // return the number of utf8 code units required to encode the given utf32 code point
4910  size_type encoded_size(utf32 code_point) const
4911  {
4912  if (code_point < 0x80)
4913  return 1;
4914  else if (code_point < 0x0800)
4915  return 2;
4916  else if (code_point < 0x10000)
4917  return 3;
4918  else
4919  return 4;
4920  }
4921 
4922  // return number of code units required to re-encode given null-terminated utf32 data as utf8. return does not include terminating null.
4923  size_type encoded_size(const utf32* buf) const
4924  {
4925  return encoded_size(buf, utf_length(buf));
4926  }
4927 
4928  // return number of code units required to re-encode given utf32 data as utf8. len is number of code units in 'buf'.
4929  size_type encoded_size(const utf32* buf, size_type len) const
4930  {
4931  size_type count = 0;
4932 
4933  while (len--)
4934  {
4935  count += encoded_size(*buf++);
4936  }
4937 
4938  return count;
4939  }
4940 
4941  // return number of utf32 code units required to re-encode given utf8 data as utf32. return does not include terminating null.
4942  size_type encoded_size(const utf8* buf) const
4943  {
4944  return encoded_size(buf, utf_length(buf));
4945  }
4946 
4947  // return number of utf32 code units required to re-encode given utf8 data as utf32. len is number of code units in 'buf'.
4948  size_type encoded_size(const utf8* buf, size_type len) const
4949  {
4950  utf8 tcp;
4951  size_type count = 0;
4952 
4953  while (len--)
4954  {
4955  tcp = *buf++;
4956  ++count;
4957  size_type size = 0;
4958 
4959  if (tcp < 0x80)
4960  {
4961  }
4962  else if (tcp < 0xE0)
4963  {
4964  size = 1;
4965  ++buf;
4966  }
4967  else if (tcp < 0xF0)
4968  {
4969  size = 2;
4970  buf += 2;
4971  }
4972  else
4973  {
4974  size = 3;
4975  buf += 3;
4976  }
4977 
4978  if (len >= size)
4979  len -= size;
4980  else
4981  break;
4982  }
4983 
4984  return count;
4985  }
4986 
4987  // return number of code units in a null terminated string
4988  size_type utf_length(const utf8* utf8_str) const
4989  {
4990  size_type cnt = 0;
4991  while (*utf8_str++)
4992  cnt++;
4993 
4994  return cnt;
4995  }
4996 
4997  // return number of code units in a null terminated string
4998  size_type utf_length(const utf32* utf32_str) const
4999  {
5000  size_type cnt = 0;
5001  while (*utf32_str++)
5002  cnt++;
5003 
5004  return cnt;
5005  }
5006 
5007  // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
5008  utf8* build_utf8_buff(void) const;
5009 
5010  // compare two utf32 buffers
5011  int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
5012  {
5013  if (!cp_count)
5014  return 0;
5015 
5016  while ((--cp_count) && (*buf1 == *buf2))
5017  buf1++, buf2++;
5018 
5019  return *buf1 - *buf2;
5020  }
5021 
5022  // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
5023  int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
5024  {
5025  if (!cp_count)
5026  return 0;
5027 
5028  while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
5029  buf1++, buf2++;
5030 
5031  return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
5032  }
5033 
5034  // compare utf32 buffer with encoded utf8 data
5035  int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
5036  {
5037  if (!cp_count)
5038  return 0;
5039 
5040  utf32 cp;
5041  utf8 cu;
5042 
5043  do
5044  {
5045  cu = *buf2++;
5046 
5047  if (cu < 0x80)
5048  {
5049  cp = (utf32)(cu);
5050  }
5051  else if (cu < 0xE0)
5052  {
5053  cp = ((cu & 0x1F) << 6);
5054  cp |= (*buf2++ & 0x3F);
5055  }
5056  else if (cu < 0xF0)
5057  {
5058  cp = ((cu & 0x0F) << 12);
5059  cp |= ((*buf2++ & 0x3F) << 6);
5060  cp |= (*buf2++ & 0x3F);
5061  }
5062  else
5063  {
5064  cp = ((cu & 0x07) << 18);
5065  cp |= ((*buf2++ & 0x3F) << 12);
5066  cp |= ((*buf2++ & 0x3F) << 6);
5067  cp |= (*buf2++ & 0x3F);
5068  }
5069 
5070  } while ((*buf1++ == cp) && (--cp_count));
5071 
5072  return (*--buf1) - cp;
5073  }
5074 
5075  // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
5076  size_type find_codepoint(const std::string& str, utf32 code_point) const
5077  {
5078  size_type idx = 0, sze = (size_type)str.size();
5079 
5080  while (idx != sze)
5081  {
5082  if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
5083  return idx;
5084 
5085  ++idx;
5086  }
5087 
5088  return npos;
5089  }
5090 
5091  // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none. len is in code points.
5092  size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
5093  {
5094  size_type idx = 0;
5095 
5096  utf32 cp;
5097  utf8 cu;
5098 
5099  while (idx != len) {
5100  cu = *str++;
5101 
5102  if (cu < 0x80)
5103  {
5104  cp = (utf32)(cu);
5105  }
5106  else if (cu < 0xE0)
5107  {
5108  cp = ((cu & 0x1F) << 6);
5109  cp |= (*str++ & 0x3F);
5110  }
5111  else if (cu < 0xF0)
5112  {
5113  cp = ((cu & 0x0F) << 12);
5114  cp |= ((*str++ & 0x3F) << 6);
5115  cp |= (*str++ & 0x3F);
5116  }
5117  else
5118  {
5119  cp = ((cu & 0x07) << 18);
5120  cp |= ((*str++ & 0x3F) << 12);
5121  cp |= ((*str++ & 0x3F) << 6);
5122  cp |= (*str++ & 0x3F);
5123  }
5124 
5125  if (code_point == cp)
5126  return idx;
5127 
5128  ++idx;
5129  }
5130 
5131  return npos;
5132  }
5133 
5134 
5135  // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
5136  size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
5137  {
5138  for (size_type idx = 0; idx != chars_len; ++idx)
5139  {
5140  if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
5141  return idx;
5142  }
5143 
5144  return npos;
5145  }
5146 
5147 };
5148 
5149 
5151 // Comparison operators
5153 
5157 bool CEGUIEXPORT operator==(const String& str1, const String& str2);
5158 
5163 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str);
5164 
5169 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str);
5170 
5175 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str);
5176 
5181 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str);
5182 
5187 bool CEGUIEXPORT operator!=(const String& str1, const String& str2);
5188 
5193 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str);
5194 
5199 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str);
5200 
5205 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str);
5206 
5211 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str);
5212 
5217 bool CEGUIEXPORT operator<(const String& str1, const String& str2);
5218 
5223 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str);
5224 
5229 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str);
5230 
5235 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str);
5236 
5241 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str);
5242 
5247 bool CEGUIEXPORT operator>(const String& str1, const String& str2);
5248 
5253 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str);
5254 
5259 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str);
5260 
5265 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str);
5266 
5271 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str);
5272 
5277 bool CEGUIEXPORT operator<=(const String& str1, const String& str2);
5278 
5283 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str);
5284 
5289 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str);
5290 
5295 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str);
5296 
5301 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str);
5302 
5307 bool CEGUIEXPORT operator>=(const String& str1, const String& str2);
5308 
5313 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str);
5314 
5319 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str);
5320 
5325 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str);
5326 
5331 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str);
5332 
5337 bool CEGUIEXPORT operator==(const String& str, const char* c_str);
5338 
5343 bool CEGUIEXPORT operator==(const char* c_str, const String& str);
5344 
5349 bool CEGUIEXPORT operator!=(const String& str, const char* c_str);
5350 
5355 bool CEGUIEXPORT operator!=(const char* c_str, const String& str);
5356 
5361 bool CEGUIEXPORT operator<(const String& str, const char* c_str);
5362 
5367 bool CEGUIEXPORT operator<(const char* c_str, const String& str);
5368 
5373 bool CEGUIEXPORT operator>(const String& str, const char* c_str);
5374 
5379 bool CEGUIEXPORT operator>(const char* c_str, const String& str);
5380 
5385 bool CEGUIEXPORT operator<=(const String& str, const char* c_str);
5386 
5391 bool CEGUIEXPORT operator<=(const char* c_str, const String& str);
5392 
5397 bool CEGUIEXPORT operator>=(const String& str, const char* c_str);
5398 
5403 bool CEGUIEXPORT operator>=(const char* c_str, const String& str);
5404 
5406 // Concatenation operator functions
5408 
5423 String CEGUIEXPORT operator+(const String& str1, const String& str2);
5424 
5440 String CEGUIEXPORT operator+(const String& str, const std::string& std_str);
5441 
5457 String CEGUIEXPORT operator+(const std::string& std_str, const String& str);
5458 
5474 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str);
5475 
5491 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str);
5492 
5508 String CEGUIEXPORT operator+(const String& str, utf32 code_point);
5509 
5525 String CEGUIEXPORT operator+(utf32 code_point, const String& str);
5526 
5542 String CEGUIEXPORT operator+(const String& str, const char* c_str);
5543 
5559 String CEGUIEXPORT operator+(const char* c_str, const String& str);
5560 
5561 
5563 // Output (stream) functions
5565 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
5566 
5567 
5569 // Modifying operations
5571 
5584 void CEGUIEXPORT swap(String& str1, String& str2);
5585 
5586 
5587 } // End of CEGUI namespace section
5588 
5589 
5590 #endif // end of guard _CEGUIString_h_