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