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