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