TGUI 1.11
Loading...
Searching...
No Matches
String.hpp
1
2//
3// TGUI - Texus' Graphical User Interface
4// Copyright (C) 2012-2025 Bruno Van de Velde (vdv_b@tgui.eu)
5//
6// This software is provided 'as-is', without any express or implied warranty.
7// In no event will the authors be held liable for any damages arising from the use of this software.
8//
9// Permission is granted to anyone to use this software for any purpose,
10// including commercial applications, and to alter it and redistribute it freely,
11// subject to the following restrictions:
12//
13// 1. The origin of this software must not be misrepresented;
14// you must not claim that you wrote the original software.
15// If you use this software in a product, an acknowledgment
16// in the product documentation would be appreciated but is not required.
17//
18// 2. Altered source versions must be plainly marked as such,
19// and must not be misrepresented as being the original software.
20//
21// 3. This notice may not be removed or altered from any source distribution.
22//
24
25#ifndef TGUI_STRING_HPP
26#define TGUI_STRING_HPP
27
28#include <TGUI/Config.hpp>
29#include <TGUI/StringView.hpp>
30#include <TGUI/Utf.hpp>
31
32#include <string>
33#include <vector>
34#include <cstring>
35#include <locale>
36#include <iomanip>
37#include <ostream>
38#include <sstream>
39#include <type_traits>
40#include <initializer_list>
41
42#if TGUI_HAS_WINDOW_BACKEND_SFML
43 #include <SFML/System/String.hpp>
44#endif
45
47
48namespace tgui
49{
55 TGUI_NODISCARD TGUI_API bool isWhitespace(char character);
56
62 TGUI_NODISCARD TGUI_API bool isWhitespace(char32_t character);
63
69 TGUI_NODISCARD TGUI_API bool isAlpha(char32_t character);
70
76 TGUI_NODISCARD TGUI_API bool isDigit(char32_t character);
77
78
93 class TGUI_API String
94 {
95 private:
96 std::u32string m_string;
97
98#if TGUI_COMPILED_WITH_CPP_VER >= 17
99 // Helper to check if template parameter is a string_view
100 template <typename StringViewType>
101 using IsStringViewType = std::enable_if_t<
102 std::is_same_v<StringViewType, std::string_view>
103#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201811L)
104 || std::is_same_v<StringViewType, std::u8string_view>
105#endif
106 || std::is_same_v<StringViewType, std::wstring_view>
107 || std::is_same_v<StringViewType, std::u16string_view>
108 || std::is_same_v<StringViewType, std::u32string_view>,
109 void>;
110#endif
111
112 public:
113
114#if TGUI_COMPILED_WITH_CPP_VER >= 17
115 static constexpr auto npos = std::u32string_view::npos;
116#else
117 static const decltype(std::u32string::npos) npos;
118#endif
119
120 using iterator = std::u32string::iterator;
121 using const_iterator = std::u32string::const_iterator;
122 using reverse_iterator = std::u32string::reverse_iterator;
123 using const_reverse_iterator = std::u32string::const_reverse_iterator;
124
125 using value_type = char32_t;
126 using reference = char32_t&;
127 using const_reference = const char32_t&;
128
129 public:
130
138 TGUI_NODISCARD bool attemptToInt(int& result) const;
139
147 TGUI_NODISCARD bool attemptToUInt(unsigned int& result) const;
148
156 TGUI_NODISCARD bool attemptToFloat(float& result) const;
157
165 TGUI_NODISCARD int toInt(int defaultValue = 0) const;
166
174 TGUI_NODISCARD unsigned int toUInt(unsigned int defaultValue = 0) const;
175
183 TGUI_NODISCARD float toFloat(float defaultValue = 0) const;
184
190 TGUI_NODISCARD String trim() const;
191
197 TGUI_NODISCARD String toLower() const;
198
204 TGUI_NODISCARD String toUpper() const;
205
213 TGUI_NODISCARD bool equalIgnoreCase(const String& other) const;
214
215#ifndef TGUI_REMOVE_DEPRECATED_CODE
225 TGUI_DEPRECATED("Use starts_with instead") TGUI_NODISCARD bool startsWith(const String& substring) const;
226#endif
227
235 TGUI_NODISCARD bool startsWithIgnoreCase(const String& substring) const;
236
237#ifndef TGUI_REMOVE_DEPRECATED_CODE
247 TGUI_DEPRECATED("Use ends_with instead") TGUI_NODISCARD bool endsWith(const String& substring) const;
248#endif
249
257 TGUI_NODISCARD bool endsWithIgnoreCase(const String& substring) const;
258
267 String& replace(const String& searchFor, const String& replaceWith);
268
274 void remove(const String& substring);
275
282 TGUI_NODISCARD std::vector<String> split(const String& delimiter, bool trim = false) const;
283
290 TGUI_NODISCARD static String join(const std::vector<String>& segments, const String& separator);
291
299 template <typename T>
300 TGUI_NODISCARD static String fromNumber(T value)
301 {
302 // If the value is a floating point then we can't use std::to_string because its result depends on the locale.
303 // If the value is an 8-bit type (e.g. uint8_t and int8_t) then using std::ostringstream results in the wrong result,
304 // as it will be interpreted as a character instead of a number.
305 TGUI_IF_CONSTEXPR (std::is_integral<T>::value)
306 {
307 return {std::to_string(value)};
308 }
309 else
310 {
311 std::ostringstream oss;
312 oss.imbue(std::locale::classic());
313 oss << value;
314 return {oss.str()};
315 }
316 }
317
326 template <typename T>
327 TGUI_NODISCARD static String fromNumberRounded(T value, unsigned int decimals)
328 {
329 // Precision is ignored by std::ostringstream for integers, so we use std::to_string for integers instead.
330 // If the value is an 8-bit type (e.g. uint8_t and int8_t) then using std::ostringstream results in the wrong result,
331 // as it will be interpreted as a character instead of a number. Which is why this separate branch for integers exists.
332 TGUI_IF_CONSTEXPR (std::is_integral<T>::value)
333 return {std::to_string(value)};
334 else
335 {
336 std::ostringstream oss;
337 oss.imbue(std::locale::classic());
338 oss << std::fixed << std::setprecision(static_cast<int>(decimals));
339 oss << value;
340 return {oss.str()};
341 }
342 }
343
345 public:
346
347 String() = default;
348
349 String(const std::string& str);
350 String(const std::wstring& str);
351 String(const std::u16string& str);
352 String(const std::u32string& str);
353
354 String(std::u32string&& str) :
355 m_string{std::move(str)}
356 {
357 }
358
359 String(char ansiChar);
360 String(wchar_t wideChar);
361 String(char16_t utfChar);
362 String(char32_t utfChar);
363
364 String(const char* str);
365 String(const wchar_t* str);
366 String(const char16_t* str);
367 String(const char32_t* str) :
368 m_string{str}
369 {
370 }
371
372 // Constructor to initialize the string from a number (integer or float)
373 template <typename T, typename = typename std::enable_if_t<std::is_arithmetic<T>::value, T>>
374 explicit String(T number) :
375 String{fromNumber(number)}
376 {
377 }
378
379 String(std::size_t count, char ch);
380 String(std::size_t count, wchar_t ch);
381 String(std::size_t count, char16_t ch);
382 String(std::size_t count, char32_t ch);
383
384 String(const std::string& str, std::size_t pos);
385 String(const std::wstring& str, std::size_t pos);
386 String(const std::u16string& str, std::size_t pos);
387 String(const std::u32string& str, std::size_t pos);
388
389 String(const std::string& str, std::size_t pos, std::size_t count);
390 String(const std::wstring& str, std::size_t pos, std::size_t count);
391 String(const std::u16string& str, std::size_t pos, std::size_t count);
392 String(const std::u32string& str, std::size_t pos, std::size_t count);
393
394 String(const char* str, std::size_t count);
395 String(const wchar_t* str, std::size_t count);
396 String(const char16_t* str, std::size_t count);
397 String(const char32_t* str, std::size_t count);
398
399 explicit String(std::initializer_list<char> chars);
400 explicit String(std::initializer_list<wchar_t> chars);
401 explicit String(std::initializer_list<char16_t> chars);
402 explicit String(std::initializer_list<char32_t> chars);
403
404 // Constructors using iterators have to be explicit to prevent {"1", "2"} to be ambiguous between String and std::vector<String>.
405 // The reason these constructors were considered a candicate to clang is due to a private constructor in the iterator class.
406 // We can't accept string_view::const_iterator iterators, because it would lead to the same kind of ambiguity even when the
407 // constructor is marked explicit (in GCC but not MSVC if we define the function normally, in MSVC but not GCC if we use a template).
408 explicit String(std::string::const_iterator first, std::string::const_iterator last);
409 explicit String(std::wstring::const_iterator first, std::wstring::const_iterator last);
410 explicit String(std::u16string::const_iterator first, std::u16string::const_iterator last);
411 explicit String(std::u32string::const_iterator first, std::u32string::const_iterator last);
412
413#if TGUI_COMPILED_WITH_CPP_VER >= 17
414 template <typename StringViewType, typename = IsStringViewType<StringViewType>>
415 explicit String(const StringViewType& stringView) :
416 String(stringView.data(), stringView.size())
417 {
418 }
419
420 template <typename StringViewType, typename = IsStringViewType<StringViewType>>
421 explicit String(const StringViewType& stringView, std::size_t pos, std::size_t count) :
422 String(stringView.data() + pos, count)
423 {
424 }
425#else
426 template <typename CharType>
427 explicit String(StringViewImpl<CharType> stringView) :
428 String(stringView.data(), stringView.size())
429 {
430 }
431
432 template <typename CharType>
433 explicit String(StringViewImpl<CharType> stringView, std::size_t pos, std::size_t count) :
434 String(stringView.data() + pos, count)
435 {
436 }
437#endif
438
439#if TGUI_HAS_WINDOW_BACKEND_SFML
440 // This constructor has to be explicit or it will cause MSVC to no longer compile code that performs sf::String + std::string
441 explicit String(const sf::String& str)
442 #if SFML_VERSION_MAJOR >= 3
443 : m_string{str.toUtf32()}
444 #else
445 : m_string{reinterpret_cast<const char32_t*>(str.toUtf32().c_str())}
446 #endif
447 {
448 }
449
450 explicit operator sf::String() const
451 {
452 return sf::String::fromUtf32(m_string.begin(), m_string.end());
453 }
454#endif
455
456 explicit operator std::string() const;
457 explicit operator std::wstring() const;
458 explicit operator std::u16string() const;
459 explicit operator const std::u32string&() const
460 {
461 return m_string;
462 }
463
464 operator StringView() const noexcept
465 {
466#if TGUI_COMPILED_WITH_CPP_VER >= 17
467 return m_string;
468#else
469 return StringView(m_string.data(), m_string.length());
470#endif
471 }
472
473 TGUI_NODISCARD std::string toStdString() const;
474 TGUI_NODISCARD std::wstring toWideString() const;
475 TGUI_NODISCARD std::u16string toUtf16() const;
476 TGUI_NODISCARD const std::u32string& toUtf32() const
477 {
478 return m_string;
479 }
480
481 String& assign(std::size_t count, char ch);
482 String& assign(std::size_t count, wchar_t ch);
483 String& assign(std::size_t count, char16_t ch);
484 String& assign(std::size_t count, char32_t ch);
485
486 String& assign(StringView sv);
487 String& assign(const char32_t* str);
488 String& assign(const std::u32string& str);
489 String& assign(const String& str);
490
491 String& assign(StringView sv, std::size_t pos, std::size_t count = npos);
492 String& assign(const std::string& str, std::size_t pos, std::size_t count = npos);
493 String& assign(const std::wstring& str, std::size_t pos, std::size_t count = npos);
494 String& assign(const std::u16string& str, std::size_t pos, std::size_t count = npos);
495 String& assign(const std::u32string& str, std::size_t pos, std::size_t count = npos);
496 String& assign(const String& str, std::size_t pos, std::size_t count = npos);
497
498 String& assign(std::u32string&& str);
499 String& assign(String&& str);
500
501 String& assign(const char* str, std::size_t count);
502 String& assign(const wchar_t* str, std::size_t count);
503 String& assign(const char16_t* str, std::size_t count);
504 String& assign(const char32_t* str, std::size_t count);
505
506 String& assign(std::initializer_list<char> chars);
507 String& assign(std::initializer_list<wchar_t> chars);
508 String& assign(std::initializer_list<char16_t> chars);
509 String& assign(std::initializer_list<char32_t> chars);
510
511 String& assign(std::string::const_iterator first, std::string::const_iterator last);
512 String& assign(std::wstring::const_iterator first, std::wstring::const_iterator last);
513 String& assign(std::u16string::const_iterator first, std::u16string::const_iterator last);
514 String& assign(std::u32string::const_iterator first, std::u32string::const_iterator last);
515 String& assign(StringView::const_iterator first, StringView::const_iterator last);
516
517 TGUI_NODISCARD reference at(std::size_t pos);
518 TGUI_NODISCARD const_reference at(std::size_t pos) const;
519
520 TGUI_NODISCARD const_reference operator [](std::size_t index) const;
521 TGUI_NODISCARD reference operator [](std::size_t index);
522
523 TGUI_NODISCARD reference front();
524 TGUI_NODISCARD const_reference front() const;
525
526 TGUI_NODISCARD reference back();
527 TGUI_NODISCARD const_reference back() const;
528
529 TGUI_NODISCARD const char32_t* data() const noexcept
530 {
531 return m_string.data();
532 }
533
534 TGUI_NODISCARD char32_t* data() noexcept
535 {
536#if __cplusplus >= 201703L
537 return m_string.data();
538#else
539 return &m_string[0];
540#endif
541 }
542
543 TGUI_NODISCARD const char32_t* c_str() const noexcept
544 {
545 return m_string.c_str();
546 }
547
548 TGUI_NODISCARD iterator begin() noexcept;
549 TGUI_NODISCARD const_iterator begin() const noexcept;
550 TGUI_NODISCARD const_iterator cbegin() const noexcept;
551
552 TGUI_NODISCARD iterator end() noexcept;
553 TGUI_NODISCARD const_iterator end() const noexcept;
554 TGUI_NODISCARD const_iterator cend() const noexcept;
555
556 TGUI_NODISCARD reverse_iterator rbegin() noexcept;
557 TGUI_NODISCARD const_reverse_iterator rbegin() const noexcept;
558 TGUI_NODISCARD const_reverse_iterator crbegin() const noexcept;
559
560 TGUI_NODISCARD reverse_iterator rend() noexcept;
561 TGUI_NODISCARD const_reverse_iterator rend() const noexcept;
562 TGUI_NODISCARD const_reverse_iterator crend() const noexcept;
563
564 TGUI_NODISCARD bool empty() const noexcept
565 {
566 return m_string.empty();
567 }
568
569 TGUI_NODISCARD std::size_t size() const noexcept
570 {
571 return m_string.size();
572 }
573
574 TGUI_NODISCARD std::size_t length() const noexcept
575 {
576 return m_string.length();
577 }
578
579 TGUI_NODISCARD std::size_t max_size() const noexcept;
580
581 void reserve(std::size_t newCap);
582 TGUI_NODISCARD std::size_t capacity() const noexcept;
583 void shrink_to_fit();
584
585 void clear() noexcept;
586
587 String& insert(std::size_t index, std::size_t count, char ch);
588 String& insert(std::size_t index, std::size_t count, wchar_t ch);
589 String& insert(std::size_t index, std::size_t count, char16_t ch);
590 String& insert(std::size_t index, std::size_t count, char32_t ch);
591
592 String& insert(std::size_t index, StringView sv);
593 String& insert(std::size_t index, const char32_t* str);
594 String& insert(std::size_t index, const std::u32string& str);
595 String& insert(std::size_t index, const String& str);
596
597 String& insert(std::size_t index, StringView sv, std::size_t pos, std::size_t count = npos);
598 String& insert(std::size_t index, const std::string& str, std::size_t pos, std::size_t count = npos);
599 String& insert(std::size_t index, const std::wstring& str, std::size_t pos, std::size_t count = npos);
600 String& insert(std::size_t index, const std::u16string& str, std::size_t pos, std::size_t count = npos);
601 String& insert(std::size_t index, const std::u32string& str, std::size_t pos, std::size_t count = npos);
602 String& insert(std::size_t index, const String& str, std::size_t pos, std::size_t count = npos);
603
604 String& insert(std::size_t index, const char* str, std::size_t count);
605 String& insert(std::size_t index, const wchar_t* str, std::size_t count);
606 String& insert(std::size_t index, const char16_t* str, std::size_t count);
607 String& insert(std::size_t index, const char32_t* str, std::size_t count);
608
609 iterator insert(const_iterator pos, char ch);
610 iterator insert(const_iterator pos, wchar_t ch);
611 iterator insert(const_iterator pos, char16_t ch);
612 iterator insert(const_iterator pos, char32_t ch);
613
614 iterator insert(const_iterator pos, std::size_t count, char ch);
615 iterator insert(const_iterator pos, std::size_t count, wchar_t ch);
616 iterator insert(const_iterator pos, std::size_t count, char16_t ch);
617 iterator insert(const_iterator pos, std::size_t count, char32_t ch);
618
619 iterator insert(const_iterator pos, std::initializer_list<char> chars);
620 iterator insert(const_iterator pos, std::initializer_list<wchar_t> chars);
621 iterator insert(const_iterator pos, std::initializer_list<char16_t> chars);
622 iterator insert(const_iterator pos, std::initializer_list<char32_t> chars);
623
624 iterator insert(const_iterator pos, std::string::const_iterator first, std::string::const_iterator last);
625 iterator insert(const_iterator pos, std::wstring::const_iterator first, std::wstring::const_iterator last);
626 iterator insert(const_iterator pos, std::u16string::const_iterator first, std::u16string::const_iterator last);
627 iterator insert(const_iterator pos, std::u32string::const_iterator first, std::u32string::const_iterator last);
628 iterator insert(const_iterator pos, StringView::const_iterator first, StringView::const_iterator last);
629
630 String& erase(std::size_t index = 0, std::size_t count = npos);
631
632 iterator erase(const_iterator position);
633 iterator erase(const_iterator first, const_iterator last);
634
635 void push_back(char ch);
636 void push_back(wchar_t ch);
637 void push_back(char16_t ch);
638 void push_back(char32_t ch);
639
640 void pop_back();
641
642 String& append(std::size_t count, char ch);
643 String& append(std::size_t count, wchar_t ch);
644 String& append(std::size_t count, char16_t ch);
645 String& append(std::size_t count, char32_t ch);
646
647 String& append(StringView sv);
648 String& append(const char32_t* str);
649 String& append(const std::u32string& str);
650 String& append(const String& str);
651
652 String& append(StringView sv, std::size_t pos, std::size_t count = npos);
653 String& append(const std::string& str, std::size_t pos, std::size_t count = npos);
654 String& append(const std::wstring& str, std::size_t pos, std::size_t count = npos);
655 String& append(const std::u16string& str, std::size_t pos, std::size_t count = npos);
656 String& append(const std::u32string& str, std::size_t pos, std::size_t count = npos);
657 String& append(const String& str, std::size_t pos, std::size_t count = npos);
658
659 String& append(const char* str, std::size_t count);
660 String& append(const wchar_t* str, std::size_t count);
661 String& append(const char16_t* str, std::size_t count);
662 String& append(const char32_t* str, std::size_t count);
663
664 String& append(std::string::const_iterator first, std::string::const_iterator last);
665 String& append(std::wstring::const_iterator first, std::wstring::const_iterator last);
666 String& append(std::u16string::const_iterator first, std::u16string::const_iterator last);
667 String& append(std::u32string::const_iterator first, std::u32string::const_iterator last);
668 String& append(StringView::const_iterator first, StringView::const_iterator last);
669
670 String& append(std::initializer_list<char> chars);
671 String& append(std::initializer_list<wchar_t> chars);
672 String& append(std::initializer_list<char16_t> chars);
673 String& append(std::initializer_list<char32_t> chars);
674
675 String& operator+=(const String& str);
676
677 TGUI_NODISCARD int compare(StringView sv) const noexcept;
678 TGUI_NODISCARD int compare(const char32_t* s) const;
679 TGUI_NODISCARD int compare(const std::u32string& str) const noexcept;
680 TGUI_NODISCARD int compare(const String& str) const noexcept;
681
682 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, StringView sv) const;
683 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const char32_t* s) const;
684 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const std::u32string& str) const;
685 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const String& str) const;
686
687 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, StringView sv, std::size_t pos2, std::size_t count2 = npos) const;
688 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const std::string& str, std::size_t pos2, std::size_t count2 = npos) const;
689 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const std::wstring& str, std::size_t pos2, std::size_t count2 = npos) const;
690 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const std::u16string& str, std::size_t pos2, std::size_t count2 = npos) const;
691 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const std::u32string& str, std::size_t pos2, std::size_t count2 = npos) const;
692 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const String& str, std::size_t pos2, std::size_t count2 = npos) const;
693
694 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const char* s, std::size_t count2) const;
695 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const wchar_t* s, std::size_t count2) const;
696 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const char16_t* s, std::size_t count2) const;
697 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const char32_t* s, std::size_t count2) const;
698
699 String& replace(std::size_t pos, std::size_t count, StringView sv);
700 String& replace(std::size_t pos, std::size_t count, const char32_t* cstr);
701 String& replace(std::size_t pos, std::size_t count, const std::u32string& str);
702 String& replace(std::size_t pos, std::size_t count, const String& str);
703
704 String& replace(const_iterator first, const_iterator last, StringView sv);
705 String& replace(const_iterator first, const_iterator last, const char32_t* cstr);
706 String& replace(const_iterator first, const_iterator last, const std::u32string& str);
707 String& replace(const_iterator first, const_iterator last, const String& str);
708
709 String& replace(std::size_t pos, std::size_t count, StringView sv, std::size_t pos2, std::size_t count2 = npos);
710 String& replace(std::size_t pos, std::size_t count, const std::string& str, std::size_t pos2, std::size_t count2 = npos);
711 String& replace(std::size_t pos, std::size_t count, const std::wstring& str, std::size_t pos2, std::size_t count2 = npos);
712 String& replace(std::size_t pos, std::size_t count, const std::u16string& str, std::size_t pos2, std::size_t count2 = npos);
713 String& replace(std::size_t pos, std::size_t count, const std::u32string& str, std::size_t pos2, std::size_t count2 = npos);
714 String& replace(std::size_t pos, std::size_t count, const String& str, std::size_t pos2, std::size_t count2 = npos);
715
716 String& replace(const_iterator first, const_iterator last, std::string::const_iterator first2, std::string::const_iterator last2);
717 String& replace(const_iterator first, const_iterator last, std::wstring::const_iterator first2, std::wstring::const_iterator last2);
718 String& replace(const_iterator first, const_iterator last, std::u16string::const_iterator first2, std::u16string::const_iterator last2);
719 String& replace(const_iterator first, const_iterator last, std::u32string::const_iterator first2, std::u32string::const_iterator last2);
720 String& replace(const_iterator first, const_iterator last, StringView::const_iterator first2, StringView::const_iterator last2);
721
722 String& replace(std::size_t pos, std::size_t count, const char* cstr, std::size_t count2);
723 String& replace(std::size_t pos, std::size_t count, const wchar_t* cstr, std::size_t count2);
724 String& replace(std::size_t pos, std::size_t count, const char16_t* cstr, std::size_t count2);
725 String& replace(std::size_t pos, std::size_t count, const char32_t* cstr, std::size_t count2);
726
727 String& replace(const_iterator first, const_iterator last, const char* cstr, std::size_t count2);
728 String& replace(const_iterator first, const_iterator last, const wchar_t* cstr, std::size_t count2);
729 String& replace(const_iterator first, const_iterator last, const char16_t* cstr, std::size_t count2);
730 String& replace(const_iterator first, const_iterator last, const char32_t* cstr, std::size_t count2);
731
732 String& replace(std::size_t pos, std::size_t count, std::size_t count2, char ch);
733 String& replace(std::size_t pos, std::size_t count, std::size_t count2, wchar_t ch);
734 String& replace(std::size_t pos, std::size_t count, std::size_t count2, char16_t ch);
735 String& replace(std::size_t pos, std::size_t count, std::size_t count2, char32_t ch);
736
737 String& replace(const_iterator first, const_iterator last, std::size_t count2, char ch);
738 String& replace(const_iterator first, const_iterator last, std::size_t count2, wchar_t ch);
739 String& replace(const_iterator first, const_iterator last, std::size_t count2, char16_t ch);
740 String& replace(const_iterator first, const_iterator last, std::size_t count2, char32_t ch);
741
742 String& replace(const_iterator first, const_iterator last, std::initializer_list<char> chars);
743 String& replace(const_iterator first, const_iterator last, std::initializer_list<wchar_t> chars);
744 String& replace(const_iterator first, const_iterator last, std::initializer_list<char16_t> chars);
745 String& replace(const_iterator first, const_iterator last, std::initializer_list<char32_t> chars);
746
747 TGUI_NODISCARD String substr(std::size_t pos = 0, std::size_t count = npos) const;
748
749 std::size_t copy(char32_t* dest, std::size_t count, std::size_t pos = 0) const;
750
751 void resize(std::size_t count);
752 void resize(std::size_t count, char ch);
753 void resize(std::size_t count, wchar_t ch);
754 void resize(std::size_t count, char16_t ch);
755 void resize(std::size_t count, char32_t ch);
756
757 void swap(String& other);
758
759 TGUI_NODISCARD bool contains(char c) const noexcept;
760 TGUI_NODISCARD bool contains(wchar_t c) const noexcept;
761 TGUI_NODISCARD bool contains(char16_t c) const noexcept;
762 TGUI_NODISCARD bool contains(char32_t c) const noexcept;
763
764 TGUI_NODISCARD bool contains(StringView sv) const noexcept;
765 TGUI_NODISCARD bool contains(const char32_t* s) const;
766 TGUI_NODISCARD bool contains(const std::u32string& s) const;
767 TGUI_NODISCARD bool contains(const String& s) const;
768
769 TGUI_NODISCARD std::size_t find(StringView sv, std::size_t pos = 0) const noexcept;
770 TGUI_NODISCARD std::size_t find(const char32_t* s, std::size_t pos = 0) const;
771 TGUI_NODISCARD std::size_t find(const std::u32string& str, std::size_t pos = 0) const noexcept;
772 TGUI_NODISCARD std::size_t find(const String& str, std::size_t pos = 0) const noexcept;
773
774 TGUI_NODISCARD std::size_t find(const char* s, std::size_t pos, std::size_t count) const;
775 TGUI_NODISCARD std::size_t find(const wchar_t* s, std::size_t pos, std::size_t count) const;
776 TGUI_NODISCARD std::size_t find(const char16_t* s, std::size_t pos, std::size_t count) const;
777 TGUI_NODISCARD std::size_t find(const char32_t* s, std::size_t pos, std::size_t count) const;
778
779 TGUI_NODISCARD std::size_t find(char ch, std::size_t pos = 0) const noexcept;
780 TGUI_NODISCARD std::size_t find(wchar_t ch, std::size_t pos = 0) const noexcept;
781 TGUI_NODISCARD std::size_t find(char16_t ch, std::size_t pos = 0) const noexcept;
782 TGUI_NODISCARD std::size_t find(char32_t ch, std::size_t pos = 0) const noexcept;
783
784 TGUI_NODISCARD std::size_t find_first_of(StringView sv, std::size_t pos = 0) const noexcept;
785 TGUI_NODISCARD std::size_t find_first_of(const char32_t* s, std::size_t pos = 0) const;
786 TGUI_NODISCARD std::size_t find_first_of(const std::u32string& str, std::size_t pos = 0) const noexcept;
787 TGUI_NODISCARD std::size_t find_first_of(const String& str, std::size_t pos = 0) const noexcept;
788
789 TGUI_NODISCARD std::size_t find_first_of(const char* s, std::size_t pos, std::size_t count) const;
790 TGUI_NODISCARD std::size_t find_first_of(const wchar_t* s, std::size_t pos, std::size_t count) const;
791 TGUI_NODISCARD std::size_t find_first_of(const char16_t* s, std::size_t pos, std::size_t count) const;
792 TGUI_NODISCARD std::size_t find_first_of(const char32_t* s, std::size_t pos, std::size_t count) const;
793
794 TGUI_NODISCARD std::size_t find_first_of(char ch, std::size_t pos = 0) const noexcept;
795 TGUI_NODISCARD std::size_t find_first_of(wchar_t ch, std::size_t pos = 0) const noexcept;
796 TGUI_NODISCARD std::size_t find_first_of(char16_t ch, std::size_t pos = 0) const noexcept;
797 TGUI_NODISCARD std::size_t find_first_of(char32_t ch, std::size_t pos = 0) const noexcept;
798
799 TGUI_NODISCARD std::size_t find_first_not_of(StringView sv, std::size_t pos = 0) const noexcept;
800 TGUI_NODISCARD std::size_t find_first_not_of(const char32_t* s, std::size_t pos = 0) const;
801 TGUI_NODISCARD std::size_t find_first_not_of(const std::u32string& str, std::size_t pos = 0) const noexcept;
802 TGUI_NODISCARD std::size_t find_first_not_of(const String& str, std::size_t pos = 0) const noexcept;
803
804 TGUI_NODISCARD std::size_t find_first_not_of(const char* s, std::size_t pos, std::size_t count) const;
805 TGUI_NODISCARD std::size_t find_first_not_of(const wchar_t* s, std::size_t pos, std::size_t count) const;
806 TGUI_NODISCARD std::size_t find_first_not_of(const char16_t* s, std::size_t pos, std::size_t count) const;
807 TGUI_NODISCARD std::size_t find_first_not_of(const char32_t* s, std::size_t pos, std::size_t count) const;
808
809 TGUI_NODISCARD std::size_t find_first_not_of(char ch, std::size_t pos = 0) const noexcept;
810 TGUI_NODISCARD std::size_t find_first_not_of(wchar_t ch, std::size_t pos = 0) const noexcept;
811 TGUI_NODISCARD std::size_t find_first_not_of(char16_t ch, std::size_t pos = 0) const noexcept;
812 TGUI_NODISCARD std::size_t find_first_not_of(char32_t ch, std::size_t pos = 0) const noexcept;
813
814 TGUI_NODISCARD std::size_t rfind(StringView sv, std::size_t pos = npos) const noexcept;
815 TGUI_NODISCARD std::size_t rfind(const char32_t* s, std::size_t pos = npos) const;
816 TGUI_NODISCARD std::size_t rfind(const std::u32string& str, std::size_t pos = npos) const noexcept;
817 TGUI_NODISCARD std::size_t rfind(const String& str, std::size_t pos = npos) const noexcept;
818
819 TGUI_NODISCARD std::size_t rfind(const char* s, std::size_t pos, std::size_t count) const;
820 TGUI_NODISCARD std::size_t rfind(const wchar_t* s, std::size_t pos, std::size_t count) const;
821 TGUI_NODISCARD std::size_t rfind(const char16_t* s, std::size_t pos, std::size_t count) const;
822 TGUI_NODISCARD std::size_t rfind(const char32_t* s, std::size_t pos, std::size_t count) const;
823
824 TGUI_NODISCARD std::size_t rfind(char ch, std::size_t pos = npos) const noexcept;
825 TGUI_NODISCARD std::size_t rfind(wchar_t ch, std::size_t pos = npos) const noexcept;
826 TGUI_NODISCARD std::size_t rfind(char16_t ch, std::size_t pos = npos) const noexcept;
827 TGUI_NODISCARD std::size_t rfind(char32_t ch, std::size_t pos = npos) const noexcept;
828
829 TGUI_NODISCARD std::size_t find_last_of(StringView sv, std::size_t pos = npos) const noexcept;
830 TGUI_NODISCARD std::size_t find_last_of(const char32_t* s, std::size_t pos = npos) const;
831 TGUI_NODISCARD std::size_t find_last_of(const std::u32string& str, std::size_t pos = npos) const noexcept;
832 TGUI_NODISCARD std::size_t find_last_of(const String& str, std::size_t pos = npos) const noexcept;
833
834 TGUI_NODISCARD std::size_t find_last_of(const char* s, std::size_t pos, std::size_t count) const;
835 TGUI_NODISCARD std::size_t find_last_of(const wchar_t* s, std::size_t pos, std::size_t count) const;
836 TGUI_NODISCARD std::size_t find_last_of(const char16_t* s, std::size_t pos, std::size_t count) const;
837 TGUI_NODISCARD std::size_t find_last_of(const char32_t* s, std::size_t pos, std::size_t count) const;
838
839 TGUI_NODISCARD std::size_t find_last_of(char ch, std::size_t pos = npos) const noexcept;
840 TGUI_NODISCARD std::size_t find_last_of(wchar_t ch, std::size_t pos = npos) const noexcept;
841 TGUI_NODISCARD std::size_t find_last_of(char16_t ch, std::size_t pos = npos) const noexcept;
842 TGUI_NODISCARD std::size_t find_last_of(char32_t ch, std::size_t pos = npos) const noexcept;
843
844 TGUI_NODISCARD std::size_t find_last_not_of(StringView sv, std::size_t pos = npos) const noexcept;
845 TGUI_NODISCARD std::size_t find_last_not_of(const char32_t* s, std::size_t pos = npos) const;
846 TGUI_NODISCARD std::size_t find_last_not_of(const std::u32string& str, std::size_t pos = npos) const noexcept;
847 TGUI_NODISCARD std::size_t find_last_not_of(const String& str, std::size_t pos = npos) const noexcept;
848
849 TGUI_NODISCARD std::size_t find_last_not_of(const char* s, std::size_t pos, std::size_t count) const;
850 TGUI_NODISCARD std::size_t find_last_not_of(const wchar_t* s, std::size_t pos, std::size_t count) const;
851 TGUI_NODISCARD std::size_t find_last_not_of(const char16_t* s, std::size_t pos, std::size_t count) const;
852 TGUI_NODISCARD std::size_t find_last_not_of(const char32_t* s, std::size_t pos, std::size_t count) const;
853
854 TGUI_NODISCARD std::size_t find_last_not_of(char ch, std::size_t pos = npos) const noexcept;
855 TGUI_NODISCARD std::size_t find_last_not_of(wchar_t ch, std::size_t pos = npos) const noexcept;
856 TGUI_NODISCARD std::size_t find_last_not_of(char16_t ch, std::size_t pos = npos) const noexcept;
857 TGUI_NODISCARD std::size_t find_last_not_of(char32_t ch, std::size_t pos = npos) const noexcept;
858
859 TGUI_NODISCARD inline bool starts_with(StringView sv) const noexcept;
860 TGUI_NODISCARD inline bool starts_with(const char32_t* s) const;
861 TGUI_NODISCARD inline bool starts_with(const std::u32string& s) const;
862 TGUI_NODISCARD inline bool starts_with(const String& s) const;
863
864 TGUI_NODISCARD inline bool starts_with(char ch) const noexcept;
865 TGUI_NODISCARD inline bool starts_with(wchar_t ch) const noexcept;
866 TGUI_NODISCARD inline bool starts_with(char16_t ch) const noexcept;
867 TGUI_NODISCARD inline bool starts_with(char32_t ch) const noexcept;
868
869 TGUI_NODISCARD inline bool ends_with(StringView sv) const noexcept;
870 TGUI_NODISCARD inline bool ends_with(const char32_t* s) const;
871 TGUI_NODISCARD inline bool ends_with(const std::u32string& s) const;
872 TGUI_NODISCARD inline bool ends_with(const String& s) const;
873
874 TGUI_NODISCARD inline bool ends_with(char ch) const noexcept;
875 TGUI_NODISCARD inline bool ends_with(wchar_t ch) const noexcept;
876 TGUI_NODISCARD inline bool ends_with(char16_t ch) const noexcept;
877 TGUI_NODISCARD inline bool ends_with(char32_t ch) const noexcept;
878
879 TGUI_NODISCARD std::size_t count(const char ch, const std::size_t pos = 0) const noexcept;
880 TGUI_NODISCARD std::size_t count(const wchar_t ch, const std::size_t pos = 0) const noexcept;
881 TGUI_NODISCARD std::size_t count(const char16_t ch, const std::size_t pos = 0) const noexcept;
882 TGUI_NODISCARD std::size_t count(const char32_t ch, const std::size_t pos = 0) const noexcept;
883
884 inline friend bool operator==(const String& left, StringView right);
885 inline friend bool operator==(const String& left, const char32_t* right);
886 inline friend bool operator==(const String& left, const std::u32string& right);
887 inline friend bool operator==(const String& left, const String& right);
888
889 inline friend bool operator!=(const String& left, StringView right);
890 inline friend bool operator!=(const String& left, const char32_t* right);
891 inline friend bool operator!=(const String& left, const std::u32string& right);
892 inline friend bool operator!=(const String& left, const String& right);
893
894 inline friend bool operator<(const String& left, StringView right);
895 inline friend bool operator<(const String& left, const char32_t* right);
896 inline friend bool operator<(const String& left, const std::u32string& right);
897 inline friend bool operator<(const String& left, const String& right);
898
899 inline friend bool operator<=(const String& left, StringView right);
900 inline friend bool operator<=(const String& left, const char32_t* right);
901 inline friend bool operator<=(const String& left, const std::u32string& right);
902 inline friend bool operator<=(const String& left, const String& right);
903
904 inline friend bool operator>(const String& left, StringView right);
905 inline friend bool operator>(const String& left, const char32_t* right);
906 inline friend bool operator>(const String& left, const std::u32string& right);
907 inline friend bool operator>(const String& left, const String& right);
908
909 inline friend bool operator>=(const String& left, StringView right);
910 inline friend bool operator>=(const String& left, const char32_t* right);
911 inline friend bool operator>=(const String& left, const std::u32string& right);
912 inline friend bool operator>=(const String& left, const String& right);
913
914 inline friend String operator+(const String& left, const String& right);
915 inline friend String operator+(const String& left, String&& right);
916 inline friend String operator+(String&& left, const String& right);
917 inline friend String operator+(String&& left, String&& right);
918
919#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201811L)
920 inline String(const std::u8string& str);
921 inline String(char8_t utfChar);
922 inline String(const char8_t* str);
923 inline String(std::size_t count, char8_t ch);
924 inline String(const std::u8string& str, std::size_t pos);
925 inline String(const std::u8string& str, std::size_t pos, std::size_t count);
926 inline String(const char8_t* str, std::size_t count);
927 inline explicit String(std::initializer_list<char8_t> chars);
928 inline explicit String(std::u8string::const_iterator first, std::u8string::const_iterator last);
929
930 inline explicit operator std::u8string() const;
931
932 TGUI_NODISCARD inline std::u8string toUtf8() const;
933
934 inline String& assign(std::size_t count, char8_t ch);
935 inline String& assign(const std::u8string& str, std::size_t pos, std::size_t count = npos);
936 inline String& assign(const char8_t* str, std::size_t count);
937 inline String& assign(std::initializer_list<char8_t> chars);
938 inline String& assign(std::u8string::const_iterator first, std::u8string::const_iterator last);
939
940 inline String& insert(std::size_t index, std::size_t count, char8_t ch);
941 inline String& insert(std::size_t index, const std::u8string& str, std::size_t pos, std::size_t count = npos);
942 inline String& insert(std::size_t index, const char8_t* str, std::size_t count);
943 inline iterator insert(const_iterator pos, char8_t ch);
944 inline iterator insert(const_iterator pos, std::size_t count, char8_t ch);
945 inline iterator insert(const_iterator pos, std::initializer_list<char8_t> chars);
946 inline iterator insert(const_iterator pos, std::u8string::const_iterator first, std::u8string::const_iterator last);
947
948 inline String& append(std::size_t count, char8_t ch);
949 inline String& append(const std::u8string& str, std::size_t pos, std::size_t count = npos);
950 inline String& append(const char8_t* str, std::size_t count);
951 inline String& append(std::initializer_list<char8_t> chars);
952 inline String& append(std::u8string::const_iterator first, std::u8string::const_iterator last);
953
954 TGUI_NODISCARD inline int compare(std::size_t pos1, std::size_t count1, const std::u8string& str, std::size_t pos2, std::size_t count2 = npos) const;
955 TGUI_NODISCARD inline int compare(std::size_t pos1, std::size_t count1, const char8_t* s, std::size_t count2) const;
956
957 inline String& replace(std::size_t pos, std::size_t count, const std::u8string& str, std::size_t pos2, std::size_t count2 = npos);
958 inline String& replace(const_iterator first, const_iterator last, std::u8string::const_iterator first2, std::u8string::const_iterator last2);
959 inline String& replace(std::size_t pos, std::size_t count, const char8_t* cstr, std::size_t count2);
960 inline String& replace(const_iterator first, const_iterator last, const char8_t* cstr, std::size_t count2);
961 inline String& replace(std::size_t pos, std::size_t count, std::size_t count2, char8_t ch);
962 inline String& replace(const_iterator first, const_iterator last, std::size_t count2, char8_t ch);
963 inline String& replace(const_iterator first, const_iterator last, std::initializer_list<char8_t> chars);
964
965 inline void resize(std::size_t count, char8_t ch);
966
967 TGUI_NODISCARD inline bool contains(char8_t c) const noexcept;
968
969 TGUI_NODISCARD inline std::size_t find(const char8_t* s, std::size_t pos, std::size_t count) const;
970 TGUI_NODISCARD inline std::size_t find(char8_t ch, std::size_t pos = 0) const noexcept;
971
972 TGUI_NODISCARD inline std::size_t find_first_of(const char8_t* s, std::size_t pos, std::size_t count) const;
973 TGUI_NODISCARD inline std::size_t find_first_of(char8_t ch, std::size_t pos = 0) const noexcept;
974
975 TGUI_NODISCARD inline std::size_t find_first_not_of(const char8_t* s, std::size_t pos, std::size_t count) const;
976 TGUI_NODISCARD inline std::size_t find_first_not_of(char8_t ch, std::size_t pos = 0) const noexcept;
977
978 TGUI_NODISCARD inline std::size_t rfind(const char8_t* s, std::size_t pos, std::size_t count) const;
979 TGUI_NODISCARD inline std::size_t rfind(char8_t ch, std::size_t pos = npos) const noexcept;
980
981 TGUI_NODISCARD inline std::size_t find_last_of(const char8_t* s, std::size_t pos, std::size_t count) const;
982 TGUI_NODISCARD inline std::size_t find_last_of(char8_t ch, std::size_t pos = npos) const noexcept;
983
984 TGUI_NODISCARD inline std::size_t find_last_not_of(const char8_t* s, std::size_t pos, std::size_t count) const;
985 TGUI_NODISCARD inline std::size_t find_last_not_of(char8_t ch, std::size_t pos = npos) const noexcept;
986
987 TGUI_NODISCARD inline bool starts_with(char8_t ch) const noexcept;
988 TGUI_NODISCARD inline bool ends_with(char8_t ch) const noexcept;
989#endif
990 };
991
993
994 inline bool String::starts_with(StringView sv) const noexcept
995 {
996 return viewStartsWith(StringView(m_string), sv);
997 }
998
999 inline bool String::starts_with(const char32_t* s) const
1000 {
1001 return viewStartsWith(StringView(m_string), StringView(s));
1002 }
1003
1004 inline bool String::starts_with(const std::u32string& s) const
1005 {
1006 return viewStartsWith(StringView(m_string), StringView(s));
1007 }
1008
1009 inline bool String::starts_with(const String& s) const
1010 {
1011 return viewStartsWith(StringView(m_string), StringView(s));
1012 }
1013
1014 inline bool String::starts_with(char ch) const noexcept
1015 {
1016 return viewStartsWith(StringView(m_string), static_cast<char32_t>(ch));
1017 }
1018
1019 inline bool String::starts_with(wchar_t ch) const noexcept
1020 {
1021 return viewStartsWith(StringView(m_string), static_cast<char32_t>(ch));
1022 }
1023
1024 inline bool String::starts_with(char16_t ch) const noexcept
1025 {
1026 return viewStartsWith(StringView(m_string), static_cast<char32_t>(ch));
1027 }
1028
1029 inline bool String::starts_with(char32_t ch) const noexcept
1030 {
1031 return viewStartsWith(StringView(m_string), ch);
1032 }
1033
1034 inline bool String::ends_with(StringView sv) const noexcept
1035 {
1036 return viewEndsWith(StringView(m_string), sv);
1037 }
1038
1039 inline bool String::ends_with(const char32_t* s) const
1040 {
1041 return viewEndsWith(StringView(m_string), StringView(s));
1042 }
1043
1044 inline bool String::ends_with(const std::u32string& s) const
1045 {
1046 return viewEndsWith(StringView(m_string), StringView(s));
1047 }
1048
1049 inline bool String::ends_with(const String& s) const
1050 {
1051 return viewEndsWith(StringView(m_string), StringView(s));
1052 }
1053
1054 inline bool String::ends_with(char ch) const noexcept
1055 {
1056 return viewEndsWith(StringView(m_string), static_cast<char32_t>(ch));
1057 }
1058
1059 inline bool String::ends_with(wchar_t ch) const noexcept
1060 {
1061 return viewEndsWith(StringView(m_string), static_cast<char32_t>(ch));
1062 }
1063
1064 inline bool String::ends_with(char16_t ch) const noexcept
1065 {
1066 return viewEndsWith(StringView(m_string), static_cast<char32_t>(ch));
1067 }
1068
1069 inline bool String::ends_with(char32_t ch) const noexcept
1070 {
1071 return viewEndsWith(StringView(m_string), ch);
1072 }
1073
1074 TGUI_NODISCARD inline bool operator==(const String& left, StringView right)
1075 {
1076 return StringView(left) == right;
1077 }
1078
1079 TGUI_NODISCARD inline bool operator==(const String& left, const char32_t* right)
1080 {
1081 return StringView(left) == right;
1082 }
1083
1084 TGUI_NODISCARD inline bool operator==(const String& left, const std::u32string& right)
1085 {
1086 return StringView(left) == right;
1087 }
1088
1089 TGUI_NODISCARD inline bool operator==(const String& left, const String& right)
1090 {
1091 return left.m_string == right.m_string;
1092 }
1093
1094 TGUI_NODISCARD inline bool operator!=(const String& left, StringView right)
1095 {
1096 return StringView(left) != right;
1097 }
1098
1099 TGUI_NODISCARD inline bool operator!=(const String& left, const char32_t* right)
1100 {
1101 return StringView(left) != right;
1102 }
1103
1104 TGUI_NODISCARD inline bool operator!=(const String& left, const std::u32string& right)
1105 {
1106 return StringView(left) != right;
1107 }
1108
1109 TGUI_NODISCARD inline bool operator!=(const String& left, const String& right)
1110 {
1111 return left.m_string != right.m_string;
1112 }
1113
1114 TGUI_NODISCARD inline bool operator<(const String& left, StringView right)
1115 {
1116 return StringView(left) < right;
1117 }
1118
1119 TGUI_NODISCARD inline bool operator<(const String& left, const char32_t* right)
1120 {
1121 return StringView(left) < right;
1122 }
1123
1124 TGUI_NODISCARD inline bool operator<(const String& left, const std::u32string& right)
1125 {
1126 return StringView(left) < right;
1127 }
1128
1129 TGUI_NODISCARD inline bool operator<(const String& left, const String& right)
1130 {
1131 return left.m_string < right.m_string;
1132 }
1133
1134 TGUI_NODISCARD inline bool operator<=(const String& left, StringView right)
1135 {
1136 return StringView(left) <= right;
1137 }
1138
1139 TGUI_NODISCARD inline bool operator<=(const String& left, const char32_t* right)
1140 {
1141 return StringView(left) <= right;
1142 }
1143
1144 TGUI_NODISCARD inline bool operator<=(const String& left, const std::u32string& right)
1145 {
1146 return StringView(left) <= right;
1147 }
1148
1149 TGUI_NODISCARD inline bool operator<=(const String& left, const String& right)
1150 {
1151 return left.m_string <= right.m_string;
1152 }
1153
1154 TGUI_NODISCARD inline bool operator>(const String& left, StringView right)
1155 {
1156 return StringView(left) > right;
1157 }
1158
1159 TGUI_NODISCARD inline bool operator>(const String& left, const char32_t* right)
1160 {
1161 return StringView(left) > right;
1162 }
1163
1164 TGUI_NODISCARD inline bool operator>(const String& left, const std::u32string& right)
1165 {
1166 return StringView(left) > right;
1167 }
1168
1169 TGUI_NODISCARD inline bool operator>(const String& left, const String& right)
1170 {
1171 return left.m_string > right.m_string;
1172 }
1173
1174 TGUI_NODISCARD inline bool operator>=(const String& left, StringView right)
1175 {
1176 return StringView(left) >= right;
1177 }
1178
1179 TGUI_NODISCARD inline bool operator>=(const String& left, const char32_t* right)
1180 {
1181 return StringView(left) >= right;
1182 }
1183
1184 TGUI_NODISCARD inline bool operator>=(const String& left, const std::u32string& right)
1185 {
1186 return StringView(left) >= right;
1187 }
1188
1189 TGUI_NODISCARD inline bool operator>=(const String& left, const String& right)
1190 {
1191 return left.m_string >= right.m_string;
1192 }
1193
1194 TGUI_NODISCARD inline String operator+(const String& left, const String& right)
1195 {
1196 return {left.m_string + right.m_string};
1197 }
1198 TGUI_NODISCARD inline String operator+(String&& left, String&& right)
1199 {
1200 return {std::move(left.m_string) + std::move(right.m_string)};
1201 }
1202 TGUI_NODISCARD inline String operator+(String&& left, const String& right)
1203 {
1204 return {std::move(left.m_string) + right.m_string};
1205 }
1206 TGUI_NODISCARD inline String operator+(const String& left, String&& right)
1207 {
1208 return {left.m_string + std::move(right.m_string)};
1209 }
1210
1211 // We don't provide operator<< implmentations for basic_ostream<charX_t> streams because
1212 // even clang 15 can't compile them when using libc++.
1213 // We could define them for VS, GCC and for clang with libstdc++, but there is no real use for them.
1214 TGUI_API std::ostream& operator<<(std::ostream& os, const String& str);
1215 TGUI_API std::wostream& operator<<(std::wostream& os, const String& str);
1216
1217 TGUI_API std::istream& operator>>(std::istream& os, String& str);
1218 TGUI_API std::wistream& operator>>(std::wistream& os, String& str);
1219
1220 // UTF-8 function are defined in the header so that they can be enabled/disabled based on
1221 // the compiler settings without having to recompile TGUI with a different c++ standard.
1222#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201811L)
1223 inline String::String(const std::u8string& str) :
1224 m_string(utf::convertUtf8toUtf32(str.begin(), str.end()))
1225 {
1226 }
1227
1228 inline String::String(char8_t utfChar)
1229 : m_string(1, static_cast<char32_t>(utfChar))
1230 {
1231 }
1232
1233 inline String::String(const char8_t* str)
1234 : String{utf::convertUtf8toUtf32(str, str + std::char_traits<char8_t>::length(str))}
1235 {
1236 }
1237
1238 inline String::String(std::size_t count, char8_t ch)
1239 : m_string(count, static_cast<char32_t>(ch))
1240 {
1241 }
1242
1243 inline String::String(const std::u8string& str, std::size_t pos)
1244 : String{std::u8string(str, pos)}
1245 {
1246 }
1247
1248 inline String::String(const std::u8string& str, std::size_t pos, std::size_t count)
1249 : String{std::u8string(str, pos, count)}
1250 {
1251 }
1252
1253 inline String::String(const char8_t* str, std::size_t count)
1254 : String{std::u8string{str, count}}
1255 {
1256 }
1257
1258 inline String::String(std::initializer_list<char8_t> chars)
1259 : String(std::u8string(chars.begin(), chars.end()))
1260 {
1261 }
1262
1263 inline String::String(std::u8string::const_iterator first, std::u8string::const_iterator last)
1264 : String{std::u8string(first, last)}
1265 {
1266 }
1267
1268 inline String::operator std::u8string() const
1269 {
1270 return utf::convertUtf32toUtf8(m_string);
1271 }
1272
1273 inline std::u8string String::toUtf8() const
1274 {
1275 return utf::convertUtf32toUtf8(m_string);
1276 }
1277
1278 inline String& String::assign(const std::u8string& str, std::size_t pos, std::size_t count)
1279 {
1280 m_string.assign(String{str, pos, count}.m_string);
1281 return *this;
1282 }
1283
1284 inline String& String::assign(const char8_t* str, std::size_t count)
1285 {
1286 m_string.assign(String{str, count}.m_string);
1287 return *this;
1288 }
1289
1290 inline String& String::assign(std::size_t count, char8_t ch)
1291 {
1292 m_string.assign(count, static_cast<char32_t>(ch));
1293 return *this;
1294 }
1295
1296 inline String& String::assign(std::initializer_list<char8_t> chars)
1297 {
1298 m_string.assign(String{chars}.m_string);
1299 return *this;
1300 }
1301
1302 inline String& String::assign(std::u8string::const_iterator first, std::u8string::const_iterator last)
1303 {
1304 m_string.assign(String{first, last}.m_string);
1305 return *this;
1306 }
1307
1308 inline String& String::insert(std::size_t index, std::size_t count, char8_t ch)
1309 {
1310 m_string.insert(index, count, static_cast<char32_t>(ch));
1311 return *this;
1312 }
1313
1314 inline String& String::insert(std::size_t index, const std::u8string& str, std::size_t pos, std::size_t count)
1315 {
1316 m_string.insert(index, String{str, pos, count}.m_string);
1317 return *this;
1318 }
1319
1320 inline String& String::insert(std::size_t index, const char8_t* str, std::size_t count)
1321 {
1322 m_string.insert(index, String{str, count}.m_string);
1323 return *this;
1324 }
1325
1326 inline String::iterator String::insert(String::const_iterator pos, char8_t ch)
1327 {
1328 return m_string.insert(pos, static_cast<char32_t>(ch));
1329 }
1330
1331 inline String::iterator String::insert(String::const_iterator pos, std::size_t count, char8_t ch)
1332 {
1333 return m_string.insert(pos, count, static_cast<char32_t>(ch));
1334 }
1335
1336 inline String::iterator String::insert(String::const_iterator pos, std::initializer_list<char8_t> chars)
1337 {
1338 const std::u32string tmpStr(utf::convertUtf8toUtf32(chars.begin(), chars.end()));
1339 return m_string.insert(pos, tmpStr.begin(), tmpStr.end());
1340 }
1341
1342 inline String::iterator String::insert(String::const_iterator pos, std::u8string::const_iterator first, std::u8string::const_iterator last)
1343 {
1344 const std::u32string tmpStr(utf::convertUtf8toUtf32(first, last));
1345 return m_string.insert(pos, tmpStr.begin(), tmpStr.end());
1346 }
1347
1348 inline String& String::append(std::size_t count, char8_t ch)
1349 {
1350 m_string.append(count, static_cast<char32_t>(ch));
1351 return *this;
1352 }
1353
1354 inline String& String::append(const std::u8string& str, std::size_t pos, std::size_t count)
1355 {
1356 m_string.append(String{str, pos, count}.m_string);
1357 return *this;
1358 }
1359
1360 inline String& String::append(const char8_t* str, std::size_t count)
1361 {
1362 m_string.append(String{str, count}.m_string);
1363 return *this;
1364 }
1365
1366 inline String& String::append(std::initializer_list<char8_t> chars)
1367 {
1368 m_string.append(String{chars}.m_string);
1369 return *this;
1370 }
1371
1372 inline String& String::append(std::u8string::const_iterator first, std::u8string::const_iterator last)
1373 {
1374 m_string.append(String{first, last}.m_string);
1375 return *this;
1376 }
1377
1378 inline int String::compare(std::size_t pos1, std::size_t count1, const std::u8string& str, std::size_t pos2, std::size_t count2) const
1379 {
1380 return m_string.compare(pos1, count1, String{str, pos2, count2}.m_string);
1381 }
1382
1383 inline int String::compare(std::size_t pos1, std::size_t count1, const char8_t* s, std::size_t count2) const
1384 {
1385 return m_string.compare(pos1, count1, String{s, count2}.m_string);
1386 }
1387
1388 inline String& String::replace(std::size_t pos, std::size_t count, const std::u8string& str, std::size_t pos2, std::size_t count2)
1389 {
1390 m_string.replace(pos, count, String{str, pos2, count2}.m_string);
1391 return *this;
1392 }
1393
1394 inline String& String::replace(const_iterator first, const_iterator last, std::u8string::const_iterator first2, std::u8string::const_iterator last2)
1395 {
1396 m_string.replace(first, last, String{first2, last2}.m_string);
1397 return *this;
1398 }
1399
1400 inline String& String::replace(std::size_t pos, std::size_t count, const char8_t* cstr, std::size_t count2)
1401 {
1402 m_string.replace(pos, count, String{cstr, count2}.m_string);
1403 return *this;
1404 }
1405
1406 inline String& String::replace(const_iterator first, const_iterator last, const char8_t* cstr, std::size_t count2)
1407 {
1408 m_string.replace(first, last, String{cstr, count2}.m_string);
1409 return *this;
1410 }
1411
1412 inline String& String::replace(std::size_t pos, std::size_t count, std::size_t count2, char8_t ch)
1413 {
1414 m_string.replace(pos, count, String(count2, ch).m_string);
1415 return *this;
1416 }
1417
1418 inline String& String::replace(const_iterator first, const_iterator last, std::size_t count2, char8_t ch)
1419 {
1420 m_string.replace(first, last, String(count2, ch).m_string);
1421 return *this;
1422 }
1423
1424 inline String& String::replace(const_iterator first, const_iterator last, std::initializer_list<char8_t> chars)
1425 {
1426 m_string.replace(first, last, String{chars}.m_string);
1427 return *this;
1428 }
1429
1430 inline void String::resize(std::size_t count, char8_t ch)
1431 {
1432 m_string.resize(count, static_cast<char32_t>(ch));
1433 }
1434
1435 inline bool String::contains(char8_t c) const noexcept
1436 {
1437 return contains(static_cast<char32_t>(c));
1438 }
1439
1440 inline std::size_t String::find(const char8_t* s, std::size_t pos, std::size_t count) const
1441 {
1442 return m_string.find(String{s, count}.m_string, pos);
1443 }
1444
1445 inline std::size_t String::find(char8_t ch, std::size_t pos) const noexcept
1446 {
1447 return m_string.find(static_cast<char32_t>(ch), pos);
1448 }
1449
1450 inline std::size_t String::find_first_of(const char8_t* s, std::size_t pos, std::size_t count) const
1451 {
1452 return m_string.find_first_of(String{s, count}.m_string, pos);
1453 }
1454
1455 inline std::size_t String::find_first_of(char8_t ch, std::size_t pos) const noexcept
1456 {
1457 return m_string.find_first_of(static_cast<char32_t>(ch), pos);
1458 }
1459
1460 inline std::size_t String::find_first_not_of(const char8_t* s, std::size_t pos, std::size_t count) const
1461 {
1462 return m_string.find_first_not_of(String{s, count}.m_string, pos);
1463 }
1464
1465 inline std::size_t String::find_first_not_of(char8_t ch, std::size_t pos) const noexcept
1466 {
1467 return m_string.find_first_not_of(static_cast<char32_t>(ch), pos);
1468 }
1469
1470 inline std::size_t String::rfind(const char8_t* s, std::size_t pos, std::size_t count) const
1471 {
1472 return m_string.rfind(String{s, count}.m_string, pos);
1473 }
1474
1475 inline std::size_t String::rfind(char8_t ch, std::size_t pos) const noexcept
1476 {
1477 return m_string.rfind(static_cast<char32_t>(ch), pos);
1478 }
1479
1480 inline std::size_t String::find_last_of(const char8_t* s, std::size_t pos, std::size_t count) const
1481 {
1482 return m_string.find_last_of(String{s, count}.m_string, pos);
1483 }
1484
1485 inline std::size_t String::find_last_of(char8_t ch, std::size_t pos) const noexcept
1486 {
1487 return m_string.find_last_of(static_cast<char32_t>(ch), pos);
1488 }
1489
1490 inline std::size_t String::find_last_not_of(const char8_t* s, std::size_t pos, std::size_t count) const
1491 {
1492 return m_string.find_last_not_of(String{s, count}.m_string, pos);
1493 }
1494
1495 inline std::size_t String::find_last_not_of(char8_t ch, std::size_t pos) const noexcept
1496 {
1497 return m_string.find_last_not_of(static_cast<char8_t>(ch), pos);
1498 }
1499
1500 inline bool String::starts_with(char8_t ch) const noexcept
1501 {
1502 return viewStartsWith(StringView(m_string), static_cast<char32_t>(ch));
1503 }
1504
1505 inline bool String::ends_with(char8_t ch) const noexcept
1506 {
1507 return viewEndsWith(StringView(m_string), static_cast<char32_t>(ch));
1508 }
1509#endif
1510
1512}
1513
1515
1516#endif // TGUI_STRING_HPP
Wrapper class to store strings.
Definition String.hpp:94
bool endsWithIgnoreCase(const String &substring) const
Checks whether the last part of the string matches the given substring, case-insensitive.
bool attemptToFloat(float &result) const
Converts the string to a float.
float toFloat(float defaultValue=0) const
Converts the string to a float.
bool equalIgnoreCase(const String &other) const
Compares this string to another and checks if they are equal if ASCII letters would have been lowerca...
bool startsWith(const String &substring) const
Checks whether the first part of the string matches the given substring.
static String fromNumber(T value)
Construct the string from a number.
Definition String.hpp:300
static String join(const std::vector< String > &segments, const String &separator)
Joins multiple string segments into a single string.
bool endsWith(const String &substring) const
Checks whether the last part of the string matches the given substring.
bool attemptToUInt(unsigned int &result) const
Converts the string to an unsigned int.
String trim() const
Returns a string with the whitespace at the start and end of this string removed.
bool startsWithIgnoreCase(const String &substring) const
Checks whether the first part of the string matches the given substring, case-insensitive.
unsigned int toUInt(unsigned int defaultValue=0) const
Converts the string to an unsigned int.
static String fromNumberRounded(T value, unsigned int decimals)
Construct the string from a floating point number, keeping only a certain amount of decimals behind t...
Definition String.hpp:327
int toInt(int defaultValue=0) const
Converts the string to an integer.
void remove(const String &substring)
Removes all occurrences of the given substring.
std::vector< String > split(const String &delimiter, bool trim=false) const
Splits the string into multiple substrings given the delimiter that separates them.
String toLower() const
Converts the ASCII characters in the string to lowercase.
bool attemptToInt(int &result) const
Converts the string to an integer.
String & replace(const String &searchFor, const String &replaceWith)
Replaces all occurrences of a substring with a replacement string.
String toUpper() const
Converts the ASCII characters in the string to uppercase.
Namespace that contains all TGUI functions and classes.
Definition AbsoluteOrRelativeValue.hpp:36
bool viewStartsWith(CharStringView viewToLookInto, CharStringView viewToLookFor)
Checks whether the view starts with the given substring.
Definition StringView.hpp:461
TGUI_API bool isWhitespace(char character)
Checks if a character is a whitespace character (e.g. space, tab, carriage return,...
bool viewEndsWith(CharStringView viewToLookInto, CharStringView viewToLookFor)
Checks whether the view ends with the given substring.
Definition StringView.hpp:490
TGUI_API bool isDigit(char32_t character)
Checks whether a character is digit (only 0 to 9 are considered digits, no unicode characters are)
TGUI_API bool isAlpha(char32_t character)
Checks whether a character is an alphabetic character.