1 #ifndef _GLIBMM_USTRING_H 2 #define _GLIBMM_USTRING_H 3 4 /* Copyright (C) 2002 The gtkmm Development Team 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <glibmmconfig.h> 21 #include <glibmm/unicode.h> 22 #include <glib.h> 23 24 #include <iosfwd> 25 #include <iterator> 26 #include <sstream> 27 #include <string> 28 #ifndef GLIBMM_HAVE_STD_ITERATOR_TRAITS 29 #include <cstddef> /* for std::ptrdiff_t */ 30 #endif 31 32 /* work around linker error on Visual Studio if we don't have GLIBMM_HAVE_ALLOWS_STATIC_INLINE_NPOS */ 33 #if (_MSC_VER >= 1600) && !defined (GLIBMM_HAVE_ALLOWS_STATIC_INLINE_NPOS) 34 const std::basic_string<char>::size_type std::basic_string<char>::npos = (std::basic_string<char>::size_type) -1; 35 #endif 36 37 namespace Glib 38 { 39 40 class GLIBMM_API ustring; 41 42 //********** Glib::StdStringView and Glib::UStringView ************* 43 44 // It would be possible to replace StdStringView and UStringView with a 45 // template class BasicStringView + two type aliases defining StdStringView 46 // and UStringView. But Doxygen don't generate links to type aliases. 47 // 48 // It would also be possible to replace StdStringView and UStringView with 49 // a StringView class with 3 constructors, taking const std::string&, 50 // const Glib::ustring& and const char*, respectively. The split into two classes 51 // is by design. Using the wrong string class shall not be as easy as using 52 // the right string class. 53 54 /** Helper class to avoid unnecessary string copying in function calls. 55 * 56 * A %Glib::StdStringView holds a const char pointer. It can be used as an argument 57 * type in a function that passes a const char pointer to a C function. 58 * 59 * Unlike std::string_view, %Glib::StdStringView shall be used only for 60 * null-terminated strings. 61 * @code 62 * std::string f1(Glib::StdStringView s1, Glib::StdStringView s2); 63 * // can be used instead of 64 * std::string f2(const std::string& s1, const std::string& s2); 65 * @endcode 66 * The strings are not copied when f1() is called with string literals. 67 * @code 68 * auto r1 = f1("string 1", "string 2"); 69 * @endcode 70 * To pass a Glib::ustring to a function taking a %Glib::StdStringView, you may have 71 * to use Glib::ustring::c_str(). 72 * @code 73 * std::string str = "non-UTF8 string"; 74 * Glib::ustring ustr = "UTF8 string"; 75 * auto r1 = f1(str, ustr.c_str()); 76 * @endcode 77 * 78 * @newin{2,64} 79 */ 80 class GLIBMM_API StdStringView 81 { 82 public: StdStringView(const std::string & s)83 StdStringView(const std::string& s) : pstring_(s.c_str()) {} StdStringView(const char * s)84 StdStringView(const char* s) : pstring_(s) {} c_str()85 const char* c_str() const { return pstring_; } 86 private: 87 const char* pstring_; 88 }; 89 90 /** Helper class to avoid unnecessary string copying in function calls. 91 * 92 * A %Glib::UStringView holds a const char pointer. It can be used as an argument 93 * type in a function that passes a const char pointer to a C function. 94 * 95 * Unlike std::string_view, %Glib::UStringView shall be used only for 96 * null-terminated strings. 97 * @code 98 * Glib::ustring f1(Glib::UStringView s1, Glib::UStringView s2); 99 * // can be used instead of 100 * Glib::ustring f2(const Glib::ustring& s1, const Glib::ustring& s2); 101 * @endcode 102 * The strings are not copied when f1() is called with string literals. 103 * @code 104 * auto r1 = f1("string 1", "string 2"); 105 * @endcode 106 * To pass a std::string to a function taking a %Glib::UStringView, you may have 107 * to use std::string::c_str(). 108 * @code 109 * std::string str = "non-UTF8 string"; 110 * Glib::ustring ustr = "UTF8 string"; 111 * auto r1 = f1(str.c_str(), ustr); 112 * @endcode 113 * 114 * @newin{2,64} 115 */ 116 class GLIBMM_API UStringView 117 { 118 public: 119 inline UStringView(const Glib::ustring& s); UStringView(const char * s)120 UStringView(const char* s) : pstring_(s) {} c_str()121 const char* c_str() const { return pstring_; } 122 private: 123 const char* pstring_; 124 }; 125 126 //*************************************************** 127 128 #ifndef DOXYGEN_SHOULD_SKIP_THIS 129 #ifndef GLIBMM_HAVE_STD_ITERATOR_TRAITS 130 131 template <class T> 132 struct IteratorTraits 133 { 134 using iterator_category = typename T::iterator_category; 135 using value_type = typename T::value_type; 136 using difference_type = typename T::difference_type; 137 using pointer = typename T::pointer; 138 using reference = typename T::reference; 139 }; 140 141 template <class T> 142 struct IteratorTraits<T*> 143 { 144 using iterator_category = std::random_access_iterator_tag; 145 using value_type = T; 146 using difference_type = std::ptrdiff_t; 147 using pointer = T*; 148 using reference = T&; 149 }; 150 151 template <class T> 152 struct IteratorTraits<const T*> 153 { 154 using iterator_category = std::random_access_iterator_tag; 155 using value_type = T; 156 using difference_type = std::ptrdiff_t; 157 using pointer = const T*; 158 using reference = const T&; 159 }; 160 161 #endif /* GLIBMM_HAVE_STD_ITERATOR_TRAITS */ 162 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 163 164 /** The iterator type of Glib::ustring. 165 * Note this is not a random access iterator but a bidirectional one, 166 * since all index operations need to iterate over the UTF-8 data. Use 167 * std::advance() to move to a certain position. However, all of the 168 * relational operators are available: 169 * <tt>== != < > <= >=</tt> 170 * 171 * A writeable iterator isn't provided because: The number of bytes of 172 * the old UTF-8 character and the new one to write could be different. 173 * Therefore, any write operation would invalidate all other iterators 174 * pointing into the same string. 175 * 176 * The Glib::ustring iterated over must contain only valid UTF-8 data. 177 * If it does not, operator++(), operator-\-() and operator*() may make 178 * accesses outside the bounds of the string. A loop such as the following 179 * one would not stop at the end of the string. 180 * @code 181 * // Bad code! Don't do this! 182 * const char not_utf8[] = { '\x80', '\xef', '\x80', '\x80', '\xef', '\x80' }; 183 * const Glib::ustring s(not_utf8, not_utf8 + sizeof not_utf8); 184 * for (Glib::ustring::const_iterator it = s.begin(); it != s.end(); ++it) 185 * std::cout << *it << std::endl; 186 * @endcode 187 * 188 * @tparam T std::string::iterator or std::string::const_iterator 189 */ 190 template <class T> 191 class ustring_Iterator 192 { 193 public: 194 using iterator_category = std::bidirectional_iterator_tag; 195 using value_type = gunichar; 196 using difference_type = std::string::difference_type; 197 using reference = value_type; 198 using pointer = void; 199 200 inline ustring_Iterator(); 201 inline ustring_Iterator(const ustring_Iterator<std::string::iterator>& other); 202 ustring_Iterator& operator=(const ustring_Iterator& other) = default; 203 204 inline value_type operator*() const; 205 206 inline ustring_Iterator<T>& operator++(); 207 inline const ustring_Iterator<T> operator++(int); 208 inline ustring_Iterator<T>& operator--(); 209 inline const ustring_Iterator<T> operator--(int); 210 211 explicit inline ustring_Iterator(T pos); 212 inline T base() const; 213 214 private: 215 T pos_; 216 }; 217 218 /** Extract a UCS-4 character from UTF-8 data. 219 * Convert a single UTF-8 (multibyte) character starting at @p pos to 220 * a UCS-4 wide character. This may read up to 6 bytes after the start 221 * position, depending on the UTF-8 character width. You have to make 222 * sure the source contains at least one valid UTF-8 character. 223 * 224 * This is mainly used by the implementation of Glib::ustring::iterator, 225 * but it might be useful as utility function if you prefer using 226 * std::string even for UTF-8 encoding. 227 */ 228 GLIBMM_API 229 gunichar get_unichar_from_std_iterator(std::string::const_iterator pos) G_GNUC_PURE; 230 231 /** %Glib::ustring has much the same interface as std::string, but contains 232 * %Unicode characters encoded as UTF-8. 233 * 234 * @par About UTF-8 and ASCII 235 * @par 236 * The standard character set ANSI_X3.4-1968 -- more commonly known as 237 * ASCII -- is a subset of UTF-8. So, if you want to, you can use 238 * %Glib::ustring without even thinking about UTF-8. 239 * @par 240 * Whenever ASCII is mentioned in this manual, we mean the @em real ASCII 241 * (i.e. as defined in ANSI_X3.4-1968), which contains only 7-bit characters. 242 * %Glib::ustring can @em not be used with ASCII-compatible extended 8-bit 243 * charsets like ISO-8859-1. It's a good idea to avoid string literals 244 * containing non-ASCII characters (e.g. German umlauts) in source code, 245 * or at least you should use UTF-8 literals. 246 * @par 247 * You can find a detailed UTF-8 and %Unicode FAQ here: 248 * http://www.cl.cam.ac.uk/~mgk25/unicode.html 249 * 250 * @par Glib::ustring vs. std::string 251 * @par 252 * %Glib::ustring has implicit type conversions to and from std::string. 253 * These conversions do @em not convert to/from the current locale (see 254 * Glib::locale_from_utf8() and Glib::locale_to_utf8() if you need that). You 255 * can always use std::string instead of %Glib::ustring -- however, using 256 * std::string with multi-byte characters is quite hard. For instance, 257 * <tt>std::string::operator[]</tt> might return a byte in the middle of a 258 * character, and <tt>std::string::length()</tt> returns the number of bytes 259 * rather than characters. So don't do that without a good reason. 260 * @par 261 * You cannot always use %Glib::ustring instead of std::string. 262 * @code 263 * Glib::ustring u("a_string_with_underscores"); 264 * std::replace(u.begin(), u.end(), '_', ' '); // does not compile 265 * @endcode 266 * You can't use a Glib::ustring::iterator for writing to a %Glib::ustring. 267 * See the documentation of Glib::ustring_Iterator for differences between it 268 * and std::string::iterator. 269 * @par 270 * Many member functions and operators of %Glib::ustring and Glib::ustring_Iterator 271 * assume that the string contains only valid UTF-8 data. If it does not, memory 272 * outside the bounds of the string can be accessed. If you're uncertain, use 273 * validate() and/or make_valid(). 274 * @par 275 * In a perfect world the C++ Standard Library would contain a UTF-8 string 276 * class. Unfortunately, the C++98 standard doesn't mention UTF-8 at all. 277 * C++11 has UTF-8 literals but no UTF-8 string class. Note 278 * that std::wstring is not a UTF-8 string class because it contains only 279 * fixed-width characters (where width could be 32, 16, or even 8 bits). 280 * 281 * @par Glib::ustring and stream input/output 282 * @par 283 * The stream I/O operators, that is operator<<() and operator>>(), perform 284 * implicit charset conversion to/from the current locale. If that's not 285 * what you intended (e.g. when writing to a configuration file that should 286 * always be UTF-8 encoded) use ustring::raw() to override this behaviour. 287 * @par 288 * If you're using std::ostringstream to build strings for display in the 289 * user interface, you must convert the result back to UTF-8 as shown below: 290 * @code 291 * std::locale::global(std::locale("")); // set the global locale to the user's preferred locale 292 * std::ostringstream output; 293 * output << percentage << " % done"; 294 * label->set_text(Glib::locale_to_utf8(output.str())); 295 * @endcode 296 * 297 * @par Formatted output and internationalization 298 * @par 299 * The methods ustring::compose() and ustring::format() provide a convenient 300 * and powerful alternative to string streams, as shown in the example below. 301 * Refer to the method documentation of compose() and format() for details. 302 * @code 303 * using Glib::ustring; 304 * 305 * ustring message = ustring::compose("%1 is lower than 0x%2.", 306 * 12, ustring::format(std::hex, 16)); 307 * @endcode 308 * 309 * @par Implementation notes 310 * @par 311 * %Glib::ustring does not inherit from std::string, because std::string was 312 * intended to be a final class. For instance, it does not have a virtual 313 * destructor. Also, a HAS-A relationship is more appropriate because 314 * ustring can't just enhance the std::string interface. Rather, it has to 315 * reimplement the interface so that all operations are based on characters 316 * instead of bytes. 317 */ 318 class GLIBMM_API ustring 319 { 320 public: 321 using size_type = std::string::size_type; 322 using difference_type = std::string::difference_type; 323 324 using value_type = gunichar; 325 using reference = gunichar&; 326 using const_reference = const gunichar&; 327 328 using iterator = ustring_Iterator<std::string::iterator>; 329 using const_iterator = ustring_Iterator<std::string::const_iterator>; 330 331 #ifndef GLIBMM_HAVE_SUN_REVERSE_ITERATOR 332 333 using reverse_iterator = std::reverse_iterator<iterator>; 334 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 335 336 #else 337 338 typedef std::reverse_iterator<iterator, iterator::iterator_category, iterator::value_type, 339 iterator::reference, iterator::pointer, iterator::difference_type> 340 reverse_iterator; 341 typedef std::reverse_iterator<const_iterator, const_iterator::iterator_category, 342 const_iterator::value_type, const_iterator::reference, const_iterator::pointer, 343 const_iterator::difference_type> 344 const_reverse_iterator; 345 346 #endif /* GLIBMM_HAVE_SUN_REVERSE_ITERATOR */ 347 348 #ifdef GLIBMM_HAVE_ALLOWS_STATIC_INLINE_NPOS 349 static const size_type npos = std::string::npos; 350 #else 351 // The IRIX MipsPro compiler says "The indicated constant value is not known", 352 // so we need to initalize the static member data elsewhere. 353 static const size_type npos; 354 #endif 355 356 /*! Default constructor, which creates an empty string. 357 */ 358 ustring(); 359 360 ~ustring() noexcept; 361 362 /*! Construct a ustring as a copy of another ustring. 363 * @param other A source string. 364 */ 365 ustring(const ustring& other); 366 367 /*! Construct a ustring by moving from another ustring. 368 * @param other A source string. 369 */ 370 ustring(ustring&& other); 371 372 /*! Assign the value of another string by copying to this string. 373 * @param other A source string. 374 */ 375 ustring& operator=(const ustring& other); 376 377 /*! Assign the value of another string by moving to this string. 378 * @param other A source string. 379 */ 380 ustring& operator=(ustring&& other); 381 382 /*! Swap contents with another string. 383 * @param other String to swap with. 384 */ 385 void swap(ustring& other); 386 387 /*! Construct a ustring as a copy of a std::string. 388 * @param src A source <tt>std::string</tt> containing text encoded as UTF-8. 389 */ 390 ustring(const std::string& src); 391 392 /*! Construct a ustring by moving from a std::string. 393 * @param src A source <tt>std::string</tt> containing text encoded as UTF-8. 394 */ 395 ustring(std::string&& src); 396 397 /*! Construct a ustring as a copy of a substring. 398 * @param src %Source ustring. 399 * @param i Index of first character to copy from. 400 * @param n Number of UTF-8 characters to copy (defaults to copying the remainder). 401 */ 402 ustring(const ustring& src, size_type i, size_type n = npos); 403 404 /*! Construct a ustring as a partial copy of a C string. 405 * @param src %Source C string encoded as UTF-8. 406 * @param n Number of UTF-8 characters to copy. 407 */ 408 ustring(const char* src, size_type n); 409 410 /*! Construct a ustring as a copy of a C string. 411 * @param src %Source C string encoded as UTF-8. 412 */ 413 ustring(const char* src); 414 415 /*! Construct a ustring as multiple characters. 416 * @param n Number of characters. 417 * @param uc UCS-4 code point to use. 418 */ 419 ustring(size_type n, gunichar uc); 420 421 /*! Construct a ustring as multiple characters. 422 * @param n Number of characters. 423 * @param c ASCII character to use. 424 */ 425 ustring(size_type n, char c); 426 427 /*! Construct a ustring as a copy of a range. 428 * @param pbegin Start of range. 429 * @param pend End of range. 430 */ 431 template <class In> 432 ustring(In pbegin, In pend); 433 434 //! @name Assign new contents. 435 //! @{ 436 437 ustring& operator=(const std::string& src); 438 ustring& operator=(std::string&& src); 439 ustring& operator=(const char* src); 440 ustring& operator=(gunichar uc); 441 ustring& operator=(char c); 442 443 ustring& assign(const ustring& src); 444 ustring& assign(ustring&& src); 445 ustring& assign(const ustring& src, size_type i, size_type n); 446 ustring& assign(const char* src, size_type n); 447 ustring& assign(const char* src); 448 ustring& assign(size_type n, gunichar uc); 449 ustring& assign(size_type n, char c); 450 template <class In> 451 ustring& assign(In pbegin, In pend); 452 453 //! @} 454 //! @name Append to the string. 455 //! @{ 456 457 ustring& operator+=(const ustring& src); 458 ustring& operator+=(const char* src); 459 ustring& operator+=(gunichar uc); 460 ustring& operator+=(char c); 461 void push_back(gunichar uc); 462 void push_back(char c); 463 464 ustring& append(const ustring& src); 465 ustring& append(const ustring& src, size_type i, size_type n); 466 ustring& append(const char* src, size_type n); 467 ustring& append(const char* src); 468 ustring& append(size_type n, gunichar uc); 469 ustring& append(size_type n, char c); 470 template <class In> 471 ustring& append(In pbegin, In pend); 472 473 //! @} 474 //! @name Insert into the string. 475 //! @{ 476 477 ustring& insert(size_type i, const ustring& src); 478 ustring& insert(size_type i, const ustring& src, size_type i2, size_type n); 479 ustring& insert(size_type i, const char* src, size_type n); 480 ustring& insert(size_type i, const char* src); 481 ustring& insert(size_type i, size_type n, gunichar uc); 482 ustring& insert(size_type i, size_type n, char c); 483 484 iterator insert(iterator p, gunichar uc); 485 iterator insert(iterator p, char c); 486 void insert(iterator p, size_type n, gunichar uc); 487 void insert(iterator p, size_type n, char c); 488 template <class In> 489 void insert(iterator p, In pbegin, In pend); 490 491 //! @} 492 //! @name Replace sub-strings. 493 //! @{ 494 495 ustring& replace(size_type i, size_type n, const ustring& src); 496 ustring& replace(size_type i, size_type n, const ustring& src, size_type i2, size_type n2); 497 ustring& replace(size_type i, size_type n, const char* src, size_type n2); 498 ustring& replace(size_type i, size_type n, const char* src); 499 ustring& replace(size_type i, size_type n, size_type n2, gunichar uc); 500 ustring& replace(size_type i, size_type n, size_type n2, char c); 501 502 ustring& replace(iterator pbegin, iterator pend, const ustring& src); 503 ustring& replace(iterator pbegin, iterator pend, const char* src, size_type n); 504 ustring& replace(iterator pbegin, iterator pend, const char* src); 505 ustring& replace(iterator pbegin, iterator pend, size_type n, gunichar uc); 506 ustring& replace(iterator pbegin, iterator pend, size_type n, char c); 507 template <class In> 508 ustring& replace(iterator pbegin, iterator pend, In pbegin2, In pend2); 509 510 //! @} 511 //! @name Erase sub-strings. 512 //! @{ 513 514 void clear(); 515 ustring& erase(size_type i, size_type n = npos); 516 ustring& erase(); 517 iterator erase(iterator p); 518 iterator erase(iterator pbegin, iterator pend); 519 520 //! @} 521 //! @name Compare and collate. 522 //! @{ 523 524 int compare(const ustring& rhs) const; 525 int compare(const char* rhs) const; 526 int compare(size_type i, size_type n, const ustring& rhs) const; 527 int compare(size_type i, size_type n, const ustring& rhs, size_type i2, size_type n2) const; 528 int compare(size_type i, size_type n, const char* rhs, size_type n2) const; 529 int compare(size_type i, size_type n, const char* rhs) const; 530 531 /*! Create a unique sorting key for the UTF-8 string. If you need to 532 * compare UTF-8 strings regularly, e.g. for sorted containers such as 533 * <tt>std::set<></tt>, you should consider creating a collate key first 534 * and compare this key instead of the actual string. 535 * 536 * The ustring::compare() methods as well as the relational operators 537 * <tt>== != < > <= >=</tt> are quite costly 538 * because they have to deal with %Unicode and the collation rules defined by 539 * the current locale. Converting both operands to UCS-4 is just the first 540 * of several costly steps involved when comparing ustrings. So be careful. 541 */ 542 std::string collate_key() const; 543 544 /*! Create a unique key for the UTF-8 string that can be used for caseless 545 * sorting. <tt>ustr.casefold_collate_key()</tt> results in the same string 546 * as <tt>ustr.casefold().collate_key()</tt>, but the former is likely more 547 * efficient. 548 */ 549 std::string casefold_collate_key() const; 550 551 //! @} 552 //! @name Extract characters and sub-strings. 553 //! @{ 554 555 /*! No reference return; use replace() to write characters. */ 556 value_type operator[](size_type i) const; 557 558 /*! No reference return; use replace() to write characters. @throw std::out_of_range */ 559 value_type at(size_type i) const; 560 561 inline ustring substr(size_type i = 0, size_type n = npos) const; 562 563 //! @} 564 //! @name Access a sequence of characters. 565 //! @{ 566 567 iterator begin(); 568 iterator end(); 569 const_iterator begin() const; 570 const_iterator end() const; 571 reverse_iterator rbegin(); 572 reverse_iterator rend(); 573 const_reverse_iterator rbegin() const; 574 const_reverse_iterator rend() const; 575 576 /** 577 * @newin{2,52} 578 */ 579 const_iterator cbegin() const; 580 581 /** 582 * @newin{2,52} 583 */ 584 const_iterator cend() const; 585 586 //! @} 587 //! @name Find sub-strings. 588 //! @{ 589 590 size_type find(const ustring& str, size_type i = 0) const; 591 size_type find(const char* str, size_type i, size_type n) const; 592 size_type find(const char* str, size_type i = 0) const; 593 size_type find(gunichar uc, size_type i = 0) const; 594 size_type find(char c, size_type i = 0) const; 595 596 size_type rfind(const ustring& str, size_type i = npos) const; 597 size_type rfind(const char* str, size_type i, size_type n) const; 598 size_type rfind(const char* str, size_type i = npos) const; 599 size_type rfind(gunichar uc, size_type i = npos) const; 600 size_type rfind(char c, size_type i = npos) const; 601 602 //! @} 603 //! @name Match against a set of characters. 604 //! @{ 605 606 size_type find_first_of(const ustring& match, size_type i = 0) const; 607 size_type find_first_of(const char* match, size_type i, size_type n) const; 608 size_type find_first_of(const char* match, size_type i = 0) const; 609 size_type find_first_of(gunichar uc, size_type i = 0) const; 610 size_type find_first_of(char c, size_type i = 0) const; 611 612 size_type find_last_of(const ustring& match, size_type i = npos) const; 613 size_type find_last_of(const char* match, size_type i, size_type n) const; 614 size_type find_last_of(const char* match, size_type i = npos) const; 615 size_type find_last_of(gunichar uc, size_type i = npos) const; 616 size_type find_last_of(char c, size_type i = npos) const; 617 618 size_type find_first_not_of(const ustring& match, size_type i = 0) const; 619 size_type find_first_not_of(const char* match, size_type i, size_type n) const; 620 size_type find_first_not_of(const char* match, size_type i = 0) const; 621 size_type find_first_not_of(gunichar uc, size_type i = 0) const; 622 size_type find_first_not_of(char c, size_type i = 0) const; 623 624 size_type find_last_not_of(const ustring& match, size_type i = npos) const; 625 size_type find_last_not_of(const char* match, size_type i, size_type n) const; 626 size_type find_last_not_of(const char* match, size_type i = npos) const; 627 size_type find_last_not_of(gunichar uc, size_type i = npos) const; 628 size_type find_last_not_of(char c, size_type i = npos) const; 629 630 //! @} 631 //! @name Retrieve the string's size. 632 //! @{ 633 634 /** Returns true if the string is empty. Equivalent to *this == "". 635 * @result Whether the string is empty. 636 */ 637 bool empty() const; 638 639 /** Returns the number of characters in the string, not including any null-termination. 640 * @result The number of UTF-8 characters. 641 * 642 * @see bytes(), empty() 643 */ 644 size_type size() const; 645 646 // We have length() as well as size(), because std::string has both. 647 648 /** This is the same as size(). 649 */ 650 size_type length() const; 651 652 /** Returns the number of bytes in the string, not including any null-termination. 653 * @result The number of bytes. 654 * 655 * @see size(), empty() 656 */ 657 size_type bytes() const; 658 659 //! @} 660 //! @name Change the string's size. 661 //! @{ 662 663 void resize(size_type n, gunichar uc); 664 void resize(size_type n, char c = '\0'); 665 666 //! @} 667 //! @name Control the allocated memory. 668 //! @{ 669 670 size_type capacity() const; 671 size_type max_size() const; 672 void reserve(size_type n = 0); 673 674 //! @} 675 //! @name Get a per-byte representation of the string. 676 //! @{ 677 678 inline operator std::string() const; // e.g. std::string str = ustring(); 679 inline const std::string& raw() const; 680 681 // Not necessarily an ASCII char*. Use g_utf8_*() where necessary. 682 const char* data() const; 683 const char* c_str() const; 684 685 /*! @return Number of copied @em bytes, not characters. */ 686 size_type copy(char* dest, size_type n, size_type i = 0) const; 687 688 //! @} 689 //! @name UTF-8 utilities. 690 //! @{ 691 692 /*! Check whether the string is valid UTF-8. */ 693 bool validate() const; 694 695 /*! Check whether the string is valid UTF-8. */ 696 bool validate(iterator& first_invalid); 697 698 /*! Check whether the string is valid UTF-8. */ 699 bool validate(const_iterator& first_invalid) const; 700 701 /*! Return a copy that is a valid UTF-8 string replacing invalid bytes 702 * in the original with %Unicode replacement character (U+FFFD). 703 * If the string is valid, return a copy of it. 704 */ 705 ustring make_valid() const; 706 707 /*! Check whether the string is plain 7-bit ASCII. @par 708 * Unlike any other ustring method, is_ascii() is safe to use on invalid 709 * UTF-8 strings. If the string isn't valid UTF-8, it cannot be valid 710 * ASCII either, therefore is_ascii() will just return @c false then. 711 * @return Whether the string contains only ASCII characters. 712 */ 713 bool is_ascii() const; 714 715 /*! "Normalize" the %Unicode character representation of the string. */ 716 ustring normalize(NormalizeMode mode = NORMALIZE_DEFAULT_COMPOSE) const; 717 718 //! @} 719 //! @name Character case conversion. 720 //! @{ 721 722 /*! Returns a new UTF-8 string with all characters characters converted to 723 * their uppercase equivalent, while honoring the current locale. The 724 * resulting string may change in the number of bytes as well as in the 725 * number of characters. For instance, the German sharp s 726 * <tt>"ß"</tt> will be replaced by two characters 727 * <tt>"SS"</tt> because there is no capital <tt>"ß"</tt>. 728 */ 729 ustring uppercase() const; 730 731 /*! Returns a new UTF-8 string with all characters characters converted to 732 * their lowercase equivalent, while honoring the current locale. The 733 * resulting string may change in the number of bytes as well as in the 734 * number of characters. 735 */ 736 ustring lowercase() const; 737 738 /*! Returns a caseless representation of the UTF-8 string. The resulting 739 * string doesn't correspond to any particular case, therefore the result 740 * is only useful to compare strings and should never be displayed to the 741 * user. 742 */ 743 ustring casefold() const; 744 745 //! @} 746 //! @name Message formatting. 747 //! @{ 748 749 /* Returns fmt as is, but checks for invalid references in the format string. 750 * @newin{2,18} 751 */ 752 template <class T1> 753 static inline ustring compose(const ustring& fmt); 754 755 /*! Substitute placeholders in a format string with the referenced arguments. 756 * The template string should be in <tt>qt-format</tt>, that is 757 * <tt>"%1"</tt>, <tt>"%2"</tt>, ..., <tt>"%9"</tt> are used as placeholders 758 * and <tt>"%%"</tt> denotes a literal <tt>"%"</tt>. Substitutions may be 759 * reordered. 760 * @par Example: 761 * @code 762 * using Glib::ustring; 763 * const int percentage = 50; 764 * const ustring text = ustring::compose("%1%% done", percentage); 765 * @endcode 766 * @param fmt A template string in <tt>qt-format</tt>. 767 * @param a1 The argument to substitute for <tt>"%1"</tt>. 768 * @return The substituted message string. 769 * @throw Glib::ConvertError 770 * 771 * @newin{2,16} 772 */ 773 template <class T1> 774 static inline ustring compose(const ustring& fmt, const T1& a1); 775 776 /* See the documentation for compose(const ustring& fmt, const T1& a1). 777 * @newin{2,16} 778 */ 779 template <class T1, class T2> 780 static inline ustring compose(const ustring& fmt, const T1& a1, const T2& a2); 781 782 /* See the documentation for compose(const ustring& fmt, const T1& a1). 783 * @newin{2,16} 784 */ 785 template <class T1, class T2, class T3> 786 static inline ustring compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3); 787 788 /* See the documentation for compose(const ustring& fmt, const T1& a1). 789 * @newin{2,16} 790 */ 791 template <class T1, class T2, class T3, class T4> 792 static inline ustring compose( 793 const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, const T4& a4); 794 795 /* See the documentation for compose(const ustring& fmt, const T1& a1). 796 * @newin{2,16} 797 */ 798 template <class T1, class T2, class T3, class T4, class T5> 799 static inline ustring compose( 800 const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5); 801 802 /* See the documentation for compose(const ustring& fmt, const T1& a1). 803 * @newin{2,16} 804 */ 805 template <class T1, class T2, class T3, class T4, class T5, class T6> 806 static inline ustring compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, 807 const T4& a4, const T5& a5, const T6& a6); 808 809 /* See the documentation for compose(const ustring& fmt, const T1& a1). 810 * @newin{2,16} 811 */ 812 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7> 813 static inline ustring compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, 814 const T4& a4, const T5& a5, const T6& a6, const T7& a7); 815 816 /* See the documentation for compose(const ustring& fmt, const T1& a1). 817 * @newin{2,16} 818 */ 819 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> 820 static inline ustring compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, 821 const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8); 822 823 /* See the documentation for compose(const ustring& fmt, const T1& a1). 824 * @newin{2,16} 825 */ 826 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, 827 class T9> 828 static inline ustring compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, 829 const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9); 830 831 /*! Format the argument to its string representation. 832 * Applies the arguments in order to an std::wostringstream and returns the 833 * resulting string. I/O manipulators may also be used as arguments. This 834 * greatly simplifies the common task of converting a number to a string, as 835 * demonstrated by the example below. The format() methods can also be used 836 * in conjunction with compose() to facilitate localization of user-visible 837 * messages. 838 * @code 839 * using Glib::ustring; 840 * double value = 22.0 / 7.0; 841 * ustring text = ustring::format(std::fixed, std::setprecision(2), value); 842 * @endcode 843 * @note The use of a wide character stream in the implementation of format() 844 * is almost completely transparent. However, one of the instances where the 845 * use of wide streams becomes visible is when the std::setfill() stream 846 * manipulator is used. In order for std::setfill() to work the argument 847 * must be of type <tt>wchar_t</tt>. This can be achieved by using the 848 * <tt>L</tt> prefix with a character literal, as shown in the example. 849 * @code 850 * using Glib::ustring; 851 * // Insert leading zeroes to fill in at least six digits 852 * ustring text = ustring::format(std::setfill(L'0'), std::setw(6), 123); 853 * @endcode 854 * 855 * @param a1 A streamable value or an I/O manipulator. 856 * @return The string representation of the argument stream. 857 * @throw Glib::ConvertError 858 * 859 * @newin{2,16} 860 */ 861 template <class T1> 862 static inline ustring format(const T1& a1); 863 864 /* See the documentation for format(const T1& a1). 865 * 866 * @newin{2,16} 867 */ 868 template <class T1, class T2> 869 static inline ustring format(const T1& a1, const T2& a2); 870 871 /* See the documentation for format(const T1& a1). 872 * 873 * @newin{2,16} 874 */ 875 template <class T1, class T2, class T3> 876 static inline ustring format(const T1& a1, const T2& a2, const T3& a3); 877 878 /* See the documentation for format(const T1& a1). 879 * 880 * @newin{2,16} 881 */ 882 template <class T1, class T2, class T3, class T4> 883 static inline ustring format(const T1& a1, const T2& a2, const T3& a3, const T4& a4); 884 885 /* See the documentation for format(const T1& a1). 886 * 887 * @newin{2,16} 888 */ 889 template <class T1, class T2, class T3, class T4, class T5> 890 static inline ustring format( 891 const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5); 892 893 /* See the documentation for format(const T1& a1). 894 * 895 * @newin{2,16} 896 */ 897 template <class T1, class T2, class T3, class T4, class T5, class T6> 898 static inline ustring format( 899 const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6); 900 901 /* See the documentation for format(const T1& a1). 902 * 903 * @newin{2,16} 904 */ 905 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7> 906 static inline ustring format(const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, 907 const T6& a6, const T7& a7); 908 909 /* See the documentation for format(const T1& a1). 910 * 911 * @newin{2,16} 912 */ 913 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> 914 static inline ustring format(const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, 915 const T6& a6, const T7& a7, const T8& a8); 916 917 /*! Substitute placeholders in a format string with the referenced arguments. 918 * 919 * This function takes a template string in the format used by C’s 920 * <tt>printf()</tt> family of functions and an arbitrary number of arguments, 921 * replaces each placeholder in the template with the formatted version of its 922 * corresponding argument at the same ordinal position in the list of 923 * subsequent arguments, and returns the result in a new Glib::ustring. 924 * 925 * Note: You must pass the correct count/types/order of arguments to match 926 * the format string, as when calling <tt>printf()</tt> directly. glibmm does 927 * not check this for you. Breaking this contract invokes undefined behavior 928 * and is a security risk. 929 * 930 * The exception is that glibmm special-cases std::string and Glib::ustring, 931 * so you can pass them in positions corresponding to <tt>%s</tt> placeholders 932 * without having to call their .c_str() functions; glibmm does that for you. 933 * glibmm also overloads sprintf() with @p fmt but no @p args to avoid risks. 934 * 935 * Said restriction also makes sprintf() unsuitable for translatable strings, 936 * as translators cannot reorder the placeholders to suit their language. If 937 * you wish to support translation, you should instead use compose(), as its 938 * placeholders are numbered rather than ordinal, so they can be moved freely. 939 * 940 * @par Example: 941 * @code 942 * 943 * const auto greeting = std::string{"Hi"}; 944 * const auto name = Glib::ustring{"Dennis"}; 945 * const auto your_cows = 3; 946 * const auto my_cows = 11; 947 * const auto cow_percentage = 100.0 * your_cows / my_cows; 948 * 949 * const auto text = Glib::ustring::sprintf( 950 * "%s, %s! You have %d cows. That's about %0.2f%% of the %d cows I have.", 951 * greeting, name, your_cows, cow_percentage, my_cows); 952 * 953 * std::cout << text; 954 * // Hi, Dennis! You have 3 cows. That's about 27.27% of the 11 cows I have. 955 * @endcode 956 * 957 * @param fmt The template string, in the format used by <tt>printf()</tt> et al. 958 * @param args A set of arguments having the count/types/order required by @a fmt. 959 * 960 * @return The substituted string. 961 * 962 * @newin{2,62} 963 */ 964 template <class... Ts> 965 static inline ustring sprintf(const ustring& fmt, const Ts&... args); 966 967 /*! Overload of sprintf() taking a string literal. 968 * 969 * The main benefit of this is not constructing a temporary ustring if @p fmt 970 * is a string literal. A secondary effect is that it might encourage compilers 971 * to check if the given format @p fmt matches the variadic arguments @p args. 972 * The latter effect is a convenience at best; you must not rely on it to find 973 * errors in your code, as your compiler might not always be able to do so. 974 * 975 * @param fmt The template string, in the format used by <tt>printf()</tt> et al. 976 * @param args A set of arguments having the count/types/order required by @a fmt. 977 * 978 * @return The substituted string. 979 * 980 * @newin{2,62} 981 */ 982 template <class... Ts> 983 static inline ustring sprintf(const char* fmt, const Ts&... args); 984 985 /*! Overload of sprintf() for a format string only, which returns it unchanged. 986 * 987 * If no @p args to be substituted are given, there is nothing to do, so the 988 * @p fmt string is returned as-is without substitution. This is an obvious 989 * case of mismatched format/args that we can check. Not doing so causes 990 * warnings/errors with common compiler options, as it is a security risk. 991 * 992 * @param fmt The string 993 * @return The same string. 994 * 995 * @newin{2,62} 996 */ 997 static inline ustring sprintf(const ustring& fmt); 998 999 /*! Overload of sprintf() for a format string only, which returns it unchanged 1000 * and avoids creating a temporary ustring as the argument. 1001 * 1002 * @param fmt The string 1003 * @return The same string, as a ustring. 1004 * 1005 * @newin{2,62} 1006 */ 1007 static inline ustring sprintf(const char* fmt); 1008 1009 //! @} 1010 1011 private: 1012 #ifndef DOXYGEN_SHOULD_SKIP_THIS 1013 1014 #ifdef GLIBMM_HAVE_STD_ITERATOR_TRAITS 1015 template <class In, class ValueType = typename std::iterator_traits<In>::value_type> 1016 #else 1017 template <class In, class ValueType = typename Glib::IteratorTraits<In>::value_type> 1018 #endif 1019 struct SequenceToString; 1020 1021 // The Tru64 compiler needs these partial specializations to be declared here, 1022 // as well as defined later. That's probably correct. murrayc. 1023 template <class In> 1024 struct SequenceToString<In, char>; 1025 template <class In> 1026 struct SequenceToString<In, gunichar>; 1027 1028 template <class T> 1029 class Stringify; 1030 class FormatStream; 1031 1032 static ustring compose_argv(const ustring& fmt, int argc, const ustring* const* argv); 1033 1034 template<class T> static inline const T& sprintify(const T& arg); 1035 static inline const char* sprintify(const ustring& arg); 1036 static inline const char* sprintify(const std::string& arg); 1037 1038 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 1039 1040 std::string string_; 1041 }; 1042 1043 #ifndef DOXYGEN_SHOULD_SKIP_THIS 1044 1045 template <class In, class ValueType> 1046 struct ustring::SequenceToString 1047 { 1048 }; 1049 1050 template <class In> 1051 struct ustring::SequenceToString<In, char> : public std::string 1052 { 1053 SequenceToString(In pbegin, In pend); 1054 }; 1055 1056 template <class In> 1057 struct ustring::SequenceToString<In, gunichar> : public std::string 1058 { 1059 SequenceToString(In pbegin, In pend); 1060 }; 1061 1062 template <> 1063 struct GLIBMM_API ustring::SequenceToString<Glib::ustring::iterator, gunichar> : public std::string 1064 { 1065 SequenceToString(Glib::ustring::iterator pbegin, Glib::ustring::iterator pend); 1066 }; 1067 1068 template <> 1069 struct GLIBMM_API ustring::SequenceToString<Glib::ustring::const_iterator, gunichar> : public std::string 1070 { 1071 SequenceToString(Glib::ustring::const_iterator pbegin, Glib::ustring::const_iterator pend); 1072 }; 1073 1074 1075 class GLIBMM_API ustring::FormatStream 1076 { 1077 public: 1078 // noncopyable 1079 FormatStream(const ustring::FormatStream&) = delete; 1080 FormatStream& operator=(const ustring::FormatStream&) = delete; 1081 1082 private: 1083 #ifdef GLIBMM_HAVE_WIDE_STREAM 1084 using StreamType = std::wostringstream; 1085 #else 1086 using StreamType = std::ostringstream; 1087 #endif 1088 StreamType stream_; 1089 1090 public: 1091 FormatStream(); 1092 ~FormatStream() noexcept; 1093 1094 template <class T> 1095 inline void stream(const T& value); 1096 1097 inline void stream(const char* value); 1098 1099 // This overload exists to avoid the templated stream() being called for non-const char*. 1100 inline void stream(char* value); 1101 1102 ustring to_string() const; 1103 }; 1104 1105 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 1106 1107 /** Stream input operator. 1108 * @relates Glib::ustring 1109 * @throw Glib::ConvertError 1110 */ 1111 GLIBMM_API 1112 std::istream& operator>>(std::istream& is, Glib::ustring& utf8_string); 1113 1114 /** Stream output operator. 1115 * @relates Glib::ustring 1116 * @throw Glib::ConvertError 1117 */ 1118 GLIBMM_API 1119 std::ostream& operator<<(std::ostream& os, const Glib::ustring& utf8_string); 1120 1121 #ifdef GLIBMM_HAVE_WIDE_STREAM 1122 1123 /** Wide stream input operator. 1124 * @relates Glib::ustring 1125 * @throw Glib::ConvertError 1126 */ 1127 GLIBMM_API 1128 std::wistream& operator>>(std::wistream& is, ustring& utf8_string); 1129 1130 /** Wide stream output operator. 1131 * @relates Glib::ustring 1132 * @throw Glib::ConvertError 1133 */ 1134 GLIBMM_API 1135 std::wostream& operator<<(std::wostream& os, const ustring& utf8_string); 1136 1137 #endif /* GLIBMM_HAVE_WIDE_STREAM */ 1138 1139 /***************************************************************************/ 1140 /* Inline implementation */ 1141 /***************************************************************************/ 1142 1143 #ifndef DOXYGEN_SHOULD_SKIP_THIS 1144 1145 /**** Glib::ustring_Iterator<> *********************************************/ 1146 1147 template <class T> 1148 inline ustring_Iterator<T>::ustring_Iterator(T pos) : pos_(pos) 1149 { 1150 } 1151 1152 template <class T> 1153 inline T 1154 ustring_Iterator<T>::base() const 1155 { 1156 return pos_; 1157 } 1158 1159 template <class T> 1160 inline ustring_Iterator<T>::ustring_Iterator() : pos_() 1161 { 1162 } 1163 1164 template <class T> 1165 inline ustring_Iterator<T>::ustring_Iterator(const ustring_Iterator<std::string::iterator>& other) 1166 : pos_(other.base()) 1167 { 1168 } 1169 1170 template <class T> 1171 inline typename ustring_Iterator<T>::value_type ustring_Iterator<T>::operator*() const 1172 { 1173 return Glib::get_unichar_from_std_iterator(pos_); 1174 } 1175 1176 template <class T> 1177 inline ustring_Iterator<T>& ustring_Iterator<T>::operator++() 1178 { 1179 pos_ += g_utf8_skip[static_cast<unsigned char>(*pos_)]; 1180 return *this; 1181 } 1182 1183 template <class T> 1184 inline const ustring_Iterator<T> ustring_Iterator<T>::operator++(int) 1185 { 1186 const ustring_Iterator<T> temp(*this); 1187 this->operator++(); 1188 return temp; 1189 } 1190 1191 template <class T> 1192 inline ustring_Iterator<T>& ustring_Iterator<T>::operator--() 1193 { 1194 while ((static_cast<unsigned char>(*--pos_) & 0xC0u) == 0x80) 1195 { 1196 ; 1197 } 1198 1199 return *this; 1200 } 1201 1202 template <class T> 1203 inline const ustring_Iterator<T> ustring_Iterator<T>::operator--(int) 1204 { 1205 const ustring_Iterator<T> temp(*this); 1206 this->operator--(); 1207 return temp; 1208 } 1209 1210 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 1211 1212 /** @relates Glib::ustring_Iterator */ 1213 inline bool 1214 operator==(const Glib::ustring::const_iterator& lhs, const Glib::ustring::const_iterator& rhs) 1215 { 1216 return (lhs.base() == rhs.base()); 1217 } 1218 1219 /** @relates Glib::ustring_Iterator */ 1220 inline bool 1221 operator!=(const Glib::ustring::const_iterator& lhs, const Glib::ustring::const_iterator& rhs) 1222 { 1223 return (lhs.base() != rhs.base()); 1224 } 1225 1226 /** @relates Glib::ustring_Iterator */ 1227 inline bool 1228 operator<(const Glib::ustring::const_iterator& lhs, const Glib::ustring::const_iterator& rhs) 1229 { 1230 return (lhs.base() < rhs.base()); 1231 } 1232 1233 /** @relates Glib::ustring_Iterator */ 1234 inline bool 1235 operator>(const Glib::ustring::const_iterator& lhs, const Glib::ustring::const_iterator& rhs) 1236 { 1237 return (lhs.base() > rhs.base()); 1238 } 1239 1240 /** @relates Glib::ustring_Iterator */ 1241 inline bool 1242 operator<=(const Glib::ustring::const_iterator& lhs, const Glib::ustring::const_iterator& rhs) 1243 { 1244 return (lhs.base() <= rhs.base()); 1245 } 1246 1247 /** @relates Glib::ustring_Iterator */ 1248 inline bool 1249 operator>=(const Glib::ustring::const_iterator& lhs, const Glib::ustring::const_iterator& rhs) 1250 { 1251 return (lhs.base() >= rhs.base()); 1252 } 1253 1254 #ifndef DOXYGEN_SHOULD_SKIP_THIS 1255 1256 /**** Glib::ustring::SequenceToString **************************************/ 1257 1258 template <class In> 1259 ustring::SequenceToString<In, char>::SequenceToString(In pbegin, In pend) 1260 : std::string(pbegin, pend) 1261 { 1262 } 1263 1264 template <class In> 1265 ustring::SequenceToString<In, gunichar>::SequenceToString(In pbegin, In pend) 1266 { 1267 char utf8_buf[6]; // stores a single UTF-8 character 1268 1269 for (; pbegin != pend; ++pbegin) 1270 { 1271 const std::string::size_type utf8_len = g_unichar_to_utf8(*pbegin, utf8_buf); 1272 this->append(utf8_buf, utf8_len); 1273 } 1274 } 1275 1276 /**** Glib::ustring::FormatStream ******************************************/ 1277 1278 template <class T> 1279 inline void 1280 ustring::FormatStream::stream(const T& value) 1281 { 1282 stream_ << value; 1283 } 1284 1285 inline void 1286 ustring::FormatStream::stream(const char* value) 1287 { 1288 stream_ << ustring(value); 1289 } 1290 1291 inline void 1292 ustring::FormatStream::stream(char* value) 1293 { 1294 stream_ << ustring(value); 1295 } 1296 1297 /**** Glib::ustring ********************************************************/ 1298 1299 template <class In> 1300 ustring::ustring(In pbegin, In pend) : string_(Glib::ustring::SequenceToString<In>(pbegin, pend)) 1301 { 1302 } 1303 1304 template <class In> 1305 ustring& 1306 ustring::assign(In pbegin, In pend) 1307 { 1308 Glib::ustring::SequenceToString<In> temp_string(pbegin, pend); 1309 string_.swap(temp_string); // constant-time operation 1310 return *this; 1311 } 1312 1313 template <class In> 1314 ustring& 1315 ustring::append(In pbegin, In pend) 1316 { 1317 string_.append(Glib::ustring::SequenceToString<In>(pbegin, pend)); 1318 return *this; 1319 } 1320 1321 template <class In> 1322 void 1323 ustring::insert(ustring::iterator p, In pbegin, In pend) 1324 { 1325 size_type pos = p.base() - string_.begin(); 1326 string_.insert(pos, Glib::ustring::SequenceToString<In>(pbegin, pend)); 1327 } 1328 1329 template <class In> 1330 ustring& 1331 ustring::replace(ustring::iterator pbegin, ustring::iterator pend, In pbegin2, In pend2) 1332 { 1333 string_.replace(pbegin.base(), pend.base(), Glib::ustring::SequenceToString<In>(pbegin2, pend2)); 1334 return *this; 1335 } 1336 1337 // The ustring methods substr() and operator std::string() are inline, 1338 // so that the compiler has a fair chance to optimize the copy ctor away. 1339 1340 inline ustring 1341 ustring::substr(ustring::size_type i, ustring::size_type n) const 1342 { 1343 return ustring(*this, i, n); 1344 } 1345 1346 inline ustring::operator std::string() const 1347 { 1348 return string_; 1349 } 1350 1351 inline const std::string& 1352 ustring::raw() const 1353 { 1354 return string_; 1355 } 1356 1357 template <class T1> 1358 inline // static 1359 ustring 1360 ustring::format(const T1& a1) 1361 { 1362 ustring::FormatStream buf; 1363 buf.stream(a1); 1364 return buf.to_string(); 1365 } 1366 1367 template <class T1, class T2> 1368 inline // static 1369 ustring 1370 ustring::format(const T1& a1, const T2& a2) 1371 { 1372 ustring::FormatStream buf; 1373 buf.stream(a1); 1374 buf.stream(a2); 1375 return buf.to_string(); 1376 } 1377 1378 template <class T1, class T2, class T3> 1379 inline // static 1380 ustring 1381 ustring::format(const T1& a1, const T2& a2, const T3& a3) 1382 { 1383 ustring::FormatStream buf; 1384 buf.stream(a1); 1385 buf.stream(a2); 1386 buf.stream(a3); 1387 return buf.to_string(); 1388 } 1389 1390 template <class T1, class T2, class T3, class T4> 1391 inline // static 1392 ustring 1393 ustring::format(const T1& a1, const T2& a2, const T3& a3, const T4& a4) 1394 { 1395 ustring::FormatStream buf; 1396 buf.stream(a1); 1397 buf.stream(a2); 1398 buf.stream(a3); 1399 buf.stream(a4); 1400 return buf.to_string(); 1401 } 1402 1403 template <class T1, class T2, class T3, class T4, class T5> 1404 inline // static 1405 ustring 1406 ustring::format(const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5) 1407 { 1408 ustring::FormatStream buf; 1409 buf.stream(a1); 1410 buf.stream(a2); 1411 buf.stream(a3); 1412 buf.stream(a4); 1413 buf.stream(a5); 1414 return buf.to_string(); 1415 } 1416 1417 template <class T1, class T2, class T3, class T4, class T5, class T6> 1418 inline // static 1419 ustring 1420 ustring::format( 1421 const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6) 1422 { 1423 ustring::FormatStream buf; 1424 buf.stream(a1); 1425 buf.stream(a2); 1426 buf.stream(a3); 1427 buf.stream(a4); 1428 buf.stream(a5); 1429 buf.stream(a6); 1430 return buf.to_string(); 1431 } 1432 1433 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7> 1434 inline // static 1435 ustring 1436 ustring::format(const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, 1437 const T6& a6, const T7& a7) 1438 { 1439 ustring::FormatStream buf; 1440 buf.stream(a1); 1441 buf.stream(a2); 1442 buf.stream(a3); 1443 buf.stream(a4); 1444 buf.stream(a5); 1445 buf.stream(a6); 1446 buf.stream(a7); 1447 return buf.to_string(); 1448 } 1449 1450 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> 1451 inline // static 1452 ustring 1453 ustring::format(const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, 1454 const T6& a6, const T7& a7, const T8& a8) 1455 { 1456 ustring::FormatStream buf; 1457 buf.stream(a1); 1458 buf.stream(a2); 1459 buf.stream(a3); 1460 buf.stream(a4); 1461 buf.stream(a5); 1462 buf.stream(a6); 1463 buf.stream(a7); 1464 buf.stream(a8); 1465 return buf.to_string(); 1466 } 1467 1468 /** An inner class used by ustring. 1469 */ 1470 template <class T> 1471 class ustring::Stringify 1472 { 1473 private: 1474 ustring string_; 1475 1476 public: 1477 explicit inline Stringify(const T& arg) : string_(ustring::format(arg)) {} 1478 1479 // TODO: Why is this here? See the template specialization: 1480 explicit inline Stringify(const char* arg) : string_(arg) {} 1481 1482 // noncopyable 1483 Stringify(const ustring::Stringify<T>&) = delete; 1484 Stringify<T>& operator=(const ustring::Stringify<T>&) = delete; 1485 1486 inline const ustring* ptr() const { return &string_; } 1487 }; 1488 1489 /// A template specialization for Stringify<ustring>: 1490 template <> 1491 class GLIBMM_API ustring::Stringify<ustring> 1492 { 1493 private: 1494 const ustring& string_; 1495 1496 public: 1497 explicit inline Stringify(const ustring& arg) : string_(arg) {} 1498 1499 // noncopyable 1500 Stringify(const ustring::Stringify<ustring>&) = delete; 1501 Stringify<ustring>& operator=(const ustring::Stringify<ustring>&) = delete; 1502 1503 inline const ustring* ptr() const { return &string_; } 1504 }; 1505 1506 /** A template specialization for Stringify<const char*>, 1507 * because the regular template has ambiguous constructor overloads for char*. 1508 */ 1509 template <> 1510 class GLIBMM_API ustring::Stringify<const char*> 1511 { 1512 private: 1513 const ustring string_; 1514 1515 public: 1516 explicit inline Stringify(const char* arg) : string_(arg) {} 1517 1518 // noncopyable 1519 Stringify(const ustring::Stringify<const char*>&) = delete; 1520 Stringify<ustring>& operator=(const ustring::Stringify<const char*>&) = delete; 1521 1522 inline const ustring* ptr() const { return &string_; } 1523 }; 1524 1525 /** A template specialization for Stringify<char[N]> (for string literals), 1526 * because the regular template has ambiguous constructor overloads for char*. 1527 */ 1528 template <std::size_t N> 1529 class ustring::Stringify<char[N]> 1530 { 1531 private: 1532 const ustring string_; 1533 1534 public: 1535 explicit inline Stringify(const char arg[N]) : string_(arg) {} 1536 1537 // noncopyable 1538 Stringify(const ustring::Stringify<char[N]>&) = delete; 1539 Stringify<ustring>& operator=(const ustring::Stringify<char[N]>&) = delete; 1540 1541 inline const ustring* ptr() const { return &string_; } 1542 }; 1543 1544 /** A template specialization for Stringify<const char[N]> (for string literals), 1545 * because the regular template has ambiguous constructor overloads for char* 1546 * on later versions of Visual C++ (2008 and later at least). 1547 */ 1548 template <std::size_t N> 1549 class ustring::Stringify<const char[N]> 1550 { 1551 private: 1552 const ustring string_; 1553 1554 public: 1555 explicit inline Stringify(const char arg[N]) : string_(arg) {} 1556 1557 // noncopyable 1558 Stringify(const ustring::Stringify<const char[N]>&) = delete; 1559 Stringify<ustring>& operator=(const ustring::Stringify<const char[N]>&) = delete; 1560 1561 inline const ustring* ptr() const { return &string_; } 1562 }; 1563 1564 template <class T1> 1565 inline // static 1566 ustring 1567 ustring::compose(const ustring& fmt) 1568 { 1569 return ustring::compose_argv(fmt, 0, nullptr); 1570 } 1571 1572 /* These helper functions used by ustring::sprintf() let users pass C++ strings 1573 * to match %s placeholders, without the hassle of writing .c_str() in user code 1574 */ 1575 template<typename T> 1576 inline // static 1577 const T& 1578 ustring::sprintify(const T& arg) 1579 { 1580 return arg; 1581 } 1582 1583 inline // static 1584 const char* 1585 ustring::sprintify(const ustring& arg) 1586 { 1587 return arg.c_str(); 1588 } 1589 1590 inline // static 1591 const char* 1592 ustring::sprintify(const std::string& arg) 1593 { 1594 return arg.c_str(); 1595 } 1596 1597 // Public methods 1598 1599 template <class T1> 1600 inline // static 1601 ustring 1602 ustring::compose(const ustring& fmt, const T1& a1) 1603 { 1604 const ustring::Stringify<T1> s1(a1); 1605 1606 const ustring* const argv[] = { s1.ptr() }; 1607 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1608 } 1609 1610 template <class T1, class T2> 1611 inline // static 1612 ustring 1613 ustring::compose(const ustring& fmt, const T1& a1, const T2& a2) 1614 { 1615 const ustring::Stringify<T1> s1(a1); 1616 const ustring::Stringify<T2> s2(a2); 1617 1618 const ustring* const argv[] = { s1.ptr(), s2.ptr() }; 1619 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1620 } 1621 1622 template <class T1, class T2, class T3> 1623 inline // static 1624 ustring 1625 ustring::compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3) 1626 { 1627 const ustring::Stringify<T1> s1(a1); 1628 const ustring::Stringify<T2> s2(a2); 1629 const ustring::Stringify<T3> s3(a3); 1630 1631 const ustring* const argv[] = { s1.ptr(), s2.ptr(), s3.ptr() }; 1632 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1633 } 1634 1635 template <class T1, class T2, class T3, class T4> 1636 inline // static 1637 ustring 1638 ustring::compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, const T4& a4) 1639 { 1640 const ustring::Stringify<T1> s1(a1); 1641 const ustring::Stringify<T2> s2(a2); 1642 const ustring::Stringify<T3> s3(a3); 1643 const ustring::Stringify<T4> s4(a4); 1644 1645 const ustring* const argv[] = { s1.ptr(), s2.ptr(), s3.ptr(), s4.ptr() }; 1646 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1647 } 1648 1649 template <class T1, class T2, class T3, class T4, class T5> 1650 inline // static 1651 ustring 1652 ustring::compose( 1653 const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5) 1654 { 1655 const ustring::Stringify<T1> s1(a1); 1656 const ustring::Stringify<T2> s2(a2); 1657 const ustring::Stringify<T3> s3(a3); 1658 const ustring::Stringify<T4> s4(a4); 1659 const ustring::Stringify<T5> s5(a5); 1660 1661 const ustring* const argv[] = { s1.ptr(), s2.ptr(), s3.ptr(), s4.ptr(), s5.ptr() }; 1662 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1663 } 1664 1665 template <class T1, class T2, class T3, class T4, class T5, class T6> 1666 inline // static 1667 ustring 1668 ustring::compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, const T4& a4, 1669 const T5& a5, const T6& a6) 1670 { 1671 const ustring::Stringify<T1> s1(a1); 1672 const ustring::Stringify<T2> s2(a2); 1673 const ustring::Stringify<T3> s3(a3); 1674 const ustring::Stringify<T4> s4(a4); 1675 const ustring::Stringify<T5> s5(a5); 1676 const ustring::Stringify<T6> s6(a6); 1677 1678 const ustring* const argv[] = { s1.ptr(), s2.ptr(), s3.ptr(), s4.ptr(), s5.ptr(), s6.ptr() }; 1679 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1680 } 1681 1682 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7> 1683 inline // static 1684 ustring 1685 ustring::compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, const T4& a4, 1686 const T5& a5, const T6& a6, const T7& a7) 1687 { 1688 const ustring::Stringify<T1> s1(a1); 1689 const ustring::Stringify<T2> s2(a2); 1690 const ustring::Stringify<T3> s3(a3); 1691 const ustring::Stringify<T4> s4(a4); 1692 const ustring::Stringify<T5> s5(a5); 1693 const ustring::Stringify<T6> s6(a6); 1694 const ustring::Stringify<T7> s7(a7); 1695 1696 const ustring* const argv[] = { s1.ptr(), s2.ptr(), s3.ptr(), s4.ptr(), s5.ptr(), s6.ptr(), 1697 s7.ptr() }; 1698 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1699 } 1700 1701 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> 1702 inline // static 1703 ustring 1704 ustring::compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, const T4& a4, 1705 const T5& a5, const T6& a6, const T7& a7, const T8& a8) 1706 { 1707 const ustring::Stringify<T1> s1(a1); 1708 const ustring::Stringify<T2> s2(a2); 1709 const ustring::Stringify<T3> s3(a3); 1710 const ustring::Stringify<T4> s4(a4); 1711 const ustring::Stringify<T5> s5(a5); 1712 const ustring::Stringify<T6> s6(a6); 1713 const ustring::Stringify<T7> s7(a7); 1714 const ustring::Stringify<T8> s8(a8); 1715 1716 const ustring* const argv[] = { s1.ptr(), s2.ptr(), s3.ptr(), s4.ptr(), s5.ptr(), s6.ptr(), 1717 s7.ptr(), s8.ptr() }; 1718 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1719 } 1720 1721 template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9> 1722 inline // static 1723 ustring 1724 ustring::compose(const ustring& fmt, const T1& a1, const T2& a2, const T3& a3, const T4& a4, 1725 const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9) 1726 { 1727 const ustring::Stringify<T1> s1(a1); 1728 const ustring::Stringify<T2> s2(a2); 1729 const ustring::Stringify<T3> s3(a3); 1730 const ustring::Stringify<T4> s4(a4); 1731 const ustring::Stringify<T5> s5(a5); 1732 const ustring::Stringify<T6> s6(a6); 1733 const ustring::Stringify<T7> s7(a7); 1734 const ustring::Stringify<T8> s8(a8); 1735 const ustring::Stringify<T9> s9(a9); 1736 1737 const ustring* const argv[] = { s1.ptr(), s2.ptr(), s3.ptr(), s4.ptr(), s5.ptr(), s6.ptr(), 1738 s7.ptr(), s8.ptr(), s9.ptr() }; 1739 return ustring::compose_argv(fmt, G_N_ELEMENTS(argv), argv); 1740 } 1741 1742 template <class... Ts> 1743 inline // static 1744 ustring 1745 ustring::sprintf(const ustring& fmt, const Ts&... args) 1746 { 1747 return sprintf(fmt.c_str(), args...); 1748 } 1749 1750 template <class... Ts> 1751 inline // static 1752 ustring 1753 ustring::sprintf(const char* fmt, const Ts&... args) 1754 { 1755 auto c_str = g_strdup_printf(fmt, sprintify(args)...); 1756 Glib::ustring ustr(c_str); 1757 g_free(c_str); 1758 1759 return ustr; 1760 } 1761 1762 inline // static 1763 ustring 1764 ustring::sprintf(const ustring& fmt) 1765 { 1766 return fmt; 1767 } 1768 1769 inline // static 1770 ustring 1771 ustring::sprintf(const char* fmt) 1772 { 1773 return ustring(fmt); 1774 } 1775 1776 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 1777 1778 /** @relates Glib::ustring */ 1779 inline void 1780 swap(ustring& lhs, ustring& rhs) 1781 { 1782 lhs.swap(rhs); 1783 } 1784 1785 /**** Glib::ustring -- comparison operators ********************************/ 1786 1787 /** @relates Glib::ustring */ 1788 inline bool 1789 operator==(const ustring& lhs, const ustring& rhs) 1790 { 1791 return (lhs.compare(rhs) == 0); 1792 } 1793 1794 /** @relates Glib::ustring */ 1795 inline bool 1796 operator==(const ustring& lhs, const char* rhs) 1797 { 1798 return (lhs.compare(rhs) == 0); 1799 } 1800 1801 /** @relates Glib::ustring */ 1802 inline bool 1803 operator==(const char* lhs, const ustring& rhs) 1804 { 1805 return (rhs.compare(lhs) == 0); 1806 } 1807 1808 /** @relates Glib::ustring */ 1809 inline bool 1810 operator!=(const ustring& lhs, const ustring& rhs) 1811 { 1812 return (lhs.compare(rhs) != 0); 1813 } 1814 1815 /** @relates Glib::ustring */ 1816 inline bool 1817 operator!=(const ustring& lhs, const char* rhs) 1818 { 1819 return (lhs.compare(rhs) != 0); 1820 } 1821 1822 /** @relates Glib::ustring */ 1823 inline bool 1824 operator!=(const char* lhs, const ustring& rhs) 1825 { 1826 return (rhs.compare(lhs) != 0); 1827 } 1828 1829 /** @relates Glib::ustring */ 1830 inline bool 1831 operator<(const ustring& lhs, const ustring& rhs) 1832 { 1833 return (lhs.compare(rhs) < 0); 1834 } 1835 1836 /** @relates Glib::ustring */ 1837 inline bool 1838 operator<(const ustring& lhs, const char* rhs) 1839 { 1840 return (lhs.compare(rhs) < 0); 1841 } 1842 1843 /** @relates Glib::ustring */ 1844 inline bool 1845 operator<(const char* lhs, const ustring& rhs) 1846 { 1847 return (rhs.compare(lhs) > 0); 1848 } 1849 1850 /** @relates Glib::ustring */ 1851 inline bool 1852 operator>(const ustring& lhs, const ustring& rhs) 1853 { 1854 return (lhs.compare(rhs) > 0); 1855 } 1856 1857 /** @relates Glib::ustring */ 1858 inline bool 1859 operator>(const ustring& lhs, const char* rhs) 1860 { 1861 return (lhs.compare(rhs) > 0); 1862 } 1863 1864 /** @relates Glib::ustring */ 1865 inline bool 1866 operator>(const char* lhs, const ustring& rhs) 1867 { 1868 return (rhs.compare(lhs) < 0); 1869 } 1870 1871 /** @relates Glib::ustring */ 1872 inline bool 1873 operator<=(const ustring& lhs, const ustring& rhs) 1874 { 1875 return (lhs.compare(rhs) <= 0); 1876 } 1877 1878 /** @relates Glib::ustring */ 1879 inline bool 1880 operator<=(const ustring& lhs, const char* rhs) 1881 { 1882 return (lhs.compare(rhs) <= 0); 1883 } 1884 1885 /** @relates Glib::ustring */ 1886 inline bool 1887 operator<=(const char* lhs, const ustring& rhs) 1888 { 1889 return (rhs.compare(lhs) >= 0); 1890 } 1891 1892 /** @relates Glib::ustring */ 1893 inline bool 1894 operator>=(const ustring& lhs, const ustring& rhs) 1895 { 1896 return (lhs.compare(rhs) >= 0); 1897 } 1898 1899 /** @relates Glib::ustring */ 1900 inline bool 1901 operator>=(const ustring& lhs, const char* rhs) 1902 { 1903 return (lhs.compare(rhs) >= 0); 1904 } 1905 1906 /** @relates Glib::ustring */ 1907 inline bool 1908 operator>=(const char* lhs, const ustring& rhs) 1909 { 1910 return (rhs.compare(lhs) <= 0); 1911 } 1912 1913 #ifndef DOXYGEN_SHOULD_SKIP_THIS 1914 // Don't allow implicit conversion of integer 0 to nullptr in the relational operators. 1915 // If the int versions of the relational operators are not deleted, attempts to 1916 // compare with other integer values than 0 can result in really unexpected behaviour. 1917 // See https://bugzilla.gnome.org/show_bug.cgi?id=572978#c10 1918 bool operator==(const ustring& lhs, int rhs) = delete; 1919 bool operator==(int lhs, const ustring& rhs) = delete; 1920 bool operator!=(const ustring& lhs, int rhs) = delete; 1921 bool operator!=(int lhs, const ustring& rhs) = delete; 1922 bool operator<(const ustring& lhs, int rhs) = delete; 1923 bool operator<(int lhs, const ustring& rhs) = delete; 1924 bool operator>(const ustring& lhs, int rhs) = delete; 1925 bool operator>(int lhs, const ustring& rhs) = delete; 1926 bool operator<=(const ustring& lhs, int rhs) = delete; 1927 bool operator<=(int lhs, const ustring& rhs) = delete; 1928 bool operator>=(const ustring& lhs, int rhs) = delete; 1929 bool operator>=(int lhs, const ustring& rhs) = delete; 1930 #endif // DOXYGEN_SHOULD_SKIP_THIS 1931 1932 /**** Glib::ustring -- concatenation operators *****************************/ 1933 1934 /** @relates Glib::ustring */ 1935 inline ustring 1936 operator+(const ustring& lhs, const ustring& rhs) 1937 { 1938 ustring temp(lhs); 1939 temp += rhs; 1940 return temp; 1941 } 1942 1943 /** @relates Glib::ustring */ 1944 inline ustring 1945 operator+(const ustring& lhs, const char* rhs) 1946 { 1947 ustring temp(lhs); 1948 temp += rhs; 1949 return temp; 1950 } 1951 1952 /** @relates Glib::ustring */ 1953 inline ustring 1954 operator+(const char* lhs, const ustring& rhs) 1955 { 1956 ustring temp(lhs); 1957 temp += rhs; 1958 return temp; 1959 } 1960 1961 /** @relates Glib::ustring */ 1962 inline ustring 1963 operator+(const ustring& lhs, gunichar rhs) 1964 { 1965 ustring temp(lhs); 1966 temp += rhs; 1967 return temp; 1968 } 1969 1970 /** @relates Glib::ustring */ 1971 inline ustring 1972 operator+(gunichar lhs, const ustring& rhs) 1973 { 1974 ustring temp(1, lhs); 1975 temp += rhs; 1976 return temp; 1977 } 1978 1979 /** @relates Glib::ustring */ 1980 inline ustring 1981 operator+(const ustring& lhs, char rhs) 1982 { 1983 ustring temp(lhs); 1984 temp += rhs; 1985 return temp; 1986 } 1987 1988 /** @relates Glib::ustring */ 1989 inline ustring 1990 operator+(char lhs, const ustring& rhs) 1991 { 1992 ustring temp(1, lhs); 1993 temp += rhs; 1994 return temp; 1995 } 1996 1997 //********** Glib::StdStringView and Glib::UStringView ************* 1998 1999 inline UStringView::UStringView(const ustring& s) : pstring_(s.c_str()) {} 2000 2001 } // namespace Glib 2002 2003 #endif /* _GLIBMM_USTRING_H */ 2004