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>==&nbsp;!=&nbsp;<&nbsp;>&nbsp;<=&nbsp;>=</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&nbsp;-- more commonly known as
237  * ASCII&nbsp;-- 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&nbsp;-- 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>==&nbsp;!=&nbsp;<&nbsp;>&nbsp;<=&nbsp;>=</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&nbsp;s
726    * <tt>&quot;&szlig;&quot;</tt> will be replaced by two characters
727    * <tt>"SS"</tt> because there is no capital <tt>&quot;&szlig;&quot;</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