1 // Modified from OpenGUI under lenient license
2 // Original copyright details and licensing below:
3 // OpenGUI (http://opengui.sourceforge.net)
4 // This source code is released under the BSD License
5 
6 // Permission is given to the MyGUI project to use the contents of file within its
7 // source and binary applications, as well as any derivative works, in accordance
8 // with the terms of any license under which MyGUI is or will be distributed.
9 //
10 // MyGUI may relicense its copy of this file, as well as any OpenGUI released updates
11 // to this file, under any terms that it deems fit, and is not required to maintain
12 // the original BSD licensing terms of this file, however OpenGUI retains the right
13 // to present its copy of this file under the terms of any license under which
14 // OpenGUI is distributed.
15 //
16 // MyGUI is not required to release to OpenGUI any future changes that it makes to
17 // this file, and understands and agrees that any such changes that are released
18 // back to OpenGUI will become available under the terms of any license under which
19 // OpenGUI is distributed.
20 //
21 // For brevity, this permission text may be removed from this file if desired.
22 // The original record kept within the SourceForge (http://sourceforge.net/) tracker
23 // is sufficient.
24 //
25 // - Eric Shorkey (zero/zeroskill) <opengui@rightbracket.com> [January 20th, 2007]
26 
27 #ifndef MYGUI_U_STRING_H_
28 #define MYGUI_U_STRING_H_
29 
30 
31 #include "MyGUI_Prerequest.h"
32 #include "MyGUI_Types.h"
33 
34 // these are explained later
35 #include <iterator>
36 #include <string>
37 #include <stdexcept>
38 
39 #if MYGUI_COMPILER == MYGUI_COMPILER_MSVC
40 // disable: warning C4275: non dll-interface class '***' used as base for dll-interface clas '***'
41 #	pragma warning (push)
42 #	pragma warning (disable : 4275)
43 #endif
44 
45 // Workaround for VC7:
46 //      when build with /MD or /MDd, VC7 have both std::basic_string<unsigned short> and
47 // basic_string<__wchar_t> instantiated in msvcprt[d].lib/MSVCP71[D].dll, but the header
48 // files tells compiler that only one of them is over there (based on /Zc:wchar_t compile
49 // option). And since this file used both of them, causing compiler instantiating another
50 // one in user object code, which lead to duplicate symbols with msvcprt.lib/MSVCP71[D].dll.
51 //
52 #if MYGUI_COMPILER == MYGUI_COMPILER_MSVC && (1300 <= MYGUI_COMP_VER && MYGUI_COMP_VER <= 1310)
53 
54 # if defined(_DLL_CPPLIB)
55 
56 namespace std
57 {
58     template class _CRTIMP2 basic_string<unsigned short, char_traits<unsigned short>,
59 	    allocator<unsigned short> >;
60 
61     template class _CRTIMP2 basic_string<__wchar_t, char_traits<__wchar_t>,
62 	    allocator<__wchar_t> >;
63 }
64 
65 # endif // defined(_DLL_CPPLIB)
66 
67 #endif  // MYGUI_COMPILER == MYGUI_COMPILER_MSVC && MYGUI_COMP_VER == 1300
68 
69 
70 namespace MyGUI
71 {
72 
73 	/* READ THIS NOTICE BEFORE USING IN YOUR OWN APPLICATIONS
74 	=NOTICE=
75 	This class is not a complete Unicode solution. It purposefully does not
76 	provide certain functionality, such as proper lexical sorting for
77 	Unicode values. It does provide comparison operators for the sole purpose
78 	of using UString as an index with std::map and other operator< sorted
79 	containers, but it should NOT be relied upon for meaningful lexical
80 	operations, such as alphabetical sorts. If you need this type of
81 	functionality, look into using ICU instead (http://icu.sourceforge.net/).
82 
83 	=REQUIREMENTS=
84 	There are a few requirements for proper operation. They are fairly small,
85 	and shouldn't restrict usage on any reasonable target.
86 	* Compiler must support unsigned 16-bit integer types
87 	* Compiler must support signed 32-bit integer types
88 	* wchar_t must be either UTF-16 or UTF-32 encoding, and specified as such
89 	    using the WCHAR_UTF16 macro as outlined below.
90 	* You must include <iterator>, <string>, and <wchar>. Probably more, but
91 	    these are the most obvious.
92 
93 	=REQUIRED PREPROCESSOR MACROS=
94 	This class requires two preprocessor macros to be defined in order to
95 	work as advertised.
96 	INT32 - must be mapped to a signed 32 bit integer (ex. #define INT32 int)
97 	UINT16 - must be mapped to an unsigned 16 bit integer (ex. #define UINT32 unsigned short)
98 
99 	Additionally, a third macro should be defined to control the evaluation of wchar_t:
100 	WCHAR_UTF16 - should be defined when wchar_t represents UTF-16 code points,
101 	    such as in Windows. Otherwise it is assumed that wchar_t is a 32-bit
102 		integer representing UTF-32 code points.
103 	*/
104 
105 	// THIS IS A VERY BRIEF AUTO DETECTION. YOU MAY NEED TO TWEAK THIS
106 #ifdef __STDC_ISO_10646__
107 // for any compiler that provides this, wchar_t is guaranteed to hold any Unicode value with a single code point (32-bit or larger)
108 // so we can safely skip the rest of the testing
109 #else // #ifdef __STDC_ISO_10646__
110 #if defined( __WIN32__ ) || defined( _WIN32 )
111 #define WCHAR_UTF16 // All currently known Windows platforms utilize UTF-16 encoding in wchar_t
112 #else // #if defined( __WIN32__ ) || defined( _WIN32 )
113 #if MYGUI_COMPILER != MYGUI_COMPILER_GCCE
114 #if WCHAR_MAX <= 0xFFFF // this is a last resort fall back test; WCHAR_MAX is defined in <wchar.h>
115 #define WCHAR_UTF16 // best we can tell, wchar_t is not larger than 16-bit
116 #endif // #if WCHAR_MAX <= 0xFFFF
117 #endif
118 #endif // #if defined( __WIN32__ ) || defined( _WIN32 )
119 #endif // #ifdef __STDC_ISO_10646__
120 
121 
122 // MYGUI_IS_NATIVE_WCHAR_T means that wchar_t isn't a typedef of
123 // uint16_t or uint32_t.
124 #if MYGUI_COMPILER == MYGUI_COMPILER_MSVC
125 
126 // Don't define wchar_t related functions since it'll duplicate
127 // with UString::code_point related functions when compile
128 // without /Zc:wchar_t, because in this case both of them are
129 // a typedef of uint16_t.
130 # if defined(_NATIVE_WCHAR_T_DEFINED)
131 #   define MYGUI_IS_NATIVE_WCHAR_T      1
132 # else
133 #   define MYGUI_IS_NATIVE_WCHAR_T      0
134 # endif
135 #else   // MYGUI_COMPILER != MYGUI_COMPILER_MSVC
136 
137 // Assumed wchar_t is natively for other compilers
138 #   define MYGUI_IS_NATIVE_WCHAR_T     1
139 
140 #endif  // MYGUI_COMPILER == MYGUI_COMPILER_MSVC
141 
142 	//! A UTF-16 string with implicit conversion to/from std::string and std::wstring
143 	/*! This class provides a complete 1 to 1 map of most std::string functions (at least to my
144 	knowledge). Implicit conversions allow this string class to work with all common C++ string
145 	formats, with specialty functions defined where implicit conversion would cause potential
146 	problems or is otherwise unavailable.
147 
148 	Some additional functionality is present to assist in working with characters using the
149 	32-bit UTF-32 encoding. (Which is guaranteed to fit any Unicode character into a single
150 	code point.) \b Note: Reverse iterators do not have this functionality due to the
151 	ambiguity that surrounds working with UTF-16 in reverse. (Such as, where should an
152 	iterator point to represent the beginning of a surrogate pair?)
153 
154 
155 	\par Supported Input Types
156 	The supported string types for input, and their assumed encoding schemes, are:
157 	- std::string (UTF-8)
158 	- char* (UTF-8)
159 	- std::wstring (autodetected UTF-16 / UTF-32 based on compiler)
160 	- wchar_t* (autodetected UTF-16 / UTF-32 based on compiler)
161 
162 
163 	\see
164 	- For additional information on UTF-16 encoding: http://en.wikipedia.org/wiki/UTF-16
165 	- For additional information on UTF-8 encoding: http://en.wikipedia.org/wiki/UTF-8
166 	- For additional information on UTF-32 encoding: http://en.wikipedia.org/wiki/UTF-32
167 	*/
168 	class MYGUI_EXPORT UString {
169 		// constants used in UTF-8 conversions
170 		static const unsigned char _lead1 = 0xC0;      //110xxxxx
171 		static const unsigned char _lead1_mask = 0x1F; //00011111
172 		static const unsigned char _lead2 = 0xE0;      //1110xxxx
173 		static const unsigned char _lead2_mask = 0x0F; //00001111
174 		static const unsigned char _lead3 = 0xF0;      //11110xxx
175 		static const unsigned char _lead3_mask = 0x07; //00000111
176 		static const unsigned char _lead4 = 0xF8;      //111110xx
177 		static const unsigned char _lead4_mask = 0x03; //00000011
178 		static const unsigned char _lead5 = 0xFC;      //1111110x
179 		static const unsigned char _lead5_mask = 0x01; //00000001
180 		static const unsigned char _cont = 0x80;       //10xxxxxx
181 		static const unsigned char _cont_mask = 0x3F;  //00111111
182 
183 	public:
184 		//! size type used to indicate string size and character positions within the string
185 		using size_type = size_t;
186 		//! the usual constant representing: not found, no limit, etc
187 		static const size_type npos = static_cast<size_type>(~0);
188 
189 		//! a single 32-bit Unicode character
190 		using unicode_char = uint32;
191 
192 		//! a single UTF-16 code point
193 		using code_point = uint16;
194 
195 		//! value type typedef for use in iterators
196 		using value_type = code_point;
197 
198 		using dstring = std::basic_string<code_point>; // data string
199 
200 		//! string type used for returning UTF-32 formatted data
201 		using utf32string = std::basic_string<unicode_char>;
202 
203 		//! This exception is used when invalid data streams are encountered
204 	class MYGUI_EXPORT invalid_data: public std::runtime_error { /* i don't know why the beautifier is freaking out on this line */
205 		public:
206 			//! constructor takes a string message that can be later retrieved by the what() function
invalid_data(const std::string & _Message)207 			explicit invalid_data( const std::string& _Message ): std::runtime_error( _Message ) {
208 				/* The thing is, Bob, it's not that I'm lazy, it's that I just don't care. */
209 			}
210 		};
211 
212 		//#########################################################################
213 		//! base iterator class for UString
214 	class MYGUI_EXPORT _base_iterator
215 	{
216 			friend class UString;
217 		protected:
218 			typedef ptrdiff_t difference_type;
219 
220 			_base_iterator();
221 
222 			void _seekFwd( size_type c );
223 			void _seekRev( size_type c );
224 			void _become( const _base_iterator& i );
225 			bool _test_begin() const;
226 			bool _test_end() const;
227 			size_type _get_index() const;
228 			void _jump_to( size_type index );
229 
230 			unicode_char _getCharacter() const;
231 			int _setCharacter( unicode_char uc );
232 
233 			void _moveNext();
234 			void _movePrev();
235 
236 			dstring::iterator mIter;
237 			UString* mString;
238 		};
239 
240 		//#########################################################################
241 		// FORWARD ITERATORS
242 		//#########################################################################
243 		class _const_fwd_iterator; // forward declaration
244 
245 		//! forward iterator for UString
246 	class MYGUI_EXPORT _fwd_iterator: public _base_iterator
247 	{
248 			friend class _const_fwd_iterator;
249 		public:
250 			_fwd_iterator();
251 			_fwd_iterator( const _fwd_iterator& i );
252 			_fwd_iterator& operator=( const _fwd_iterator& i );
253 
254 			//! pre-increment
255 			_fwd_iterator& operator++();
256 			//! post-increment
257 			_fwd_iterator operator++( int );
258 
259 			//! pre-decrement
260 			_fwd_iterator& operator--();
261 			//! post-decrement
262 			_fwd_iterator operator--( int );
263 
264 			//! addition operator
265 			_fwd_iterator operator+( difference_type n );
266 			//! subtraction operator
267 			_fwd_iterator operator-( difference_type n );
268 
269 			//! addition assignment operator
270 			_fwd_iterator& operator+=( difference_type n );
271 			//! subtraction assignment operator
272 			_fwd_iterator& operator-=( difference_type n );
273 
274 			//! dereference operator
275 			value_type& operator*() const;
276 
277 			//! dereference at offset operator
278 			value_type& operator[]( difference_type n ) const;
279 
280 			//! advances to the next Unicode character, honoring surrogate pairs in the UTF-16 stream
281 			_fwd_iterator& moveNext();
282 			//! rewinds to the previous Unicode character, honoring surrogate pairs in the UTF-16 stream
283 			_fwd_iterator& movePrev();
284 			//! Returns the Unicode value of the character at the current position (decodes surrogate pairs if needed)
285 			unicode_char getCharacter() const;
286 			//! Sets the Unicode value of the character at the current position (adding a surrogate pair if needed); returns the amount of string length change caused by the operation
287 			int setCharacter( unicode_char uc );
288 		};
289 
290 
291 
292 		//#########################################################################
293 		//! const forward iterator for UString
294 	class MYGUI_EXPORT _const_fwd_iterator: public _base_iterator { /* i don't know why the beautifier is freaking out on this line */
295 		public:
296 			_const_fwd_iterator();
297 			_const_fwd_iterator( const _const_fwd_iterator& i );
298 			_const_fwd_iterator& operator=( const _const_fwd_iterator& i );
299 			_const_fwd_iterator( const _fwd_iterator& i );
300 
301 			//! pre-increment
302 			_const_fwd_iterator& operator++();
303 			//! post-increment
304 			_const_fwd_iterator operator++( int );
305 
306 			//! pre-decrement
307 			_const_fwd_iterator& operator--();
308 			//! post-decrement
309 			_const_fwd_iterator operator--( int );
310 
311 			//! addition operator
312 			_const_fwd_iterator operator+( difference_type n );
313 			//! subtraction operator
314 			_const_fwd_iterator operator-( difference_type n );
315 
316 			//! addition assignment operator
317 			_const_fwd_iterator& operator+=( difference_type n );
318 			//! subtraction assignment operator
319 			_const_fwd_iterator& operator-=( difference_type n );
320 
321 			//! dereference operator
322 			const value_type& operator*() const;
323 
324 			//! dereference at offset operator
325 			const value_type& operator[]( difference_type n ) const;
326 
327 			//! advances to the next Unicode character, honoring surrogate pairs in the UTF-16 stream
328 			_const_fwd_iterator& moveNext();
329 			//! rewinds to the previous Unicode character, honoring surrogate pairs in the UTF-16 stream
330 			_const_fwd_iterator& movePrev();
331 			//! Returns the Unicode value of the character at the current position (decodes surrogate pairs if needed)
332 			unicode_char getCharacter() const;
333 
334 			//! difference operator
335 			friend size_type operator-( const _const_fwd_iterator& left, const _const_fwd_iterator& right );
336 			//! equality operator
337 			friend bool operator==( const _const_fwd_iterator& left, const _const_fwd_iterator& right );
338 			//! inequality operator
339 			friend bool operator!=( const _const_fwd_iterator& left, const _const_fwd_iterator& right );
340 			//! less than
341 			friend bool operator<( const _const_fwd_iterator& left, const _const_fwd_iterator& right );
342 			//! less than or equal
343 			friend bool operator<=( const _const_fwd_iterator& left, const _const_fwd_iterator& right );
344 			//! greater than
345 			friend bool operator>( const _const_fwd_iterator& left, const _const_fwd_iterator& right );
346 			//! greater than or equal
347 			friend bool operator>=( const _const_fwd_iterator& left, const _const_fwd_iterator& right );
348 
349 		};
350 
351 		//#########################################################################
352 		// REVERSE ITERATORS
353 		//#########################################################################
354 		class _const_rev_iterator; // forward declaration
355 		//! forward iterator for UString
356 	class MYGUI_EXPORT _rev_iterator: public _base_iterator { /* i don't know why the beautifier is freaking out on this line */
357 			friend class _const_rev_iterator;
358 		public:
359 			_rev_iterator();
360 			_rev_iterator( const _rev_iterator& i );
361 
362 			//! pre-increment
363 			_rev_iterator& operator++();
364 			//! post-increment
365 			_rev_iterator operator++( int );
366 
367 			//! pre-decrement
368 			_rev_iterator& operator--();
369 			//! post-decrement
370 			_rev_iterator operator--( int );
371 
372 			//! addition operator
373 			_rev_iterator operator+( difference_type n );
374 			//! subtraction operator
375 			_rev_iterator operator-( difference_type n );
376 
377 			//! addition assignment operator
378 			_rev_iterator& operator+=( difference_type n );
379 			//! subtraction assignment operator
380 			_rev_iterator& operator-=( difference_type n );
381 
382 			//! dereference operator
383 			value_type& operator*() const;
384 
385 			//! dereference at offset operator
386 			value_type& operator[]( difference_type n ) const;
387 		};
388 		//#########################################################################
389 		//! const reverse iterator for UString
390 	class MYGUI_EXPORT _const_rev_iterator: public _base_iterator { /* i don't know why the beautifier is freaking out on this line */
391 		public:
392 			_const_rev_iterator();
393 			_const_rev_iterator( const _const_rev_iterator& i );
394 			_const_rev_iterator( const _rev_iterator& i );
395 			//! pre-increment
396 			_const_rev_iterator& operator++();
397 			//! post-increment
398 			_const_rev_iterator operator++( int );
399 
400 			//! pre-decrement
401 			_const_rev_iterator& operator--();
402 			//! post-decrement
403 			_const_rev_iterator operator--( int );
404 
405 			//! addition operator
406 			_const_rev_iterator operator+( difference_type n );
407 			//! subtraction operator
408 			_const_rev_iterator operator-( difference_type n );
409 
410 			//! addition assignment operator
411 			_const_rev_iterator& operator+=( difference_type n );
412 			//! subtraction assignment operator
413 			_const_rev_iterator& operator-=( difference_type n );
414 
415 			//! dereference operator
416 			const value_type& operator*() const;
417 
418 			//! dereference at offset operator
419 			const value_type& operator[]( difference_type n ) const;
420 
421 			//! difference operator
422 			friend size_type operator-( const _const_rev_iterator& left, const _const_rev_iterator& right );
423 			//! equality operator
424 			friend bool operator==( const _const_rev_iterator& left, const _const_rev_iterator& right );
425 			//! inequality operator
426 			friend bool operator!=( const _const_rev_iterator& left, const _const_rev_iterator& right );
427 			//! less than
428 			friend bool operator<( const _const_rev_iterator& left, const _const_rev_iterator& right );
429 			//! less than or equal
430 			friend bool operator<=( const _const_rev_iterator& left, const _const_rev_iterator& right );
431 			//! greater than
432 			friend bool operator>( const _const_rev_iterator& left, const _const_rev_iterator& right );
433 			//! greater than or equal
434 			friend bool operator>=( const _const_rev_iterator& left, const _const_rev_iterator& right );
435 		};
436 		//#########################################################################
437 
438 		using iterator = _fwd_iterator;                     //!< iterator
439 		using reverse_iterator = _rev_iterator;             //!< reverse iterator
440 		using const_iterator = _const_fwd_iterator;         //!< const iterator
441 		using const_reverse_iterator = _const_rev_iterator; //!< const reverse iterator
442 
443 
444 		//!\name Constructors/Destructor
445 		//@{
446 		//! default constructor, creates an empty string
447 		UString();
448 		//! copy constructor
449 		UString( const UString& copy );
450 		//! \a length copies of \a ch
451 		UString( size_type length, const code_point& ch );
452 		//! duplicate of nul-terminated sequence \a str
453 		UString( const code_point* str );
454 		//! duplicate of \a str, \a length code points long
455 		UString( const code_point* str, size_type length );
456 		//! substring of \a str starting at \a index and \a length code points long
457 		UString( const UString& str, size_type index, size_type length );
458 #if MYGUI_IS_NATIVE_WCHAR_T
459 		//! duplicate of nul-terminated \c wchar_t array
460 		UString( const wchar_t* w_str );
461 		//! duplicate of \a w_str, \a length characters long
462 		UString( const wchar_t* w_str, size_type length );
463 #endif
464 		//! duplicate of \a wstr
465 		UString( const std::wstring& wstr );
466 		//! duplicate of nul-terminated C-string \a c_str (UTF-8 encoding)
467 		UString( const char* c_str );
468 		//! duplicate of \a c_str, \a length characters long (UTF-8 encoding)
469 		UString( const char* c_str, size_type length );
470 		//! duplicate of \a str (UTF-8 encoding)
471 		UString( const std::string& str );
472 
473 		//! destructor
474 		~UString();
475 		//@}
476 
477 		//////////////////////////////////////////////////////////////////////////
478 
479 		//!\name Utility functions
480 		//@{
481 		//! Returns the number of code points in the current string
482 		size_type size() const;
483 		//! Returns the number of code points in the current string
484 		size_type length() const;
485 		//! Returns the number of Unicode characters in the string
486 		/*! Executes in linear time. */
487 		size_type length_Characters() const;
488 		//! returns the maximum number of UTF-16 code points that the string can hold
489 		size_type max_size() const;
490 		//! sets the capacity of the string to at least \a size code points
491 		void reserve( size_type size );
492 		//! changes the size of the string to \a size, filling in any new area with \a val
493 		void resize( size_type num, const code_point& val = 0 );
494 		//! exchanges the elements of the current string with those of \a from
495 		void swap( UString& from );
496 		//! returns \c true if the string has no elements, \c false otherwise
497 		bool empty() const;
498 		//! returns a pointer to the first character in the current string
499 		const code_point* c_str() const;
500 		//! returns a pointer to the first character in the current string
501 		const code_point* data() const;
502 		//! returns the number of elements that the string can hold before it will need to allocate more space
503 		size_type capacity() const;
504 		//! deletes all of the elements in the string
505 		void clear();
506 		//! returns a substring of the current string, starting at \a index, and \a num characters long.
507 		/*! If \a num is omitted, it will default to \c UString::npos, and the substr() function will simply return the remainder of the string starting at \a index. */
508 		UString substr( size_type index, size_type num = npos ) const;
509 		//! appends \a val to the end of the string
510 		void push_back( unicode_char val );
511 #if MYGUI_IS_NATIVE_WCHAR_T
512 		//! appends \a val to the end of the string
513 		void push_back( wchar_t val );
514 #endif
515 		//! appends \a val to the end of the string
516 		/*! This can be used to push surrogate pair code points, you'll just need to push them
517 		one after the other. */
518 		void push_back( code_point val );
519 		//! appends \a val to the end of the string
520 		/*! Limited to characters under the 127 value barrier. */
521 		void push_back( char val );
522 		//! returns \c true if the given Unicode character \a ch is in this string
523 		bool inString( unicode_char ch ) const;
524 		//@}
525 
526 		//////////////////////////////////////////////////////////////////////////
527 
528 		//!\name Stream variations
529 		//@{
530 		//! returns the current string in UTF-8 form within a std::string
531 		const std::string& asUTF8() const;
532 		//! returns the current string in UTF-8 form as a nul-terminated char array
533 		const char* asUTF8_c_str() const;
534 		//! returns the current string in UTF-32 form within a utf32string
535 		const utf32string& asUTF32() const;
536 		//! returns the current string in UTF-32 form as a nul-terminated unicode_char array
537 		const unicode_char* asUTF32_c_str() const;
538 		//! returns the current string in the native form of std::wstring
539 		const std::wstring& asWStr() const;
540 		//! returns the current string in the native form of a nul-terminated wchar_t array
541 		const wchar_t* asWStr_c_str() const;
542 		//@}
543 
544 		//////////////////////////////////////////////////////////////////////////
545 
546 		//!\name Single Character Access
547 		//@{
548 		//! returns a reference to the element in the string at index \c loc
549 		code_point& at( size_type loc );
550 		//! returns a reference to the element in the string at index \c loc
551 		const code_point& at( size_type loc ) const;
552 		//! returns the data point \a loc evaluated as a UTF-32 value
553 		/*! This function will will only properly decode surrogate pairs when \a loc points to the index
554 		of a lead code point that is followed by a trailing code point. Evaluating the trailing code point
555 		itself, or pointing to a code point that is a sentinel value (part of a broken pair) will return
556 		the value of just that code point (not a valid Unicode value, but useful as a sentinel value). */
557 		unicode_char getChar( size_type loc ) const;
558 		//! sets the value of the character at \a loc to the Unicode value \a ch (UTF-32)
559 		/*! Providing sentinel values (values between U+D800-U+DFFF) are accepted, but you should be aware
560 		that you can also unwittingly create a valid surrogate pair if you don't pay attention to what you
561 		are doing. \note This operation may also lengthen the string if a surrogate pair is needed to
562 		represent the value given, but one is not available to replace; or alternatively shorten the string
563 		if an existing surrogate pair is replaced with a character that is representable without a surrogate
564 		pair. The return value will signify any lengthening or shortening performed, returning 0 if no change
565 		was made, -1 if the string was shortened, or 1 if the string was lengthened. Any single call can
566 		only change the string length by + or - 1. */
567 		int setChar( size_type loc, unicode_char ch );
568 		//@}
569 
570 		//////////////////////////////////////////////////////////////////////////
571 
572 		//!\name iterator acquisition
573 		//@{
574 		//! returns an iterator to the first element of the string
575 		iterator begin();
576 		//! returns an iterator to the first element of the string
577 		const_iterator begin() const;
578 		//! returns an iterator just past the end of the string
579 		iterator end();
580 		//! returns an iterator just past the end of the string
581 		const_iterator end() const;
582 		//! returns a reverse iterator to the last element of the string
583 		reverse_iterator rbegin();
584 		//! returns a reverse iterator to the last element of the string
585 		const_reverse_iterator rbegin() const;
586 		//! returns a reverse iterator just past the beginning of the string
587 		reverse_iterator rend();
588 		//! returns a reverse iterator just past the beginning of the string
589 		const_reverse_iterator rend() const;
590 		//@}
591 
592 		//////////////////////////////////////////////////////////////////////////
593 
594 		//!\name assign
595 		//@{
596 		//! gives the current string the values from \a start to \a end
597 		UString& assign( iterator start, iterator end );
598 		//! assign \a str to the current string
599 		UString& assign( const UString& str );
600 		//! assign the nul-terminated \a str to the current string
601 		UString& assign( const code_point* str );
602 		//! assign the first \a num characters of \a str to the current string
603 		UString& assign( const code_point* str, size_type num );
604 		//! assign \a len entries from \a str to the current string, starting at \a index
605 		UString& assign( const UString& str, size_type index, size_type len );
606 		//! assign \a num copies of \a ch to the current string
607 		UString& assign( size_type num, const code_point& ch );
608 		//! assign \a wstr to the current string (\a wstr is treated as a UTF-16 stream)
609 		UString& assign( const std::wstring& wstr );
610 #if MYGUI_IS_NATIVE_WCHAR_T
611 		//! assign \a w_str to the current string
612 		UString& assign( const wchar_t* w_str );
613 		//! assign the first \a num characters of \a w_str to the current string
614 		UString& assign( const wchar_t* w_str, size_type num );
615 #endif
616 		//! assign \a str to the current string (\a str is treated as a UTF-8 stream)
617 		UString& assign( const std::string& str );
618 		//! assign \a c_str to the current string (\a c_str is treated as a UTF-8 stream)
619 		UString& assign( const char* c_str );
620 		//! assign the first \a num characters of \a c_str to the current string (\a c_str is treated as a UTF-8 stream)
621 		UString& assign( const char* c_str, size_type num );
622 		//@}
623 
624 		//////////////////////////////////////////////////////////////////////////
625 
626 		//!\name append
627 		//@{
628 		//! appends \a str on to the end of the current string
629 		UString& append( const UString& str );
630 		//! appends \a str on to the end of the current string
631 		UString& append( const code_point* str );
632 		//! appends a substring of \a str starting at \a index that is \a len characters long on to the end of the current string
633 		UString& append( const UString& str, size_type index, size_type len );
634 		//! appends \a num characters of \a str on to the end of the current string
635 		UString& append( const code_point* str, size_type num );
636 		//! appends \a num repetitions of \a ch on to the end of the current string
637 		UString& append( size_type num, code_point ch );
638 		//! appends the sequence denoted by \a start and \a end on to the end of the current string
639 		UString& append( iterator start, iterator end );
640 #if MYGUI_IS_NATIVE_WCHAR_T
641 		//! appends \a num characters of \a str on to the end of the current string
642 		UString& append( const wchar_t* w_str, size_type num );
643 		//! appends \a num repetitions of \a ch on to the end of the current string
644 		UString& append( size_type num, wchar_t ch );
645 #endif
646 		//! appends \a num characters of \a str on to the end of the current string  (UTF-8 encoding)
647 		UString& append( const char* c_str, size_type num );
648 		//! appends \a num repetitions of \a ch on to the end of the current string (Unicode values less than 128)
649 		UString& append( size_type num, char ch );
650 		//! appends \a num repetitions of \a ch on to the end of the current string (Full Unicode spectrum)
651 		UString& append( size_type num, unicode_char ch );
652 		//@}
653 
654 		//////////////////////////////////////////////////////////////////////////
655 
656 		//!\name insert
657 		//@{
658 		//! inserts \a ch before the code point denoted by \a i
659 		iterator insert( iterator i, const code_point& ch );
660 		//! inserts \a str into the current string, at location \a index
661 		UString& insert( size_type index, const UString& str );
662 		//! inserts \a str into the current string, at location \a index
insert(size_type index,const code_point * str)663 		UString& insert( size_type index, const code_point* str ) {
664 			mData.insert( index, str );
665 			return *this;
666 		}
667 		//! inserts a substring of \a str (starting at \a index2 and \a num code points long) into the current string, at location \a index1
668 		UString& insert( size_type index1, const UString& str, size_type index2, size_type num );
669 		//! inserts the code points denoted by \a start and \a end into the current string, before the code point specified by \a i
670 		void insert( iterator i, iterator start, iterator end );
671 		//! inserts \a num code points of \a str into the current string, at location \a index
672 		UString& insert( size_type index, const code_point* str, size_type num );
673 #if MYGUI_IS_NATIVE_WCHAR_T
674 		//! inserts \a num code points of \a str into the current string, at location \a index
675 		UString& insert( size_type index, const wchar_t* w_str, size_type num );
676 #endif
677 		//! inserts \a num code points of \a str into the current string, at location \a index
678 		UString& insert( size_type index, const char* c_str, size_type num );
679 		//! inserts \a num copies of \a ch into the current string, at location \a index
680 		UString& insert( size_type index, size_type num, code_point ch );
681 #if MYGUI_IS_NATIVE_WCHAR_T
682 		//! inserts \a num copies of \a ch into the current string, at location \a index
683 		UString& insert( size_type index, size_type num, wchar_t ch );
684 #endif
685 		//! inserts \a num copies of \a ch into the current string, at location \a index
686 		UString& insert( size_type index, size_type num, char ch );
687 		//! inserts \a num copies of \a ch into the current string, at location \a index
688 		UString& insert( size_type index, size_type num, unicode_char ch );
689 		//! inserts \a num copies of \a ch into the current string, before the code point denoted by \a i
690 		void insert( iterator i, size_type num, const code_point& ch );
691 #if MYGUI_IS_NATIVE_WCHAR_T
692 		//! inserts \a num copies of \a ch into the current string, before the code point denoted by \a i
693 		void insert( iterator i, size_type num, const wchar_t& ch );
694 #endif
695 		//! inserts \a num copies of \a ch into the current string, before the code point denoted by \a i
696 		void insert( iterator i, size_type num, const char& ch );
697 		//! inserts \a num copies of \a ch into the current string, before the code point denoted by \a i
698 		void insert( iterator i, size_type num, const unicode_char& ch );
699 		//@}
700 
701 		//////////////////////////////////////////////////////////////////////////
702 
703 		//!\name erase
704 		//@{
705 		//! removes the code point pointed to by \a loc, returning an iterator to the next character
706 		iterator erase( iterator loc );
707 		//! removes the code points between \a start and \a end (including the one at \a start but not the one at \a end), returning an iterator to the code point after the last code point removed
708 		iterator erase( iterator start, iterator end );
709 		//! removes \a num code points from the current string, starting at \a index
710 		UString& erase( size_type index = 0, size_type num = npos );
711 		//@}
712 
713 		//////////////////////////////////////////////////////////////////////////
714 
715 		//!\name replace
716 		//@{
717 		//! replaces up to \a num1 code points of the current string (starting at \a index1) with \a str
718 		UString& replace( size_type index1, size_type num1, const UString& str );
719 		//! replaces up to \a num1 code points of the current string (starting at \a index1) with up to \a num2 code points from \a str
720 		UString& replace( size_type index1, size_type num1, const UString& str, size_type num2 );
721 		//! replaces up to \a num1 code points of the current string (starting at \a index1) with up to \a num2 code points from \a str beginning at \a index2
722 		UString& replace( size_type index1, size_type num1, const UString& str, size_type index2, size_type num2 );
723 		//! replaces code points in the current string from \a start to \a end with \a num code points from \a str
724 		UString& replace( iterator start, iterator end, const UString& str, size_type num = npos );
725 		//! replaces up to \a num1 code points in the current string (beginning at \a index) with \c num2 copies of \c ch
726 		UString& replace( size_type index, size_type num1, size_type num2, code_point ch );
727 		//! replaces the code points in the current string from \a start to \a end with \a num copies of \a ch
728 		UString& replace( iterator start, iterator end, size_type num, code_point ch );
729 		//@}
730 
731 		//////////////////////////////////////////////////////////////////////////
732 
733 		//!\name compare
734 		//@{
735 		//! compare \a str to the current string
736 		int compare( const UString& str ) const;
737 		//! compare \a str to the current string
738 		int compare( const code_point* str ) const;
739 		//! compare \a str to a substring of the current string, starting at \a index for \a length characters
740 		int compare( size_type index, size_type length, const UString& str ) const;
741 		//! compare a substring of \a str to a substring of the current string, where \a index2 and \a length2 refer to \a str and \a index and \a length refer to the current string
742 		int compare( size_type index, size_type length, const UString& str, size_type index2, size_type length2 ) const;
743 		//! compare a substring of \a str to a substring of the current string, where the substring of \a str begins at zero and is \a length2 characters long, and the substring of the current string begins at \a index and is \a length  characters long
744 		int compare( size_type index, size_type length, const code_point* str, size_type length2 ) const;
745 #if MYGUI_IS_NATIVE_WCHAR_T
746 		//! compare a substring of \a str to a substring of the current string, where the substring of \a str begins at zero and is \a length2 elements long, and the substring of the current string begins at \a index and is \a length characters long
747 		int compare( size_type index, size_type length, const wchar_t* w_str, size_type length2 ) const;
748 #endif
749 		//! compare a substring of \a str to a substring of the current string, where the substring of \a str begins at zero and is \a length2 <b>UTF-8 code points</b> long, and the substring of the current string begins at \a index and is \a length characters long
750 		int compare( size_type index, size_type length, const char* c_str, size_type length2 ) const;
751 		//@}
752 
753 		//////////////////////////////////////////////////////////////////////////
754 
755 		//!\name find & rfind
756 		//@{
757 		//! returns the index of the first occurrence of \a str within the current string, starting at \a index; returns \c UString::npos if nothing is found
758 		/*! \a str is a UTF-16 encoded string, but through implicit casting can also be a UTF-8 encoded string (const char* or std::string) */
759 		size_type find( const UString& str, size_type index = 0 ) const;
760 		//! returns the index of the first occurrence of \a str within the current string and within \a length code points, starting at \a index; returns \c UString::npos if nothing is found
761 		/*! \a cp_str is a UTF-16 encoded string */
762 		size_type find( const code_point* cp_str, size_type index, size_type length ) const;
763 		//! returns the index of the first occurrence of \a str within the current string and within \a length code points, starting at \a index; returns \c UString::npos if nothing is found
764 		/*! \a cp_str is a UTF-8 encoded string */
765 		size_type find( const char* c_str, size_type index, size_type length ) const;
766 #if MYGUI_IS_NATIVE_WCHAR_T
767 		//! returns the index of the first occurrence of \a str within the current string and within \a length code points, starting at \a index; returns \c UString::npos if nothing is found
768 		/*! \a cp_str is a UTF-16 encoded string */
769 		size_type find( const wchar_t* w_str, size_type index, size_type length ) const;
770 #endif
771 		//! returns the index of the first occurrence \a ch within the current string, starting at \a index; returns \c UString::npos if nothing is found
772 		/*! \a ch is only capable of representing Unicode values up to U+007F (127) */
773 		size_type find( char ch, size_type index = 0 ) const;
774 		//! returns the index of the first occurrence \a ch within the current string, starting at \a index; returns \c UString::npos if nothing is found
775 		/*! \a ch is only capable of representing Unicode values up to U+FFFF (65535) */
776 		size_type find( code_point ch, size_type index = 0 ) const;
777 #if MYGUI_IS_NATIVE_WCHAR_T
778 		//! returns the index of the first occurrence \a ch within the current string, starting at \a index; returns \c UString::npos if nothing is found
779 		/*! \a ch is only capable of representing Unicode values up to U+FFFF (65535) */
780 		size_type find( wchar_t ch, size_type index = 0 ) const;
781 #endif
782 		//! returns the index of the first occurrence \a ch within the current string, starting at \a index; returns \c UString::npos if nothing is found
783 		/*! \a ch can fully represent any Unicode character */
784 		size_type find( unicode_char ch, size_type index = 0 ) const;
785 
786 		//! returns the location of the first occurrence of \a str in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
787 		size_type rfind( const UString& str, size_type index = 0 ) const;
788 		//! returns the location of the first occurrence of \a str in the current string, doing a reverse search from \a index, searching at most \a num characters; returns \c UString::npos if nothing is found
789 		size_type rfind( const code_point* cp_str, size_type index, size_type num ) const;
790 		//! returns the location of the first occurrence of \a str in the current string, doing a reverse search from \a index, searching at most \a num characters; returns \c UString::npos if nothing is found
791 		size_type rfind( const char* c_str, size_type index, size_type num ) const;
792 #if MYGUI_IS_NATIVE_WCHAR_T
793 		//! returns the location of the first occurrence of \a str in the current string, doing a reverse search from \a index, searching at most \a num characters; returns \c UString::npos if nothing is found
794 		size_type rfind( const wchar_t* w_str, size_type index, size_type num ) const;
795 #endif
796 		//! returns the location of the first occurrence of \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
797 		size_type rfind( char ch, size_type index = 0 ) const;
798 		//! returns the location of the first occurrence of \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
799 		size_type rfind( code_point ch, size_type index ) const;
800 #if MYGUI_IS_NATIVE_WCHAR_T
801 		//! returns the location of the first occurrence of \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
802 		size_type rfind( wchar_t ch, size_type index = 0 ) const;
803 #endif
804 		//! returns the location of the first occurrence of \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
805 		size_type rfind( unicode_char ch, size_type index = 0 ) const;
806 		//@}
807 
808 		//////////////////////////////////////////////////////////////////////////
809 
810 		//!\name find_first/last_(not)_of
811 		//@{
812 		//! Returns the index of the first character within the current string that matches \b any character in \a str, beginning the search at \a index and searching at most \a num characters; returns \c UString::npos if nothing is found
813 		size_type find_first_of( const UString &str, size_type index = 0, size_type num = npos ) const;
814 		//! returns the index of the first occurrence of \a ch in the current string, starting the search at \a index; returns \c UString::npos if nothing is found
815 		size_type find_first_of( code_point ch, size_type index = 0 ) const;
816 		//! returns the index of the first occurrence of \a ch in the current string, starting the search at \a index; returns \c UString::npos if nothing is found
817 		size_type find_first_of( char ch, size_type index = 0 ) const;
818 #if MYGUI_IS_NATIVE_WCHAR_T
819 		//! returns the index of the first occurrence of \a ch in the current string, starting the search at \a index; returns \c UString::npos if nothing is found
820 		size_type find_first_of( wchar_t ch, size_type index = 0 ) const;
821 #endif
822 		//! returns the index of the first occurrence of \a ch in the current string, starting the search at \a index; returns \c UString::npos if nothing is found
823 		size_type find_first_of( unicode_char ch, size_type index = 0 ) const;
824 
825 		//! returns the index of the first character within the current string that does not match any character in \a str, beginning the search at \a index and searching at most \a num characters; returns \c UString::npos if nothing is found
826 		size_type find_first_not_of( const UString& str, size_type index = 0, size_type num = npos ) const;
827 		//! returns the index of the first character within the current string that does not match \a ch, starting the search at \a index; returns \c UString::npos if nothing is found
828 		size_type find_first_not_of( code_point ch, size_type index = 0 ) const;
829 		//! returns the index of the first character within the current string that does not match \a ch, starting the search at \a index; returns \c UString::npos if nothing is found
830 		size_type find_first_not_of( char ch, size_type index = 0 ) const;
831 #if MYGUI_IS_NATIVE_WCHAR_T
832 		//! returns the index of the first character within the current string that does not match \a ch, starting the search at \a index; returns \c UString::npos if nothing is found
833 		size_type find_first_not_of( wchar_t ch, size_type index = 0 ) const;
834 #endif
835 		//! returns the index of the first character within the current string that does not match \a ch, starting the search at \a index; returns \c UString::npos if nothing is found
836 		size_type find_first_not_of( unicode_char ch, size_type index = 0 ) const;
837 
838 		//! returns the index of the first character within the current string that matches any character in \a str, doing a reverse search from \a index and searching at most \a num characters; returns \c UString::npos if nothing is found
839 		size_type find_last_of( const UString& str, size_type index = npos, size_type num = npos ) const;
840 		//! returns the index of the first occurrence of \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
841 		size_type find_last_of( code_point ch, size_type index = npos ) const;
842 		//! returns the index of the first occurrence of \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
843 		size_type find_last_of( char ch, size_type index = npos ) const {
844 			return find_last_of( static_cast<code_point>( ch ), index );
845 		}
846 #if MYGUI_IS_NATIVE_WCHAR_T
847 		//! returns the index of the first occurrence of \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
848 		size_type find_last_of( wchar_t ch, size_type index = npos ) const;
849 #endif
850 		//! returns the index of the first occurrence of \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
851 		size_type find_last_of( unicode_char ch, size_type index = npos ) const;
852 
853 		//! returns the index of the last character within the current string that does not match any character in \a str, doing a reverse search from \a index; returns \c UString::npos if nothing is found
854 		size_type find_last_not_of( const UString& str, size_type index = npos, size_type num = npos ) const;
855 		//! returns the index of the last occurrence of a character that does not match \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
856 		size_type find_last_not_of( code_point ch, size_type index = npos ) const;
857 		//! returns the index of the last occurrence of a character that does not match \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
858 		size_type find_last_not_of( char ch, size_type index = npos ) const;
859 #if MYGUI_IS_NATIVE_WCHAR_T
860 		//! returns the index of the last occurrence of a character that does not match \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
861 		size_type find_last_not_of( wchar_t ch, size_type index = npos ) const;
862 #endif
863 		//! returns the index of the last occurrence of a character that does not match \a ch in the current string, doing a reverse search from \a index; returns \c UString::npos if nothing is found
864 		size_type find_last_not_of( unicode_char ch, size_type index = npos ) const;
865 		//@}
866 
867 		//////////////////////////////////////////////////////////////////////////
868 
869 		//!\name Operators
870 		//@{
871 		//! less than operator
872 		bool operator<( const UString& right ) const;
873 		//! less than or equal operator
874 		bool operator<=( const UString& right ) const;
875 		//! greater than operator
876 		bool operator>( const UString& right ) const;
877 		//! greater than or equal operator
878 		bool operator>=( const UString& right ) const;
879 		//! equality operator
880 		bool operator==( const UString& right ) const;
881 		//! inequality operator
882 		bool operator!=( const UString& right ) const;
883 		//! assignment operator, implicitly casts all compatible types
884 		UString& operator=( const UString& s );
885 		//! assignment operator
886 		UString& operator=( code_point ch );
887 		//! assignment operator
888 		UString& operator=( char ch );
889 #if MYGUI_IS_NATIVE_WCHAR_T
890 		//! assignment operator
891 		UString& operator=( wchar_t ch );
892 #endif
893 		//! assignment operator
894 		UString& operator=( unicode_char ch );
895 		//! code point dereference operator
896 		code_point& operator[]( size_type index );
897 		//! code point dereference operator
898 		const code_point& operator[]( size_type index ) const;
899 		//@}
900 
901 		//////////////////////////////////////////////////////////////////////////
902 
903 		//!\name Implicit Cast Operators
904 		//@{
905 		//! implicit cast to std::string
906 		operator std::string() const;
907 		//! implicit cast to std::wstring
908 		operator std::wstring() const;
909 		//@}
910 
911 		//////////////////////////////////////////////////////////////////////////
912 
913 		//!\name UTF-16 character encoding/decoding
914 		//@{
915 		//! returns \c true if \a cp does not match the signature for the lead of follow code point of a surrogate pair in a UTF-16 sequence
916 		static bool _utf16_independent_char( code_point cp );
917 		//! returns \c true if \a cp matches the signature of a surrogate pair lead character
918 		static bool _utf16_surrogate_lead( code_point cp );
919 		//! returns \c true if \a cp matches the signature of a surrogate pair following character
920 		static bool _utf16_surrogate_follow( code_point cp );
921 		//! estimates the number of UTF-16 code points in the sequence starting with \a cp
922 		static size_t _utf16_char_length( code_point cp );
923 		//! returns the number of UTF-16 code points needed to represent the given UTF-32 character \a cp
924 		static size_t _utf16_char_length( unicode_char uc );
925 		//! converts the given UTF-16 character buffer \a in_cp to a single UTF-32 Unicode character \a out_uc, returns the number of code points used to create the output character (2 for surrogate pairs, otherwise 1)
926 		/*! This function does it's best to prevent error conditions, verifying complete
927 		surrogate pairs before applying the algorithm. In the event that half of a pair
928 		is found it will happily generate a value in the 0xD800 - 0xDFFF range, which is
929 		normally an invalid Unicode value but we preserve them for use as sentinel values. */
930 		static size_t _utf16_to_utf32( const code_point in_cp[2], unicode_char& out_uc );
931 		//! writes the given UTF-32 \a uc_in to the buffer location \a out_cp using UTF-16 encoding, returns the number of code points used to encode the input (always 1 or 2)
932 		/*! This function, like its counterpart, will happily create invalid UTF-16 surrogate pairs. These
933 		invalid entries will be created for any value of \c in_uc that falls in the range U+D800 - U+DFFF.
934 		These are generally useful as sentinel values to represent various program specific conditions.
935 		\note This function will also pass through any single UTF-16 code point without modification,
936 		making it a safe method of ensuring a stream that is unknown UTF-32 or UTF-16 is truly UTF-16.*/
937 		static size_t _utf32_to_utf16( const unicode_char& in_uc, code_point out_cp[2] );
938 		//@}
939 
940 		//////////////////////////////////////////////////////////////////////////
941 
942 		//!\name UTF-8 character encoding/decoding
943 		//@{
944 		//! returns \c true if \a cp is the beginning of a UTF-8 sequence
945 		static bool _utf8_start_char( unsigned char cp );
946 		//! estimates the number of UTF-8 code points in the sequence starting with \a cp
947 		static size_t _utf8_char_length( unsigned char cp );
948 		//! returns the number of UTF-8 code points needed to represent the given UTF-32 character \a cp
949 		static size_t _utf8_char_length( unicode_char uc );
950 
951 		//! converts the given UTF-8 character buffer to a single UTF-32 Unicode character, returns the number of bytes used to create the output character (maximum of 6)
952 		static size_t _utf8_to_utf32( const unsigned char in_cp[6], unicode_char& out_uc );
953 		//! writes the given UTF-32 \a uc_in to the buffer location \a out_cp using UTF-8 encoding, returns the number of bytes used to encode the input
954 		static size_t _utf32_to_utf8( const unicode_char& in_uc, unsigned char out_cp[6] );
955 
956 		//! verifies a UTF-8 stream, returning the total number of Unicode characters found
957 		static size_type _verifyUTF8( const unsigned char* c_str );
958 		//! verifies a UTF-8 stream, returning the total number of Unicode characters found
959 		static size_type _verifyUTF8( const std::string& str );
960 		//@}
961 
962 	private:
963 		//template<class ITER_TYPE> friend class _iterator;
964 		dstring mData;
965 
966 		//! buffer data type identifier
967 		enum BufferType {
968 			bt_none,
969 			bt_string,
970 			bt_wstring,
971 			bt_utf32string
972 		};
973 
974 		//! common constructor operations
975 		void _init();
976 
977 		///////////////////////////////////////////////////////////////////////
978 		// Scratch buffer
979 		//! auto cleans the scratch buffer using the proper delete for the stored type
980 		void _cleanBuffer() const;
981 
982 		//! create a std::string in the scratch buffer area
983 		void _getBufferStr() const;
984 		//! create a std::wstring in the scratch buffer area
985 		void _getBufferWStr() const;
986 		//! create a utf32string in the scratch buffer area
987 		void _getBufferUTF32Str() const;
988 
989 		void _load_buffer_UTF8() const;
990 		void _load_buffer_WStr() const;
991 		void _load_buffer_UTF32() const;
992 
993 		mutable BufferType m_bufferType; // identifies the data type held in m_buffer
994 		mutable size_t m_bufferSize; // size of the CString buffer
995 
996 		// multi-purpose buffer used everywhere we need a throw-away buffer
997 		union {
998 			mutable void* mVoidBuffer;
999 			mutable std::string* mStrBuffer;
1000 			mutable std::wstring* mWStrBuffer;
1001 			mutable utf32string* mUTF32StrBuffer;
1002 		}
1003 		m_buffer;
1004 	};
1005 
1006 	//! string addition operator \relates UString
1007 	inline UString operator+( const UString& s1, const UString& s2 ) {
1008 		return UString( s1 ).append( s2 );
1009 	}
1010 	//! string addition operator \relates UString
1011 	inline UString operator+( const UString& s1, UString::code_point c ) {
1012 		return UString( s1 ).append( 1, c );
1013 	}
1014 	//! string addition operator \relates UString
1015 	inline UString operator+( const UString& s1, UString::unicode_char c ) {
1016 		return UString( s1 ).append( 1, c );
1017 	}
1018 	//! string addition operator \relates UString
1019 	inline UString operator+( const UString& s1, char c ) {
1020 		return UString( s1 ).append( 1, c );
1021 	}
1022 #if MYGUI_IS_NATIVE_WCHAR_T
1023 	//! string addition operator \relates UString
1024 	inline UString operator+( const UString& s1, wchar_t c ) {
1025 		return UString( s1 ).append( 1, c );
1026 	}
1027 #endif
1028 	//! string addition operator \relates UString
1029 	inline UString operator+( UString::code_point c, const UString& s2 ) {
1030 		return UString().append( 1, c ).append( s2 );
1031 	}
1032 	//! string addition operator \relates UString
1033 	inline UString operator+( UString::unicode_char c, const UString& s2 ) {
1034 		return UString().append( 1, c ).append( s2 );
1035 	}
1036 	//! string addition operator \relates UString
1037 	inline UString operator+( char c, const UString& s2 ) {
1038 		return UString().append( 1, c ).append( s2 );
1039 	}
1040 #if MYGUI_IS_NATIVE_WCHAR_T
1041 	//! string addition operator \relates UString
1042 	inline UString operator+( wchar_t c, const UString& s2 ) {
1043 		return UString().append( 1, c ).append( s2 );
1044 	}
1045 #endif
1046 
1047 	// (const) forward iterator common operators
1048 	inline UString::size_type operator-( const UString::_const_fwd_iterator& left, const UString::_const_fwd_iterator& right ) {
1049 		return ( left.mIter - right.mIter );
1050 	}
1051 	inline bool operator==( const UString::_const_fwd_iterator& left, const UString::_const_fwd_iterator& right ) {
1052 		return left.mIter == right.mIter;
1053 	}
1054 	inline bool operator!=( const UString::_const_fwd_iterator& left, const UString::_const_fwd_iterator& right ) {
1055 		return left.mIter != right.mIter;
1056 	}
1057 	inline bool operator<( const UString::_const_fwd_iterator& left, const UString::_const_fwd_iterator& right ) {
1058 		return left.mIter < right.mIter;
1059 	}
1060 	inline bool operator<=( const UString::_const_fwd_iterator& left, const UString::_const_fwd_iterator& right ) {
1061 		return left.mIter <= right.mIter;
1062 	}
1063 	inline bool operator>( const UString::_const_fwd_iterator& left, const UString::_const_fwd_iterator& right ) {
1064 		return left.mIter > right.mIter;
1065 	}
1066 	inline bool operator>=( const UString::_const_fwd_iterator& left, const UString::_const_fwd_iterator& right ) {
1067 		return left.mIter >= right.mIter;
1068 	}
1069 
1070 	// (const) reverse iterator common operators
1071 	// NB: many of these operations are evaluated in reverse because this is a reverse iterator wrapping a forward iterator
1072 	inline UString::size_type operator-( const UString::_const_rev_iterator& left, const UString::_const_rev_iterator& right ) {
1073 		return ( right.mIter - left.mIter );
1074 	}
1075 	inline bool operator==( const UString::_const_rev_iterator& left, const UString::_const_rev_iterator& right ) {
1076 		return left.mIter == right.mIter;
1077 	}
1078 	inline bool operator!=( const UString::_const_rev_iterator& left, const UString::_const_rev_iterator& right ) {
1079 		return left.mIter != right.mIter;
1080 	}
1081 	inline bool operator<( const UString::_const_rev_iterator& left, const UString::_const_rev_iterator& right ) {
1082 		return right.mIter < left.mIter;
1083 	}
1084 	inline bool operator<=( const UString::_const_rev_iterator& left, const UString::_const_rev_iterator& right ) {
1085 		return right.mIter <= left.mIter;
1086 	}
1087 	inline bool operator>( const UString::_const_rev_iterator& left, const UString::_const_rev_iterator& right ) {
1088 		return right.mIter > left.mIter;
1089 	}
1090 	inline bool operator>=( const UString::_const_rev_iterator& left, const UString::_const_rev_iterator& right ) {
1091 		return right.mIter >= left.mIter;
1092 	}
1093 
1094 	//! std::ostream write operator \relates UString
1095 	inline std::ostream& operator << ( std::ostream& os, const UString& s ) {
1096 		return os << s.asUTF8();
1097 	}
1098 
1099 	//! std::wostream write operator \relates UString
1100 	inline std::wostream& operator << ( std::wostream& os, const UString& s ) {
1101 		return os << s.asWStr();
1102 	}
1103 
1104 } // namespace MyGUI
1105 
1106 #if MYGUI_COMPILER == MYGUI_COMPILER_MSVC
1107 #	pragma warning (pop)
1108 #endif
1109 
1110 #endif  // __MYGUI_U_STRING_H__
1111