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