Crazy Eddie's GUI System  0.8.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
String.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 "CEGUI/Base.h"
34 #include <string.h>
35 #include <stdexcept>
36 #include <cstddef>
37 
38 // Start of CEGUI namespace section
39 namespace CEGUI
40 {
41 /*************************************************************************
42 Basic Types
43 *************************************************************************/
44 typedef uint8 utf8;
45 //typedef uint16 utf16; // removed typedef to prevent usage, as utf16 is not supported (yet)
46 typedef uint32 utf32;
47 
48 #if CEGUI_STRING_CLASS == CEGUI_STRING_CLASS_UNICODE
49 
51 typedef utf8 encoded_char;
52 
53 #define CEGUI_STR_QUICKBUFF_SIZE 32
54 
63 class CEGUIEXPORT String :
64  public AllocatedObject<String>
65 {
66 public:
67  /*************************************************************************
68  Integral Types
69  *************************************************************************/
70  typedef utf32 value_type;
71  typedef size_t size_type;
72  typedef std::ptrdiff_t difference_type;
73  typedef utf32& reference;
74  typedef const utf32& const_reference;
75  typedef utf32* pointer;
76  typedef const utf32* const_pointer;
77 
78  static const size_type npos;
79 
80 private:
81  /*************************************************************************
82  Implementation data
83  *************************************************************************/
84  size_type d_cplength;
85  size_type d_reserve;
86 
87  mutable utf8* d_encodedbuff;
88  mutable size_type d_encodeddatlen;
89  mutable size_type d_encodedbufflen;
90 
91  utf32 d_quickbuff[CEGUI_STR_QUICKBUFF_SIZE];
92  utf32* d_buffer;
93 
94 public:
95  /*************************************************************************
96  Iterator Classes
97  *************************************************************************/
99  class iterator : public std::iterator<std::random_access_iterator_tag, utf32>
100  {
101  public:
102  iterator() : d_ptr(0) {}
103  explicit iterator(utf32* const ptr) : d_ptr(ptr) {}
104 
105  utf32& operator*() const
106  {
107  return *d_ptr;
108  }
109 
110  utf32* operator->() const
111  {
112  return &**this;
113  }
114 
115  String::iterator& operator++()
116  {
117  ++d_ptr;
118  return *this;
119  }
120 
121  String::iterator operator++(int)
122  {
123  String::iterator temp = *this;
124  ++*this;
125  return temp;
126  }
127 
128  String::iterator& operator--()
129  {
130  --d_ptr;
131  return *this;
132  }
133 
134  String::iterator operator--(int)
135  {
136  String::iterator temp = *this;
137  --*this;
138  return temp;
139  }
140 
141  String::iterator& operator+=(difference_type offset)
142  {
143  d_ptr += offset;
144  return *this;
145  }
146 
148  {
149  String::iterator temp = *this;
150  return temp += offset;
151  }
152 
153  String::iterator& operator-=(difference_type offset)
154  {
155  return *this += -offset;
156  }
157 
158  String::iterator operator-(difference_type offset) const
159  {
160  String::iterator temp = *this;
161  return temp -= offset;
162  }
163 
164  utf32& operator[](difference_type offset) const
165  {
166  return *(*this + offset);
167  }
168 
169  friend difference_type operator-(const String::iterator& lhs,
170  const String::iterator& rhs)
171  { return lhs.d_ptr - rhs.d_ptr; }
172 
173  friend String::iterator operator+(difference_type offset, const String::iterator& iter)
174  { return iter + offset; }
175 
176  friend bool operator==(const String::iterator& lhs,
177  const String::iterator& rhs)
178  { return lhs.d_ptr == rhs.d_ptr; }
179 
180  friend bool operator!=(const String::iterator& lhs,
181  const String::iterator& rhs)
182  { return lhs.d_ptr != rhs.d_ptr; }
183 
184  friend bool operator<(const String::iterator& lhs,
185  const String::iterator& rhs)
186  { return lhs.d_ptr < rhs.d_ptr; }
187 
188  friend bool operator>(const String::iterator& lhs,
189  const String::iterator& rhs)
190  { return lhs.d_ptr > rhs.d_ptr; }
191 
192  friend bool operator<=(const String::iterator& lhs,
193  const String::iterator& rhs)
194  { return lhs.d_ptr <= rhs.d_ptr; }
195 
196  friend bool operator>=(const String::iterator& lhs,
197  const String::iterator& rhs)
198  { return lhs.d_ptr >= rhs.d_ptr; }
199 
200  utf32* d_ptr;
201  };
202 
204  class const_iterator : public std::iterator<std::random_access_iterator_tag, const utf32>
205  {
206  public:
207  const_iterator() : d_ptr(0) {}
208  explicit const_iterator(const utf32* const ptr) : d_ptr(ptr) {}
209  const_iterator(const String::iterator& iter) : d_ptr(iter.d_ptr) {}
210 
211  const utf32& operator*() const
212  {
213  return *d_ptr;
214  }
215 
216  const utf32* operator->() const
217  {
218  return &**this;
219  }
220 
221  String::const_iterator& operator++()
222  {
223  ++d_ptr;
224  return *this;
225  }
226 
227  String::const_iterator operator++(int)
228  {
229  String::const_iterator temp = *this;
230  ++*this;
231  return temp;
232  }
233 
234  String::const_iterator& operator--()
235  {
236  --d_ptr;
237  return *this;
238  }
239 
240  String::const_iterator operator--(int)
241  {
242  String::const_iterator temp = *this;
243  --*this;
244  return temp;
245  }
246 
247  String::const_iterator& operator+=(difference_type offset)
248  {
249  d_ptr += offset;
250  return *this;
251  }
252 
254  {
255  String::const_iterator temp = *this;
256  return temp += offset;
257  }
258 
259  String::const_iterator& operator-=(difference_type offset)
260  {
261  return *this += -offset;
262  }
263 
264  String::const_iterator operator-(difference_type offset) const
265  {
266  String::const_iterator temp = *this;
267  return temp -= offset;
268  }
269 
270  const utf32& operator[](difference_type offset) const
271  {
272  return *(*this + offset);
273  }
274 
275  String::const_iterator& operator=(const String::iterator& iter)
276  {
277  d_ptr = iter.d_ptr;
278  return *this;
279  }
280 
282  { return iter + offset; }
283 
284  friend difference_type operator-(const String::const_iterator& lhs,
285  const String::const_iterator& rhs)
286  { return lhs.d_ptr - rhs.d_ptr; }
287 
288  friend bool operator==(const String::const_iterator& lhs,
289  const String::const_iterator& rhs)
290  { return lhs.d_ptr == rhs.d_ptr; }
291 
292  friend bool operator!=(const String::const_iterator& lhs,
293  const String::const_iterator& rhs)
294  { return lhs.d_ptr != rhs.d_ptr; }
295 
296  friend bool operator<(const String::const_iterator& lhs,
297  const String::const_iterator& rhs)
298  { return lhs.d_ptr < rhs.d_ptr; }
299 
300  friend bool operator>(const String::const_iterator& lhs,
301  const String::const_iterator& rhs)
302  { return lhs.d_ptr > rhs.d_ptr; }
303 
304  friend bool operator<=(const String::const_iterator& lhs,
305  const String::const_iterator& rhs)
306  { return lhs.d_ptr <= rhs.d_ptr; }
307 
308  friend bool operator>=(const String::const_iterator& lhs,
309  const String::const_iterator& rhs)
310  { return lhs.d_ptr >= rhs.d_ptr; }
311 
312  const utf32* d_ptr;
313  };
314 
319 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
320  typedef std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type> const_reverse_iterator;
321 #else
322  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
323 #endif
324 
329 #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
330  typedef std::reverse_iterator<iterator, pointer, reference, difference_type> reverse_iterator;
331 #else
332  typedef std::reverse_iterator<iterator> reverse_iterator;
333 #endif
334 
335 public:
337  // Default Construction and Destructor
339 
343  String(void)
344  {
345  init();
346  }
347 
352  ~String(void);
353 
355  // Construction via CEGUI::String
357 
367  String(const String& str)
368  {
369  init();
370  assign(str);
371  }
372 
373 
390  String(const String& str, size_type str_idx, size_type str_num = npos)
391  {
392  init();
393  assign(str, str_idx, str_num);
394  }
395 
397  // Construction via std::string
399 
415  String(const std::string& std_str)
416  {
417  init();
418  assign(std_str);
419  }
420 
443  String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
444  {
445  init();
446  assign(std_str, str_idx, str_num);
447  }
448 
449 
451  // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
453 
471  String(const utf8* utf8_str)
472  {
473  init();
474  assign(utf8_str);
475  }
476 
503  String(const utf8* utf8_str, size_type chars_len)
504  {
505  init();
506  assign(utf8_str, chars_len);
507  }
508 
510  // Construction via code-point (using a UTF-32 code unit)
512 
527  String(size_type num, utf32 code_point)
528  {
529  init();
530  assign(num, code_point);
531  }
532 
534  // Construction via iterator
536  // Create string with characters in the range [beg, end)
551  {
552  init();
553  append(iter_beg, iter_end);
554  }
555 
556 
558  // Construction via c-string
560 
572  String(const char* cstr)
573  {
574  init();
575  assign(cstr);
576  }
577 
593  String(const char* chars, size_type chars_len)
594  {
595  init();
596  assign(chars, chars_len);
597  }
598 
599 
601  // Size operations
603 
610  size_type size(void) const
611  {
612  return d_cplength;
613  }
614 
622  size_type length(void) const
623  {
624  return d_cplength;
625  }
626 
634  bool empty(void) const
635  {
636  return (d_cplength == 0);
637  }
638 
648  size_type max_size(void) const
649  {
650  return (((size_type)-1) / sizeof(utf32));
651  }
652 
654  // Capacity Operations
656  // return the number of code points the string could hold without re-allocation
657  // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
666  size_type capacity(void) const
667  {
668  return d_reserve - 1;
669  }
670 
671  // reserve internal memory for at-least 'num' code-points (characters). if num is 0, request is shrink-to-fit.
686  void reserve(size_type num = 0)
687  {
688  if (num == 0)
689  trim();
690  else
691  grow(num);
692  }
693 
695  // Comparisons
697 
712  int compare(const String& str) const
713  {
714  return compare(0, d_cplength, str);
715  }
716 
746  int compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
747  {
748  if ((d_cplength < idx) || (str.d_cplength < str_idx))
749  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
750 
751  if ((len == npos) || (idx + len > d_cplength))
752  len = d_cplength - idx;
753 
754  if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
755  str_len = str.d_cplength - str_idx;
756 
757  int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
758 
759  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
760  }
761 
762 
782  int compare(const std::string& std_str) const
783  {
784  return compare(0, d_cplength, std_str);
785  }
786 
787 
821  int compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
822  {
823  if (d_cplength < idx)
824  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
825 
826  if (std_str.size() < str_idx)
827  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
828 
829  if ((len == npos) || (idx + len > d_cplength))
830  len = d_cplength - idx;
831 
832  if ((str_len == npos) || (str_idx + str_len > std_str.size()))
833  str_len = (size_type)std_str.size() - str_idx;
834 
835  int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
836 
837  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
838  }
839 
840 
862  int compare(const utf8* utf8_str) const
863  {
864  return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
865  }
866 
867 
897  int compare(size_type idx, size_type len, const utf8* utf8_str) const
898  {
899  return compare(idx, len, utf8_str, encoded_size(utf8_str));
900  }
901 
935  int compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
936  {
937  if (d_cplength < idx)
938  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
939 
940  if (str_cplen == npos)
941  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
942 
943  if ((len == npos) || (idx + len > d_cplength))
944  len = d_cplength - idx;
945 
946  int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
947 
948  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
949  }
950 
951 
967  int compare(const char* cstr) const
968  {
969  return compare(0, d_cplength, cstr, strlen(cstr));
970  }
971 
972 
996  int compare(size_type idx, size_type len, const char* cstr) const
997  {
998  return compare(idx, len, cstr, strlen(cstr));
999  }
1000 
1001 
1029  int compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
1030  {
1031  if (d_cplength < idx)
1032  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1033 
1034  if (chars_len == npos)
1035  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
1036 
1037  if ((len == npos) || (idx + len > d_cplength))
1038  len = d_cplength - idx;
1039 
1040  int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
1041 
1042  return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
1043  }
1044 
1045 
1047  // Character access
1049 
1063  reference operator[](size_type idx)
1064  {
1065  return (ptr()[idx]);
1066  }
1067 
1082  value_type operator[](size_type idx) const
1083  {
1084  return ptr()[idx];
1085  }
1086 
1100  {
1101  if (d_cplength <= idx)
1102  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1103 
1104  return ptr()[idx];
1105  }
1106 
1120  {
1121  if (d_cplength <= idx)
1122  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1123 
1124  return ptr()[idx];
1125  }
1126 
1127 
1129  // C-Strings and arrays
1131 
1144  const char* c_str(void) const
1145  {
1146  return (const char*)build_utf8_buff();
1147  }
1148 
1162  const utf8* data(void) const
1163  {
1164  return build_utf8_buff();
1165  }
1166 
1171  utf32* ptr(void)
1172  {
1173  return (d_reserve > CEGUI_STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
1174  }
1175 
1180  const utf32* ptr(void) const
1181  {
1182  return (d_reserve > CEGUI_STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
1183  }
1184 
1185  // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
1186  // return number of utf8 code units placed into the buffer
1207  size_type copy(utf8* buf, size_type len = npos, size_type idx = 0) const
1208  {
1209  if (d_cplength < idx)
1210  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1211 
1212  if (len == npos)
1213  len = d_cplength;
1214 
1215  return encode(&ptr()[idx], buf, npos, len);
1216  }
1217 
1219  // UTF8 Encoding length information
1221  // 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.
1237  size_type utf8_stream_len(size_type num = npos, size_type idx = 0) const
1238  {
1239  using namespace std;
1240 
1241  if (d_cplength < idx)
1242  CEGUI_THROW(out_of_range("Index was out of range for CEGUI::String object"));
1243 
1244  size_type maxlen = d_cplength - idx;
1245 
1246  return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
1247  }
1248 
1250  // Assignment Functions
1252 
1262  String& operator=(const String& str)
1263  {
1264  return assign(str);
1265  }
1266 
1285  String& assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
1286  {
1287  if (str.d_cplength < str_idx)
1288  CEGUI_THROW(std::out_of_range("Index was out of range for CEGUI::String object"));
1289 
1290  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
1291  str_num = str.d_cplength - str_idx;
1292 
1293  grow(str_num);
1294  setlen(str_num);
1295  memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
1296 
1297  return *this;
1298  }
1299 
1316  String& operator=(const std::string& std_str)
1317  {
1318  return assign(std_str);
1319  }
1320 
1344  String& assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1345  {
1346  if (std_str.size() < str_idx)
1347  CEGUI_THROW(std::out_of_range("Index was out of range for std::string object"));
1348 
1349  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
1350  str_num = (size_type)std_str.size() - str_idx;
1351 
1352  grow(str_num);
1353  setlen(str_num);
1354 
1355  while(str_num--)
1356  {
1357  ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
1358  }
1359 
1360  return *this;
1361  }
1362 
1381  String& operator=(const utf8* utf8_str)
1382  {
1383  return assign(utf8_str, utf_length(utf8_str));
1384  }
1385 
1404  String& assign(const utf8* utf8_str)
1405  {
1406  return assign(utf8_str, utf_length(utf8_str));
1407  }
1408 
1430  String& assign(const utf8* utf8_str, size_type str_num)
1431  {
1432  if (str_num == npos)
1433  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
1434 
1435  size_type enc_sze = encoded_size(utf8_str, str_num);
1436 
1437  grow(enc_sze);
1438  encode(utf8_str, ptr(), d_reserve, str_num);
1439  setlen(enc_sze);
1440  return *this;
1441  }
1442 
1453  String& operator=(utf32 code_point)
1454  {
1455  return assign(1, code_point);
1456  }
1457 
1473  String& assign(size_type num, utf32 code_point)
1474  {
1475  if (num == npos)
1476  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
1477 
1478  grow(num);
1479  setlen(num);
1480  utf32* p = ptr();
1481 
1482  while(num--)
1483  *p++ = code_point;
1484 
1485  return *this;
1486  }
1487 
1488 
1501  String& operator=(const char* cstr)
1502  {
1503  return assign(cstr, strlen(cstr));
1504  }
1505 
1506 
1519  String& assign(const char* cstr)
1520  {
1521  return assign(cstr, strlen(cstr));
1522  }
1523 
1524 
1540  String& assign(const char* chars, size_type chars_len)
1541  {
1542  grow(chars_len);
1543  utf32* pt = ptr();
1544 
1545  for (size_type i = 0; i < chars_len; ++i)
1546  {
1547  *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
1548  }
1549 
1550  setlen(chars_len);
1551  return *this;
1552  }
1553 
1554 
1565  void swap(String& str)
1566  {
1567  size_type temp_len = d_cplength;
1568  d_cplength = str.d_cplength;
1569  str.d_cplength = temp_len;
1570 
1571  size_type temp_res = d_reserve;
1572  d_reserve = str.d_reserve;
1573  str.d_reserve = temp_res;
1574 
1575  utf32* temp_buf = d_buffer;
1576  d_buffer = str.d_buffer;
1577  str.d_buffer = temp_buf;
1578 
1579  // see if we need to swap 'quick buffer' data
1580  if (temp_res <= CEGUI_STR_QUICKBUFF_SIZE)
1581  {
1582  utf32 temp_qbf[CEGUI_STR_QUICKBUFF_SIZE];
1583 
1584  memcpy(temp_qbf, d_quickbuff, CEGUI_STR_QUICKBUFF_SIZE * sizeof(utf32));
1585  memcpy(d_quickbuff, str.d_quickbuff, CEGUI_STR_QUICKBUFF_SIZE * sizeof(utf32));
1586  memcpy(str.d_quickbuff, temp_qbf, CEGUI_STR_QUICKBUFF_SIZE * sizeof(utf32));
1587  }
1588 
1589  }
1590 
1592  // Appending Functions
1594 
1606  String& operator+=(const String& str)
1607  {
1608  return append(str);
1609  }
1610 
1630  String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
1631  {
1632  if (str.d_cplength < str_idx)
1633  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
1634 
1635  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
1636  str_num = str.d_cplength - str_idx;
1637 
1638  grow(d_cplength + str_num);
1639  memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
1640  setlen(d_cplength + str_num);
1641  return *this;
1642  }
1643 
1644 
1661  String& operator+=(const std::string& std_str)
1662  {
1663  return append(std_str);
1664  }
1665 
1689  String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
1690  {
1691  if (std_str.size() < str_idx)
1692  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
1693 
1694  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
1695  str_num = (size_type)std_str.size() - str_idx;
1696 
1697  size_type newsze = d_cplength + str_num;
1698 
1699  grow(newsze);
1700  utf32* pt = &ptr()[newsze-1];
1701 
1702  while(str_num--)
1703  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
1704 
1705  setlen(newsze);
1706  return *this;
1707  }
1708 
1709 
1728  String& operator+=(const utf8* utf8_str)
1729  {
1730  return append(utf8_str, utf_length(utf8_str));
1731  }
1732 
1751  String& append(const utf8* utf8_str)
1752  {
1753  return append(utf8_str, utf_length(utf8_str));
1754  }
1755 
1756 
1778  String& append(const utf8* utf8_str, size_type len)
1779  {
1780  if (len == npos)
1781  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
1782 
1783  size_type encsz = encoded_size(utf8_str, len);
1784  size_type newsz = d_cplength + encsz;
1785 
1786  grow(newsz);
1787  encode(utf8_str, &ptr()[d_cplength], encsz, len);
1788  setlen(newsz);
1789 
1790  return *this;
1791  }
1792 
1793 
1806  String& operator+=(utf32 code_point)
1807  {
1808  return append(1, code_point);
1809  }
1810 
1826  String& append(size_type num, utf32 code_point)
1827  {
1828  if (num == npos)
1829  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
1830 
1831  size_type newsz = d_cplength + num;
1832  grow(newsz);
1833 
1834  utf32* p = &ptr()[d_cplength];
1835 
1836  while(num--)
1837  *p++ = code_point;
1838 
1839  setlen(newsz);
1840 
1841  return *this;
1842  }
1843 
1856  void push_back(utf32 code_point)
1857  {
1858  append(1, code_point);
1859  }
1860 
1876  String& append(const_iterator iter_beg, const_iterator iter_end)
1877  {
1878  return replace(end(), end(), iter_beg, iter_end);
1879  }
1880 
1881 
1894  String& operator+=(const char* cstr)
1895  {
1896  return append(cstr, strlen(cstr));
1897  }
1898 
1899 
1912  String& append(const char* cstr)
1913  {
1914  return append(cstr, strlen(cstr));
1915  }
1916 
1917 
1933  String& append(const char* chars, size_type chars_len)
1934  {
1935  if (chars_len == npos)
1936  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
1937 
1938  size_type newsz = d_cplength + chars_len;
1939 
1940  grow(newsz);
1941 
1942  utf32* pt = &ptr()[newsz-1];
1943 
1944  while(chars_len--)
1945  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
1946 
1947  setlen(newsz);
1948 
1949  return *this;
1950  }
1951 
1952 
1954  // Insertion Functions
1956 
1972  String& insert(size_type idx, const String& str)
1973  {
1974  return insert(idx, str, 0, npos);
1975  }
1976 
1999  String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
2000  {
2001  if ((d_cplength < idx) || (str.d_cplength < str_idx))
2002  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2003 
2004  if ((str_num == npos) || (str_num > str.d_cplength - str_idx))
2005  str_num = str.d_cplength - str_idx;
2006 
2007  size_type newsz = d_cplength + str_num;
2008  grow(newsz);
2009  memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2010  memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2011  setlen(newsz);
2012 
2013  return *this;
2014  }
2015 
2036  String& insert(size_type idx, const std::string& std_str)
2037  {
2038  return insert(idx, std_str, 0, npos);
2039  }
2040 
2067  String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
2068  {
2069  if (d_cplength < idx)
2070  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2071 
2072  if (std_str.size() < str_idx)
2073  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
2074 
2075  if ((str_num == npos) || (str_num > (size_type)std_str.size() - str_idx))
2076  str_num = (size_type)std_str.size() - str_idx;
2077 
2078  size_type newsz = d_cplength + str_num;
2079  grow(newsz);
2080 
2081  memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2082 
2083  utf32* pt = &ptr()[idx + str_num - 1];
2084 
2085  while(str_num--)
2086  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2087 
2088  setlen(newsz);
2089 
2090  return *this;
2091  }
2092 
2115  String& insert(size_type idx, const utf8* utf8_str)
2116  {
2117  return insert(idx, utf8_str, utf_length(utf8_str));
2118  }
2119 
2145  String& insert(size_type idx, const utf8* utf8_str, size_type len)
2146  {
2147  if (d_cplength < idx)
2148  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2149 
2150  if (len == npos)
2151  CEGUI_THROW(std::length_error("Length of utf8 encoded string can not be 'npos'"));
2152 
2153  size_type encsz = encoded_size(utf8_str, len);
2154  size_type newsz = d_cplength + encsz;
2155 
2156  grow(newsz);
2157  memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2158  encode(utf8_str, &ptr()[idx], encsz, len);
2159  setlen(newsz);
2160 
2161  return *this;
2162  }
2163 
2183  String& insert(size_type idx, size_type num, utf32 code_point)
2184  {
2185  if (d_cplength < idx)
2186  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2187 
2188  if (num == npos)
2189  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
2190 
2191  size_type newsz = d_cplength + num;
2192  grow(newsz);
2193 
2194  memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2195 
2196  utf32* pt = &ptr()[idx + num - 1];
2197 
2198  while(num--)
2199  *pt-- = code_point;
2200 
2201  setlen(newsz);
2202 
2203  return *this;
2204  }
2205 
2224  void insert(iterator pos, size_type num, utf32 code_point)
2225  {
2226  insert(safe_iter_dif(pos, begin()), num, code_point);
2227  }
2228 
2244  iterator insert(iterator pos, utf32 code_point)
2245  {
2246  insert(pos, 1, code_point);
2247  return pos;
2248  }
2249 
2268  void insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
2269  {
2270  replace(iter_pos, iter_pos, iter_beg, iter_end);
2271  }
2272 
2273 
2290  String& insert(size_type idx, const char* cstr)
2291  {
2292  return insert(idx, cstr, strlen(cstr));
2293  }
2294 
2295 
2315  String& insert(size_type idx, const char* chars, size_type chars_len)
2316  {
2317  if (d_cplength < idx)
2318  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2319 
2320  if (chars_len == npos)
2321  CEGUI_THROW(std::length_error("Length of char array can not be 'npos'"));
2322 
2323  size_type newsz = d_cplength + chars_len;
2324 
2325  grow(newsz);
2326  memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
2327 
2328  utf32* pt = &ptr()[idx + chars_len - 1];
2329 
2330  while(chars_len--)
2331  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
2332 
2333  setlen(newsz);
2334 
2335  return *this;
2336  }
2337 
2338 
2340  // Erasing characters
2342 
2349  void clear(void)
2350  {
2351  setlen(0);
2352  trim();
2353  }
2354 
2362  String& erase(void)
2363  {
2364  clear();
2365  return *this;
2366  }
2367 
2380  String& erase(size_type idx)
2381  {
2382  return erase(idx, 1);
2383  }
2384 
2400  String& erase(size_type idx, size_type len)
2401  {
2402  // cover the no-op case.
2403  if (len == 0)
2404  return *this;
2405 
2406  if (d_cplength <= idx)
2407  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2408 
2409  if (len == npos)
2410  len = d_cplength - idx;
2411 
2412  size_type newsz = d_cplength - len;
2413 
2414  memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
2415  setlen(newsz);
2416  return *this;
2417  }
2418 
2429  String& erase(iterator pos)
2430  {
2431  return erase(safe_iter_dif(pos, begin()), 1);
2432  }
2433 
2447  String& erase(iterator iter_beg, iterator iter_end)
2448  {
2449  return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
2450  }
2451 
2453  // Resizing
2455 
2467  void resize(size_type num)
2468  {
2469  resize(num, utf32());
2470  }
2471 
2487  void resize(size_type num, utf32 code_point)
2488  {
2489  if (num < d_cplength)
2490  {
2491  setlen(num);
2492  }
2493  else
2494  {
2495  append(num - d_cplength, code_point);
2496  }
2497 
2498  }
2499 
2501  // Replacing Characters
2503 
2522  String& replace(size_type idx, size_type len, const String& str)
2523  {
2524  return replace(idx, len, str, 0, npos);
2525  }
2526 
2548  String& replace(iterator iter_beg, iterator iter_end, const String& str)
2549  {
2550  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
2551  }
2552 
2578  String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
2579  {
2580  if ((d_cplength < idx) || (str.d_cplength < str_idx))
2581  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2582 
2583  if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
2584  str_num = str.d_cplength - str_idx;
2585 
2586  if (((len + idx) > d_cplength) || (len == npos))
2587  len = d_cplength - idx;
2588 
2589  size_type newsz = d_cplength + str_num - len;
2590 
2591  grow(newsz);
2592 
2593  if ((idx + len) < d_cplength)
2594  memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2595 
2596  memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
2597  setlen(newsz);
2598 
2599  return *this;
2600  }
2601 
2602 
2626  String& replace(size_type idx, size_type len, const std::string& std_str)
2627  {
2628  return replace(idx, len, std_str, 0, npos);
2629  }
2630 
2656  String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
2657  {
2658  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
2659  }
2660 
2690  String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
2691  {
2692  if (d_cplength < idx)
2693  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2694 
2695  if (std_str.size() < str_idx)
2696  CEGUI_THROW(std::out_of_range("Index is out of range for std::string"));
2697 
2698  if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
2699  str_num = (size_type)std_str.size() - str_idx;
2700 
2701  if (((len + idx) > d_cplength) || (len == npos))
2702  len = d_cplength - idx;
2703 
2704  size_type newsz = d_cplength + str_num - len;
2705 
2706  grow(newsz);
2707 
2708  if ((idx + len) < d_cplength)
2709  memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2710 
2711  utf32* pt = &ptr()[idx + str_num - 1];
2712 
2713  while (str_num--)
2714  *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
2715 
2716  setlen(newsz);
2717 
2718  return *this;
2719  }
2720 
2721 
2747  String& replace(size_type idx, size_type len, const utf8* utf8_str)
2748  {
2749  return replace(idx, len, utf8_str, utf_length(utf8_str));
2750  }
2751 
2779  String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
2780  {
2781  return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
2782  }
2783 
2812  String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
2813  {
2814  if (d_cplength < idx)
2815  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2816 
2817  if (str_len == npos)
2818  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
2819 
2820  if (((len + idx) > d_cplength) || (len == npos))
2821  len = d_cplength - idx;
2822 
2823  size_type encsz = encoded_size(utf8_str, str_len);
2824  size_type newsz = d_cplength + encsz - len;
2825 
2826  grow(newsz);
2827 
2828  if ((idx + len) < d_cplength)
2829  memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2830 
2831  encode(utf8_str, &ptr()[idx], encsz, str_len);
2832 
2833  setlen(newsz);
2834  return *this;
2835  }
2836 
2867  String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
2868  {
2869  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
2870  }
2871 
2894  String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
2895  {
2896  if (d_cplength < idx)
2897  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
2898 
2899  if (num == npos)
2900  CEGUI_THROW(std::length_error("Code point count can not be 'npos'"));
2901 
2902  if (((len + idx) > d_cplength) || (len == npos))
2903  len = d_cplength - idx;
2904 
2905  size_type newsz = d_cplength + num - len;
2906 
2907  grow(newsz);
2908 
2909  if ((idx + len) < d_cplength)
2910  memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2911 
2912  utf32* pt = &ptr()[idx + num - 1];
2913 
2914  while (num--)
2915  *pt-- = code_point;
2916 
2917  setlen(newsz);
2918 
2919  return *this;
2920  }
2921 
2946  String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
2947  {
2948  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
2949  }
2950 
2951 
2976  String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
2977  {
2978  if (iter_newBeg == iter_newEnd)
2979  {
2980  erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
2981  }
2982  else
2983  {
2984  size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
2985  size_type idx = safe_iter_dif(iter_beg, begin());
2986  size_type len = safe_iter_dif(iter_end, iter_beg);
2987 
2988  if ((len + idx) > d_cplength)
2989  len = d_cplength - idx;
2990 
2991  size_type newsz = d_cplength + str_len - len;
2992 
2993  grow(newsz);
2994 
2995  if ((idx + len) < d_cplength)
2996  memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
2997 
2998  memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
2999  setlen(newsz);
3000  }
3001 
3002  return *this;
3003  }
3004 
3005 
3025  String& replace(size_type idx, size_type len, const char* cstr)
3026  {
3027  return replace(idx, len, cstr, strlen(cstr));
3028  }
3029 
3030 
3052  String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
3053  {
3054  return replace(iter_beg, iter_end, cstr, strlen(cstr));
3055  }
3056 
3057 
3080  String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
3081  {
3082  if (d_cplength < idx)
3083  CEGUI_THROW(std::out_of_range("Index is out of range for CEGUI::String"));
3084 
3085  if (chars_len == npos)
3086  CEGUI_THROW(std::length_error("Length for the char array can not be 'npos'"));
3087 
3088  if (((len + idx) > d_cplength) || (len == npos))
3089  len = d_cplength - idx;
3090 
3091  size_type newsz = d_cplength + chars_len - len;
3092 
3093  grow(newsz);
3094 
3095  if ((idx + len) < d_cplength)
3096  memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
3097 
3098  utf32* pt = &ptr()[idx + chars_len - 1];
3099 
3100  while (chars_len--)
3101  *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
3102 
3103  setlen(newsz);
3104  return *this;
3105  }
3106 
3107 
3132  String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
3133  {
3134  return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
3135  }
3136 
3137 
3139  // Find a code point
3141 
3155  size_type find(utf32 code_point, size_type idx = 0) const
3156  {
3157  if (idx < d_cplength)
3158  {
3159  const utf32* pt = &ptr()[idx];
3160 
3161  while (idx < d_cplength)
3162  {
3163  if (*pt++ == code_point)
3164  return idx;
3165 
3166  ++idx;
3167  }
3168 
3169  }
3170 
3171  return npos;
3172  }
3173 
3188  size_type rfind(utf32 code_point, size_type idx = npos) const
3189  {
3190  if (idx >= d_cplength)
3191  idx = d_cplength - 1;
3192 
3193  if (d_cplength > 0)
3194  {
3195  const utf32* pt = &ptr()[idx];
3196 
3197  do
3198  {
3199  if (*pt-- == code_point)
3200  return idx;
3201 
3202  } while (idx-- != 0);
3203 
3204  }
3205 
3206  return npos;
3207  }
3208 
3210  // Find a substring
3212 
3226  size_type find(const String& str, size_type idx = 0) const
3227  {
3228  if ((str.d_cplength == 0) && (idx < d_cplength))
3229  return idx;
3230 
3231  if (idx < d_cplength)
3232  {
3233  // loop while search string could fit in to search area
3234  while (d_cplength - idx >= str.d_cplength)
3235  {
3236  if (0 == compare(idx, str.d_cplength, str))
3237  return idx;
3238 
3239  ++idx;
3240  }
3241 
3242  }
3243 
3244  return npos;
3245  }
3246 
3261  size_type rfind(const String& str, size_type idx = npos) const
3262  {
3263  if (str.d_cplength == 0)
3264  return (idx < d_cplength) ? idx : d_cplength;
3265 
3266  if (str.d_cplength <= d_cplength)
3267  {
3268  if (idx > (d_cplength - str.d_cplength))
3269  idx = d_cplength - str.d_cplength;
3270 
3271  do
3272  {
3273  if (0 == compare(idx, str.d_cplength, str))
3274  return idx;
3275 
3276  } while (idx-- != 0);
3277 
3278  }
3279 
3280  return npos;
3281  }
3282 
3301  size_type find(const std::string& std_str, size_type idx = 0) const
3302  {
3303  std::string::size_type sze = std_str.size();
3304 
3305  if ((sze == 0) && (idx < d_cplength))
3306  return idx;
3307 
3308  if (idx < d_cplength)
3309  {
3310  // loop while search string could fit in to search area
3311  while (d_cplength - idx >= sze)
3312  {
3313  if (0 == compare(idx, (size_type)sze, std_str))
3314  return idx;
3315 
3316  ++idx;
3317  }
3318 
3319  }
3320 
3321  return npos;
3322  }
3323 
3342  size_type rfind(const std::string& std_str, size_type idx = npos) const
3343  {
3344  std::string::size_type sze = std_str.size();
3345 
3346  if (sze == 0)
3347  return (idx < d_cplength) ? idx : d_cplength;
3348 
3349  if (sze <= d_cplength)
3350  {
3351  if (idx > (d_cplength - sze))
3352  idx = d_cplength - sze;
3353 
3354  do
3355  {
3356  if (0 == compare(idx, (size_type)sze, std_str))
3357  return idx;
3358 
3359  } while (idx-- != 0);
3360 
3361  }
3362 
3363  return npos;
3364  }
3365 
3388  size_type find(const utf8* utf8_str, size_type idx = 0) const
3389  {
3390  return find(utf8_str, idx, utf_length(utf8_str));
3391  }
3392 
3415  size_type rfind(const utf8* utf8_str, size_type idx = npos) const
3416  {
3417  return rfind(utf8_str, idx, utf_length(utf8_str));
3418  }
3419 
3445  size_type find(const utf8* utf8_str, size_type idx, size_type str_len) const
3446  {
3447  if (str_len == npos)
3448  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3449 
3450  size_type sze = encoded_size(utf8_str, str_len);
3451 
3452  if ((sze == 0) && (idx < d_cplength))
3453  return idx;
3454 
3455  if (idx < d_cplength)
3456  {
3457  // loop while search string could fit in to search area
3458  while (d_cplength - idx >= sze)
3459  {
3460  if (0 == compare(idx, sze, utf8_str, sze))
3461  return idx;
3462 
3463  ++idx;
3464  }
3465 
3466  }
3467 
3468  return npos;
3469  }
3470 
3496  size_type rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
3497  {
3498  if (str_len == npos)
3499  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3500 
3501  size_type sze = encoded_size(utf8_str, str_len);
3502 
3503  if (sze == 0)
3504  return (idx < d_cplength) ? idx : d_cplength;
3505 
3506  if (sze <= d_cplength)
3507  {
3508  if (idx > (d_cplength - sze))
3509  idx = d_cplength - sze;
3510 
3511  do
3512  {
3513  if (0 == compare(idx, sze, utf8_str, sze))
3514  return idx;
3515 
3516  } while (idx-- != 0);
3517 
3518  }
3519 
3520  return npos;
3521  }
3522 
3523 
3540  size_type find(const char* cstr, size_type idx = 0) const
3541  {
3542  return find(cstr, idx, strlen(cstr));
3543  }
3544 
3545 
3562  size_type rfind(const char* cstr, size_type idx = npos) const
3563  {
3564  return rfind(cstr, idx, strlen(cstr));
3565  }
3566 
3567 
3587  size_type find(const char* chars, size_type idx, size_type chars_len) const
3588  {
3589  if (chars_len == npos)
3590  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
3591 
3592  if ((chars_len == 0) && (idx < d_cplength))
3593  return idx;
3594 
3595  if (idx < d_cplength)
3596  {
3597  // loop while search string could fit in to search area
3598  while (d_cplength - idx >= chars_len)
3599  {
3600  if (0 == compare(idx, chars_len, chars, chars_len))
3601  return idx;
3602 
3603  ++idx;
3604  }
3605 
3606  }
3607 
3608  return npos;
3609  }
3610 
3611 
3631  size_type rfind(const char* chars, size_type idx, size_type chars_len) const
3632  {
3633  if (chars_len == npos)
3634  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
3635 
3636  if (chars_len == 0)
3637  return (idx < d_cplength) ? idx : d_cplength;
3638 
3639  if (chars_len <= d_cplength)
3640  {
3641  if (idx > (d_cplength - chars_len))
3642  idx = d_cplength - chars_len;
3643 
3644  do
3645  {
3646  if (0 == compare(idx, chars_len, chars, chars_len))
3647  return idx;
3648 
3649  } while (idx-- != 0);
3650 
3651  }
3652 
3653  return npos;
3654  }
3655 
3656 
3658  // Find first of different code-points
3660 
3674  size_type find_first_of(const String& str, size_type idx = 0) const
3675  {
3676  if (idx < d_cplength)
3677  {
3678  const utf32* pt = &ptr()[idx];
3679 
3680  do
3681  {
3682  if (npos != str.find(*pt++))
3683  return idx;
3684 
3685  } while (++idx != d_cplength);
3686 
3687  }
3688 
3689  return npos;
3690  }
3691 
3706  size_type find_first_not_of(const String& str, size_type idx = 0) const
3707  {
3708  if (idx < d_cplength)
3709  {
3710  const utf32* pt = &ptr()[idx];
3711 
3712  do
3713  {
3714  if (npos == str.find(*pt++))
3715  return idx;
3716 
3717  } while (++idx != d_cplength);
3718 
3719  }
3720 
3721  return npos;
3722  }
3723 
3724 
3743  size_type find_first_of(const std::string& std_str, size_type idx = 0) const
3744  {
3745  if (idx < d_cplength)
3746  {
3747  const utf32* pt = &ptr()[idx];
3748 
3749  do
3750  {
3751  if (npos != find_codepoint(std_str, *pt++))
3752  return idx;
3753 
3754  } while (++idx != d_cplength);
3755 
3756  }
3757 
3758  return npos;
3759  }
3760 
3779  size_type find_first_not_of(const std::string& std_str, size_type idx = 0) const
3780  {
3781  if (idx < d_cplength)
3782  {
3783  const utf32* pt = &ptr()[idx];
3784 
3785  do
3786  {
3787  if (npos == find_codepoint(std_str, *pt++))
3788  return idx;
3789 
3790  } while (++idx != d_cplength);
3791 
3792  }
3793 
3794  return npos;
3795  }
3796 
3797 
3820  size_type find_first_of(const utf8* utf8_str, size_type idx = 0) const
3821  {
3822  return find_first_of(utf8_str, idx, utf_length(utf8_str));
3823  }
3824 
3847  size_type find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
3848  {
3849  return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
3850  }
3851 
3877  size_type find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3878  {
3879  if (str_len == npos)
3880  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3881 
3882  if (idx < d_cplength)
3883  {
3884  size_type encsze = encoded_size(utf8_str, str_len);
3885 
3886  const utf32* pt = &ptr()[idx];
3887 
3888  do
3889  {
3890  if (npos != find_codepoint(utf8_str, encsze, *pt++))
3891  return idx;
3892 
3893  } while (++idx != d_cplength);
3894 
3895  }
3896 
3897  return npos;
3898  }
3899 
3925  size_type find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
3926  {
3927  if (str_len == npos)
3928  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
3929 
3930  if (idx < d_cplength)
3931  {
3932  size_type encsze = encoded_size(utf8_str, str_len);
3933 
3934  const utf32* pt = &ptr()[idx];
3935 
3936  do
3937  {
3938  if (npos == find_codepoint(utf8_str, encsze, *pt++))
3939  return idx;
3940 
3941  } while (++idx != d_cplength);
3942 
3943  }
3944 
3945  return npos;
3946  }
3947 
3948 
3963  size_type find_first_of(utf32 code_point, size_type idx = 0) const
3964  {
3965  return find(code_point, idx);
3966  }
3967 
3984  size_type find_first_not_of(utf32 code_point, size_type idx = 0) const
3985  {
3986  if (idx < d_cplength)
3987  {
3988  do
3989  {
3990  if ((*this)[idx] != code_point)
3991  return idx;
3992 
3993  } while(idx++ < d_cplength);
3994 
3995  }
3996 
3997  return npos;
3998  }
3999 
4000 
4017  size_type find_first_of(const char* cstr, size_type idx = 0) const
4018  {
4019  return find_first_of(cstr, idx, strlen(cstr));
4020  }
4021 
4022 
4039  size_type find_first_not_of(const char* cstr, size_type idx = 0) const
4040  {
4041  return find_first_not_of(cstr, idx, strlen(cstr));
4042  }
4043 
4044 
4064  size_type find_first_of(const char* chars, size_type idx, size_type chars_len) const
4065  {
4066  if (chars_len == npos)
4067  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4068 
4069  if (idx < d_cplength)
4070  {
4071  const utf32* pt = &ptr()[idx];
4072 
4073  do
4074  {
4075  if (npos != find_codepoint(chars, chars_len, *pt++))
4076  return idx;
4077 
4078  } while (++idx != d_cplength);
4079 
4080  }
4081 
4082  return npos;
4083  }
4084 
4085 
4105  size_type find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
4106  {
4107  if (chars_len == npos)
4108  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4109 
4110  if (idx < d_cplength)
4111  {
4112  const utf32* pt = &ptr()[idx];
4113 
4114  do
4115  {
4116  if (npos == find_codepoint(chars, chars_len, *pt++))
4117  return idx;
4118 
4119  } while (++idx != d_cplength);
4120 
4121  }
4122 
4123  return npos;
4124  }
4125 
4126 
4128  // Find last of different code-points
4130 
4144  size_type find_last_of(const String& str, size_type idx = npos) const
4145  {
4146  if (d_cplength > 0)
4147  {
4148  if (idx >= d_cplength)
4149  idx = d_cplength - 1;
4150 
4151  const utf32* pt = &ptr()[idx];
4152 
4153  do
4154  {
4155  if (npos != str.find(*pt--))
4156  return idx;
4157 
4158  } while (idx-- != 0);
4159 
4160  }
4161 
4162  return npos;
4163  }
4164 
4179  size_type find_last_not_of(const String& str, size_type idx = npos) const
4180  {
4181  if (d_cplength > 0)
4182  {
4183  if (idx >= d_cplength)
4184  idx = d_cplength - 1;
4185 
4186  const utf32* pt = &ptr()[idx];
4187 
4188  do
4189  {
4190  if (npos == str.find(*pt--))
4191  return idx;
4192 
4193  } while (idx-- != 0);
4194 
4195  }
4196 
4197  return npos;
4198  }
4199 
4200 
4219  size_type find_last_of(const std::string& std_str, size_type idx = npos) const
4220  {
4221  if (d_cplength > 0)
4222  {
4223  if (idx >= d_cplength)
4224  idx = d_cplength - 1;
4225 
4226  const utf32* pt = &ptr()[idx];
4227 
4228  do
4229  {
4230  if (npos != find_codepoint(std_str, *pt--))
4231  return idx;
4232 
4233  } while (idx-- != 0);
4234 
4235  }
4236 
4237  return npos;
4238  }
4239 
4258  size_type find_last_not_of(const std::string& std_str, size_type idx = npos) const
4259  {
4260  if (d_cplength > 0)
4261  {
4262  if (idx >= d_cplength)
4263  idx = d_cplength - 1;
4264 
4265  const utf32* pt = &ptr()[idx];
4266 
4267  do
4268  {
4269  if (npos == find_codepoint(std_str, *pt--))
4270  return idx;
4271 
4272  } while (idx-- != 0);
4273 
4274  }
4275 
4276  return npos;
4277  }
4278 
4279 
4302  size_type find_last_of(const utf8* utf8_str, size_type idx = npos) const
4303  {
4304  return find_last_of(utf8_str, idx, utf_length(utf8_str));
4305  }
4306 
4329  size_type find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
4330  {
4331  return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
4332  }
4333 
4359  size_type find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4360  {
4361  if (str_len == npos)
4362  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
4363 
4364  if (d_cplength > 0)
4365  {
4366  if (idx >= d_cplength)
4367  idx = d_cplength - 1;
4368 
4369  size_type encsze = encoded_size(utf8_str, str_len);
4370 
4371  const utf32* pt = &ptr()[idx];
4372 
4373  do
4374  {
4375  if (npos != find_codepoint(utf8_str, encsze, *pt--))
4376  return idx;
4377 
4378  } while (idx-- != 0);
4379 
4380  }
4381 
4382  return npos;
4383  }
4384 
4410  size_type find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
4411  {
4412  if (str_len == npos)
4413  CEGUI_THROW(std::length_error("Length for utf8 encoded string can not be 'npos'"));
4414 
4415  if (d_cplength > 0)
4416  {
4417  if (idx >= d_cplength)
4418  idx = d_cplength - 1;
4419 
4420  size_type encsze = encoded_size(utf8_str, str_len);
4421 
4422  const utf32* pt = &ptr()[idx];
4423 
4424  do
4425  {
4426  if (npos == find_codepoint(utf8_str, encsze, *pt--))
4427  return idx;
4428 
4429  } while (idx-- != 0);
4430 
4431  }
4432 
4433  return npos;
4434  }
4435 
4436 
4451  size_type find_last_of(utf32 code_point, size_type idx = npos) const
4452  {
4453  return rfind(code_point, idx);
4454  }
4455 
4470  size_type find_last_not_of(utf32 code_point, size_type idx = npos) const
4471  {
4472  if (d_cplength > 0)
4473  {
4474  if (idx >= d_cplength)
4475  idx = d_cplength - 1;
4476 
4477  do
4478  {
4479  if ((*this)[idx] != code_point)
4480  return idx;
4481 
4482  } while(idx-- != 0);
4483 
4484  }
4485 
4486  return npos;
4487  }
4488 
4489 
4506  size_type find_last_of(const char* cstr, size_type idx = npos) const
4507  {
4508  return find_last_of(cstr, idx, strlen(cstr));
4509  }
4510 
4511 
4528  size_type find_last_not_of(const char* cstr, size_type idx = npos) const
4529  {
4530  return find_last_not_of(cstr, idx, strlen(cstr));
4531  }
4532 
4533 
4553  size_type find_last_of(const char* chars, size_type idx, size_type chars_len) const
4554  {
4555  if (chars_len == npos)
4556  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4557 
4558  if (d_cplength > 0)
4559  {
4560  if (idx >= d_cplength)
4561  idx = d_cplength - 1;
4562 
4563  const utf32* pt = &ptr()[idx];
4564 
4565  do
4566  {
4567  if (npos != find_codepoint(chars, chars_len, *pt--))
4568  return idx;
4569 
4570  } while (idx-- != 0);
4571 
4572  }
4573 
4574  return npos;
4575  }
4576 
4577 
4597  size_type find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
4598  {
4599  if (chars_len == npos)
4600  CEGUI_THROW(std::length_error("Length for char array can not be 'npos'"));
4601 
4602  if (d_cplength > 0)
4603  {
4604  if (idx >= d_cplength)
4605  idx = d_cplength - 1;
4606 
4607  const utf32* pt = &ptr()[idx];
4608 
4609  do
4610  {
4611  if (npos == find_codepoint(chars, chars_len, *pt--))
4612  return idx;
4613 
4614  } while (idx-- != 0);
4615 
4616  }
4617 
4618  return npos;
4619  }
4620 
4621 
4623  // Substring
4625 
4640  String substr(size_type idx = 0, size_type len = npos) const
4641  {
4642  if (d_cplength < idx)
4643  CEGUI_THROW(std::out_of_range("Index is out of range for this CEGUI::String"));
4644 
4645  return String(*this, idx, len);
4646  }
4647 
4649  // Iterator creation
4651 
4658  iterator begin(void)
4659  {
4660  return iterator(ptr());
4661  }
4662 
4670  const_iterator begin(void) const
4671  {
4672  return const_iterator(ptr());
4673  }
4674 
4682  iterator end(void)
4683  {
4684  return iterator(&ptr()[d_cplength]);
4685  }
4686 
4694  const_iterator end(void) const
4695  {
4696  return const_iterator(&ptr()[d_cplength]);
4697  }
4698 
4706  reverse_iterator rbegin(void)
4707  {
4708  return reverse_iterator(end());
4709  }
4710 
4718  const_reverse_iterator rbegin(void) const
4719  {
4720  return const_reverse_iterator(end());
4721  }
4722 
4730  reverse_iterator rend(void)
4731  {
4732  return reverse_iterator(begin());
4733  }
4734 
4742  const_reverse_iterator rend(void) const
4743  {
4744  return const_reverse_iterator(begin());
4745  }
4746 
4747 private:
4748  /*************************************************************************
4749  Implementation Functions
4750  *************************************************************************/
4751  // string management
4752 
4753  // change size of allocated buffer so it is at least 'new_size'.
4754  // May or may not cause re-allocation and copy of buffer if size is larger
4755  // will never re-allocate to make size smaller. (see trim())
4756  bool grow(size_type new_size);
4757 
4758  // perform re-allocation to remove wasted space.
4759  void trim(void);
4760 
4761  // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
4762  void setlen(size_type len)
4763  {
4764  d_cplength = len;
4765  ptr()[len] = (utf32)(0);
4766  }
4767 
4768  // initialise string object
4769  void init(void)
4770  {
4771  d_reserve = CEGUI_STR_QUICKBUFF_SIZE;
4772  d_encodedbuff = 0;
4773  d_encodedbufflen = 0;
4774  d_encodeddatlen = 0;
4775  d_buffer = 0;
4776  setlen(0);
4777  }
4778 
4779  // return true if the given pointer is inside the string data
4780  bool inside(utf32* inptr)
4781  {
4782  if (inptr < ptr() || ptr() + d_cplength <= inptr)
4783  return false;
4784  else
4785  return true;
4786  }
4787 
4788  // compute distance between two iterators, returning a 'safe' value
4789  size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
4790  {
4791  return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
4792  }
4793 
4794  // encoding functions
4795  // for all:
4796  // src_len is in code units, or 0 for null terminated string.
4797  // dest_len is in code units.
4798  // returns number of code units put into dest buffer.
4799  size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
4800  {
4801  // count length for null terminated source...
4802  if (src_len == 0)
4803  {
4804  src_len = utf_length(src);
4805  }
4806 
4807  size_type destCapacity = dest_len;
4808 
4809  // while there is data in the source buffer,
4810  for (uint idx = 0; idx < src_len; ++idx)
4811  {
4812  utf32 cp = src[idx];
4813 
4814  // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
4815  if (destCapacity < encoded_size(cp))
4816  {
4817  break;
4818  }
4819 
4820  if (cp < 0x80)
4821  {
4822  *dest++ = (utf8)cp;
4823  --destCapacity;
4824  }
4825  else if (cp < 0x0800)
4826  {
4827  *dest++ = (utf8)((cp >> 6) | 0xC0);
4828  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4829  destCapacity -= 2;
4830  }
4831  else if (cp < 0x10000)
4832  {
4833  *dest++ = (utf8)((cp >> 12) | 0xE0);
4834  *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4835  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4836  destCapacity -= 3;
4837  }
4838  else
4839  {
4840  *dest++ = (utf8)((cp >> 18) | 0xF0);
4841  *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
4842  *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
4843  *dest++ = (utf8)((cp & 0x3F) | 0x80);
4844  destCapacity -= 4;
4845  }
4846 
4847  }
4848 
4849  return dest_len - destCapacity;
4850  }
4851 
4852  size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
4853  {
4854  // count length for null terminated source...
4855  if (src_len == 0)
4856  {
4857  src_len = utf_length(src);
4858  }
4859 
4860  size_type destCapacity = dest_len;
4861 
4862  // while there is data in the source buffer, and space in the dest buffer
4863  for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
4864  {
4865  utf32 cp;
4866  utf8 cu = src[idx++];
4867 
4868  if (cu < 0x80)
4869  {
4870  cp = (utf32)(cu);
4871  }
4872  else if (cu < 0xE0)
4873  {
4874  cp = ((cu & 0x1F) << 6);
4875  cp |= (src[idx++] & 0x3F);
4876  }
4877  else if (cu < 0xF0)
4878  {
4879  cp = ((cu & 0x0F) << 12);
4880  cp |= ((src[idx++] & 0x3F) << 6);
4881  cp |= (src[idx++] & 0x3F);
4882  }
4883  else
4884  {
4885  cp = ((cu & 0x07) << 18);
4886  cp |= ((src[idx++] & 0x3F) << 12);
4887  cp |= ((src[idx++] & 0x3F) << 6);
4888  cp |= (src[idx++] & 0x3F);
4889  }
4890 
4891  *dest++ = cp;
4892  --destCapacity;
4893  }
4894 
4895  return dest_len - destCapacity;
4896  }
4897 
4898  // return the number of utf8 code units required to encode the given utf32 code point
4899  size_type encoded_size(utf32 code_point) const
4900  {
4901  if (code_point < 0x80)
4902  return 1;
4903  else if (code_point < 0x0800)
4904  return 2;
4905  else if (code_point < 0x10000)
4906  return 3;
4907  else
4908  return 4;
4909  }
4910 
4911  // return number of code units required to re-encode given null-terminated utf32 data as utf8. return does not include terminating null.
4912  size_type encoded_size(const utf32* buf) const
4913  {
4914  return encoded_size(buf, utf_length(buf));
4915  }
4916 
4917  // return number of code units required to re-encode given utf32 data as utf8. len is number of code units in 'buf'.
4918  size_type encoded_size(const utf32* buf, size_type len) const
4919  {
4920  size_type count = 0;
4921 
4922  while (len--)
4923  {
4924  count += encoded_size(*buf++);
4925  }
4926 
4927  return count;
4928  }
4929 
4930  // return number of utf32 code units required to re-encode given utf8 data as utf32. return does not include terminating null.
4931  size_type encoded_size(const utf8* buf) const
4932  {
4933  return encoded_size(buf, utf_length(buf));
4934  }
4935 
4936  // return number of utf32 code units required to re-encode given utf8 data as utf32. len is number of code units in 'buf'.
4937  size_type encoded_size(const utf8* buf, size_type len) const
4938  {
4939  utf8 tcp;
4940  size_type count = 0;
4941 
4942  while (len--)
4943  {
4944  tcp = *buf++;
4945  ++count;
4946  size_type size = 0;
4947 
4948  if (tcp < 0x80)
4949  {
4950  }
4951  else if (tcp < 0xE0)
4952  {
4953  size = 1;
4954  ++buf;
4955  }
4956  else if (tcp < 0xF0)
4957  {
4958  size = 2;
4959  buf += 2;
4960  }
4961  else
4962  {
4963  size = 3;
4964  buf += 3;
4965  }
4966 
4967  if (len >= size)
4968  len -= size;
4969  else
4970  break;
4971  }
4972 
4973  return count;
4974  }
4975 
4976  // return number of code units in a null terminated string
4977  size_type utf_length(const utf8* utf8_str) const
4978  {
4979  size_type cnt = 0;
4980  while (*utf8_str++)
4981  cnt++;
4982 
4983  return cnt;
4984  }
4985 
4986  // return number of code units in a null terminated string
4987  size_type utf_length(const utf32* utf32_str) const
4988  {
4989  size_type cnt = 0;
4990  while (*utf32_str++)
4991  cnt++;
4992 
4993  return cnt;
4994  }
4995 
4996  // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
4997  utf8* build_utf8_buff(void) const;
4998 
4999  // compare two utf32 buffers
5000  int utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
5001  {
5002  if (!cp_count)
5003  return 0;
5004 
5005  while ((--cp_count) && (*buf1 == *buf2))
5006  buf1++, buf2++;
5007 
5008  return *buf1 - *buf2;
5009  }
5010 
5011  // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
5012  int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
5013  {
5014  if (!cp_count)
5015  return 0;
5016 
5017  while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
5018  buf1++, buf2++;
5019 
5020  return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
5021  }
5022 
5023  // compare utf32 buffer with encoded utf8 data
5024  int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
5025  {
5026  if (!cp_count)
5027  return 0;
5028 
5029  utf32 cp;
5030  utf8 cu;
5031 
5032  do
5033  {
5034  cu = *buf2++;
5035 
5036  if (cu < 0x80)
5037  {
5038  cp = (utf32)(cu);
5039  }
5040  else if (cu < 0xE0)
5041  {
5042  cp = ((cu & 0x1F) << 6);
5043  cp |= (*buf2++ & 0x3F);
5044  }
5045  else if (cu < 0xF0)
5046  {
5047  cp = ((cu & 0x0F) << 12);
5048  cp |= ((*buf2++ & 0x3F) << 6);
5049  cp |= (*buf2++ & 0x3F);
5050  }
5051  else
5052  {
5053  cp = ((cu & 0x07) << 18);
5054  cp |= ((*buf2++ & 0x3F) << 12);
5055  cp |= ((*buf2++ & 0x3F) << 6);
5056  cp |= (*buf2++ & 0x3F);
5057  }
5058 
5059  } while ((*buf1++ == cp) && (--cp_count));
5060 
5061  return (*--buf1) - cp;
5062  }
5063 
5064  // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
5065  size_type find_codepoint(const std::string& str, utf32 code_point) const
5066  {
5067  size_type idx = 0, sze = (size_type)str.size();
5068 
5069  while (idx != sze)
5070  {
5071  if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
5072  return idx;
5073 
5074  ++idx;
5075  }
5076 
5077  return npos;
5078  }
5079 
5080  // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none. len is in code points.
5081  size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const
5082  {
5083  size_type idx = 0;
5084 
5085  utf32 cp;
5086  utf8 cu;
5087 
5088  while (idx != len) {
5089  cu = *str++;
5090 
5091  if (cu < 0x80)
5092  {
5093  cp = (utf32)(cu);
5094  }
5095  else if (cu < 0xE0)
5096  {
5097  cp = ((cu & 0x1F) << 6);
5098  cp |= (*str++ & 0x3F);
5099  }
5100  else if (cu < 0xF0)
5101  {
5102  cp = ((cu & 0x0F) << 12);
5103  cp |= ((*str++ & 0x3F) << 6);
5104  cp |= (*str++ & 0x3F);
5105  }
5106  else
5107  {
5108  cp = ((cu & 0x07) << 18);
5109  cp |= ((*str++ & 0x3F) << 12);
5110  cp |= ((*str++ & 0x3F) << 6);
5111  cp |= (*str++ & 0x3F);
5112  }
5113 
5114  if (code_point == cp)
5115  return idx;
5116 
5117  ++idx;
5118  }
5119 
5120  return npos;
5121  }
5122 
5123 
5124  // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
5125  size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
5126  {
5127  for (size_type idx = 0; idx != chars_len; ++idx)
5128  {
5129  if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
5130  return idx;
5131  }
5132 
5133  return npos;
5134  }
5135 
5136 };
5137 
5138 
5140 // Comparison operators
5142 
5146 bool CEGUIEXPORT operator==(const String& str1, const String& str2);
5147 
5152 bool CEGUIEXPORT operator==(const String& str, const std::string& std_str);
5153 
5158 bool CEGUIEXPORT operator==(const std::string& std_str, const String& str);
5159 
5164 bool CEGUIEXPORT operator==(const String& str, const utf8* utf8_str);
5165 
5170 bool CEGUIEXPORT operator==(const utf8* utf8_str, const String& str);
5171 
5176 bool CEGUIEXPORT operator!=(const String& str1, const String& str2);
5177 
5182 bool CEGUIEXPORT operator!=(const String& str, const std::string& std_str);
5183 
5188 bool CEGUIEXPORT operator!=(const std::string& std_str, const String& str);
5189 
5194 bool CEGUIEXPORT operator!=(const String& str, const utf8* utf8_str);
5195 
5200 bool CEGUIEXPORT operator!=(const utf8* utf8_str, const String& str);
5201 
5206 bool CEGUIEXPORT operator<(const String& str1, const String& str2);
5207 
5212 bool CEGUIEXPORT operator<(const String& str, const std::string& std_str);
5213 
5218 bool CEGUIEXPORT operator<(const std::string& std_str, const String& str);
5219 
5224 bool CEGUIEXPORT operator<(const String& str, const utf8* utf8_str);
5225 
5230 bool CEGUIEXPORT operator<(const utf8* utf8_str, const String& str);
5231 
5236 bool CEGUIEXPORT operator>(const String& str1, const String& str2);
5237 
5242 bool CEGUIEXPORT operator>(const String& str, const std::string& std_str);
5243 
5248 bool CEGUIEXPORT operator>(const std::string& std_str, const String& str);
5249 
5254 bool CEGUIEXPORT operator>(const String& str, const utf8* utf8_str);
5255 
5260 bool CEGUIEXPORT operator>(const utf8* utf8_str, const String& str);
5261 
5266 bool CEGUIEXPORT operator<=(const String& str1, const String& str2);
5267 
5272 bool CEGUIEXPORT operator<=(const String& str, const std::string& std_str);
5273 
5278 bool CEGUIEXPORT operator<=(const std::string& std_str, const String& str);
5279 
5284 bool CEGUIEXPORT operator<=(const String& str, const utf8* utf8_str);
5285 
5290 bool CEGUIEXPORT operator<=(const utf8* utf8_str, const String& str);
5291 
5296 bool CEGUIEXPORT operator>=(const String& str1, const String& str2);
5297 
5302 bool CEGUIEXPORT operator>=(const String& str, const std::string& std_str);
5303 
5308 bool CEGUIEXPORT operator>=(const std::string& std_str, const String& str);
5309 
5314 bool CEGUIEXPORT operator>=(const String& str, const utf8* utf8_str);
5315 
5320 bool CEGUIEXPORT operator>=(const utf8* utf8_str, const String& str);
5321 
5326 bool CEGUIEXPORT operator==(const String& str, const char* c_str);
5327 
5332 bool CEGUIEXPORT operator==(const char* c_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 
5395 // Concatenation operator functions
5397 
5412 String CEGUIEXPORT operator+(const String& str1, const String& str2);
5413 
5429 String CEGUIEXPORT operator+(const String& str, const std::string& std_str);
5430 
5446 String CEGUIEXPORT operator+(const std::string& std_str, const String& str);
5447 
5463 String CEGUIEXPORT operator+(const String& str, const utf8* utf8_str);
5464 
5480 String CEGUIEXPORT operator+(const utf8* utf8_str, const String& str);
5481 
5497 String CEGUIEXPORT operator+(const String& str, utf32 code_point);
5498 
5514 String CEGUIEXPORT operator+(utf32 code_point, const String& str);
5515 
5531 String CEGUIEXPORT operator+(const String& str, const char* c_str);
5532 
5548 String CEGUIEXPORT operator+(const char* c_str, const String& str);
5549 
5550 
5552 // Output (stream) functions
5554 CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
5555 
5556 
5558 // Modifying operations
5560 
5573 void CEGUIEXPORT swap(String& str1, String& str2);
5574 
5581 {
5582  bool operator() (const String& a, const String& b) const
5583  {
5584  const size_t la = a.length();
5585  const size_t lb = b.length();
5586  if (la == lb)
5587  return (memcmp(a.ptr(), b.ptr(), la * sizeof(utf32)) < 0);
5588 
5589  return (la < lb);
5590  }
5591 };
5592 
5593 #else
5594 
5596 typedef char encoded_char;
5597 
5598 #if CEGUI_STRING_CLASS == CEGUI_STRING_CLASS_STD
5599 
5600 typedef std::string String;
5601 
5602 #else // CEGUI_STRING_CLASS_STD_AO
5603 
5604 typedef std::basic_string<char, std::char_traits<char>, STLAllocatorWrapper<char, AllocatorConfig<STLAllocator>::Allocator> > String;
5605 
5606 #endif
5607 
5613 struct StringFastLessCompare
5614 {
5615  bool operator() (const String& a, const String& b) const
5616  {
5617  const size_t la = a.length();
5618  const size_t lb = b.length();
5619  if (la == lb)
5620  return (memcmp(a.c_str(), b.c_str(), la * sizeof(String::value_type)) < 0);
5621 
5622  return (la < lb);
5623  }
5624 };
5625 
5626 #if defined(_MSC_VER)
5627 # pragma warning(disable : 4251)
5628 #endif
5629 
5630 #endif
5631 
5632 } // End of CEGUI namespace section
5633 
5634 
5635 #endif // end of guard _CEGUIString_h_