TGUI  1.1
Loading...
Searching...
No Matches
String.hpp
1
2//
3// TGUI - Texus' Graphical User Interface
4// Copyright (C) 2012-2023 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
240 TGUI_DEPRECATED("Use starts_with instead") TGUI_NODISCARD bool startsWith(const String& substring) const;
241#endif
242
250 TGUI_NODISCARD bool startsWithIgnoreCase(const String& substring) const;
251
252#ifndef TGUI_REMOVE_DEPRECATED_CODE
260 TGUI_DEPRECATED("Use ends_with instead") TGUI_NODISCARD bool endsWith(const String& substring) const;
261#endif
262
270 TGUI_NODISCARD bool endsWithIgnoreCase(const String& substring) const;
271
272
281 String& replace(const String& searchFor, const String& replaceWith);
282
283
289 void remove(const String& substring);
290
291
298 TGUI_NODISCARD std::vector<String> split(const String& delimiter, bool trim = false) const;
299
300
307 TGUI_NODISCARD static String join(const std::vector<String>& segments, const String& separator);
308
309
317 template <typename T>
318 TGUI_NODISCARD static String fromNumber(T value)
319 {
320 std::ostringstream oss;
321 oss.imbue(std::locale::classic());
322 oss << value;
323 return {oss.str()};
324 }
325
326
335 template <typename T>
336 TGUI_NODISCARD static String fromNumberRounded(T value, unsigned int decimals)
337 {
338 std::ostringstream oss;
339 oss.imbue(std::locale::classic());
340 oss << std::fixed << std::setprecision(static_cast<int>(decimals));
341 oss << value;
342 return {oss.str()};
343 }
344
346 public:
347
348 String() = default;
349
350 String(const std::string& str);
351 String(const std::wstring& str);
352 String(const std::u16string& str);
353 String(const std::u32string& str);
354
355 String(std::u32string&& str) :
356 m_string{std::move(str)}
357 {
358 }
359
360 String(char ansiChar);
361 String(wchar_t wideChar);
362 String(char16_t utfChar);
363 String(char32_t utfChar);
364
365 String(const char* str);
366 String(const wchar_t* str);
367 String(const char16_t* str);
368 String(const char32_t* str) :
369 m_string{str}
370 {
371 }
372
373 // Constructor to initialize the string from a number (integer or float)
374 template <typename T, typename = typename std::enable_if_t<std::is_arithmetic<T>::value, T>>
375 explicit String(T number) :
376 String{fromNumber(number)}
377 {
378 }
379
380 String(std::size_t count, char ch);
381 String(std::size_t count, wchar_t ch);
382 String(std::size_t count, char16_t ch);
383 String(std::size_t count, char32_t ch);
384
385 String(const std::string& str, std::size_t pos);
386 String(const std::wstring& str, std::size_t pos);
387 String(const std::u16string& str, std::size_t pos);
388 String(const std::u32string& str, std::size_t pos);
389
390 String(const std::string& str, std::size_t pos, std::size_t count);
391 String(const std::wstring& str, std::size_t pos, std::size_t count);
392 String(const std::u16string& str, std::size_t pos, std::size_t count);
393 String(const std::u32string& str, std::size_t pos, std::size_t count);
394
395 String(const char* str, std::size_t count);
396 String(const wchar_t* str, std::size_t count);
397 String(const char16_t* str, std::size_t count);
398 String(const char32_t* str, std::size_t count);
399
400 explicit String(std::initializer_list<char> chars);
401 explicit String(std::initializer_list<wchar_t> chars);
402 explicit String(std::initializer_list<char16_t> chars);
403 explicit String(std::initializer_list<char32_t> chars);
404
405 // Constructors using iterators have to be explicit to prevent {"1", "2"} to be ambiguous between String and std::vector<String>.
406 // The reason these constructors were considered a candicate to clang is due to a private constructor in the iterator class.
407 // We can't accept string_view::const_iterator iterators, because it would lead to the same kind of ambiguity even when the
408 // 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).
409 explicit String(std::string::const_iterator first, std::string::const_iterator last);
410 explicit String(std::wstring::const_iterator first, std::wstring::const_iterator last);
411 explicit String(std::u16string::const_iterator first, std::u16string::const_iterator last);
412 explicit String(std::u32string::const_iterator first, std::u32string::const_iterator last);
413
414#if TGUI_COMPILED_WITH_CPP_VER >= 17
415 template <typename StringViewType, typename = IsStringViewType<StringViewType>>
416 explicit String(const StringViewType& stringView) :
417 String(stringView.data(), stringView.size())
418 {
419 }
420
421 template <typename StringViewType, typename = IsStringViewType<StringViewType>>
422 explicit String(const StringViewType& stringView, std::size_t pos, std::size_t count) :
423 String(stringView.data() + pos, count)
424 {
425 }
426#else
427 template <typename CharType>
428 explicit String(StringViewImpl<CharType> stringView) :
429 String(stringView.data(), stringView.size())
430 {
431 }
432
433 template <typename CharType>
434 explicit String(StringViewImpl<CharType> stringView, std::size_t pos, std::size_t count) :
435 String(stringView.data() + pos, count)
436 {
437 }
438#endif
439
440#if TGUI_HAS_WINDOW_BACKEND_SFML
441 // This constructor has to be explicit or it will cause MSVC to no longer compile code that performs sf::String + std::string
442 explicit String(const sf::String& str)
443 : m_string{reinterpret_cast<const char32_t*>(str.toUtf32().c_str())}
444 {
445 }
446
447 explicit operator sf::String() const
448 {
449 return sf::String::fromUtf32(m_string.begin(), m_string.end());
450 }
451#endif
452
453 explicit operator std::string() const;
454 explicit operator std::wstring() const;
455 explicit operator std::u16string() const;
456 explicit operator const std::u32string&() const
457 {
458 return m_string;
459 }
460
461 operator StringView() const noexcept
462 {
463#if TGUI_COMPILED_WITH_CPP_VER >= 17
464 return m_string;
465#else
466 return StringView(m_string.data(), m_string.length());
467#endif
468 }
469
470 TGUI_NODISCARD std::string toStdString() const;
471 TGUI_NODISCARD std::wstring toWideString() const;
472 TGUI_NODISCARD std::u16string toUtf16() const;
473 TGUI_NODISCARD const std::u32string& toUtf32() const
474 {
475 return m_string;
476 }
477
478 String& assign(std::size_t count, char ch);
479 String& assign(std::size_t count, wchar_t ch);
480 String& assign(std::size_t count, char16_t ch);
481 String& assign(std::size_t count, char32_t ch);
482
483 String& assign(StringView sv);
484 String& assign(const char32_t* str);
485 String& assign(const std::u32string& str);
486 String& assign(const String& str);
487
488 String& assign(StringView sv, std::size_t pos, std::size_t count = npos);
489 String& assign(const std::string& str, std::size_t pos, std::size_t count = npos);
490 String& assign(const std::wstring& str, std::size_t pos, std::size_t count = npos);
491 String& assign(const std::u16string& str, std::size_t pos, std::size_t count = npos);
492 String& assign(const std::u32string& str, std::size_t pos, std::size_t count = npos);
493 String& assign(const String& str, std::size_t pos, std::size_t count = npos);
494
495 String& assign(std::u32string&& str);
496 String& assign(String&& str);
497
498 String& assign(const char* str, std::size_t count);
499 String& assign(const wchar_t* str, std::size_t count);
500 String& assign(const char16_t* str, std::size_t count);
501 String& assign(const char32_t* str, std::size_t count);
502
503 String& assign(std::initializer_list<char> chars);
504 String& assign(std::initializer_list<wchar_t> chars);
505 String& assign(std::initializer_list<char16_t> chars);
506 String& assign(std::initializer_list<char32_t> chars);
507
508 String& assign(std::string::const_iterator first, std::string::const_iterator last);
509 String& assign(std::wstring::const_iterator first, std::wstring::const_iterator last);
510 String& assign(std::u16string::const_iterator first, std::u16string::const_iterator last);
511 String& assign(std::u32string::const_iterator first, std::u32string::const_iterator last);
512 String& assign(StringView::const_iterator first, StringView::const_iterator last);
513
514 TGUI_NODISCARD reference at(std::size_t pos);
515 TGUI_NODISCARD const_reference at(std::size_t pos) const;
516
517 TGUI_NODISCARD const_reference operator [](std::size_t index) const;
518 TGUI_NODISCARD reference operator [](std::size_t index);
519
520 TGUI_NODISCARD reference front();
521 TGUI_NODISCARD const_reference front() const;
522
523 TGUI_NODISCARD reference back();
524 TGUI_NODISCARD const_reference back() const;
525
526 TGUI_NODISCARD const char32_t* data() const noexcept
527 {
528 return m_string.data();
529 }
530
531 TGUI_NODISCARD char32_t* data() noexcept
532 {
533#if __cplusplus >= 201703L
534 return m_string.data();
535#else
536 return &m_string[0];
537#endif
538 }
539
540 TGUI_NODISCARD const char32_t* c_str() const noexcept
541 {
542 return m_string.c_str();
543 }
544
545 TGUI_NODISCARD iterator begin() noexcept;
546 TGUI_NODISCARD const_iterator begin() const noexcept;
547 TGUI_NODISCARD const_iterator cbegin() const noexcept;
548
549 TGUI_NODISCARD iterator end() noexcept;
550 TGUI_NODISCARD const_iterator end() const noexcept;
551 TGUI_NODISCARD const_iterator cend() const noexcept;
552
553 TGUI_NODISCARD reverse_iterator rbegin() noexcept;
554 TGUI_NODISCARD const_reverse_iterator rbegin() const noexcept;
555 TGUI_NODISCARD const_reverse_iterator crbegin() const noexcept;
556
557 TGUI_NODISCARD reverse_iterator rend() noexcept;
558 TGUI_NODISCARD const_reverse_iterator rend() const noexcept;
559 TGUI_NODISCARD const_reverse_iterator crend() const noexcept;
560
561 TGUI_NODISCARD bool empty() const noexcept
562 {
563 return m_string.empty();
564 }
565
566 TGUI_NODISCARD std::size_t size() const noexcept
567 {
568 return m_string.size();
569 }
570
571 TGUI_NODISCARD std::size_t length() const noexcept
572 {
573 return m_string.length();
574 }
575
576 TGUI_NODISCARD std::size_t max_size() const noexcept;
577
578 void reserve(std::size_t newCap);
579 TGUI_NODISCARD std::size_t capacity() const noexcept;
580 void shrink_to_fit();
581
582 void clear() noexcept;
583
584 String& insert(std::size_t index, std::size_t count, char ch);
585 String& insert(std::size_t index, std::size_t count, wchar_t ch);
586 String& insert(std::size_t index, std::size_t count, char16_t ch);
587 String& insert(std::size_t index, std::size_t count, char32_t ch);
588
589 String& insert(std::size_t index, StringView sv);
590 String& insert(std::size_t index, const char32_t* str);
591 String& insert(std::size_t index, const std::u32string& str);
592 String& insert(std::size_t index, const String& str);
593
594 String& insert(std::size_t index, StringView sv, std::size_t pos, std::size_t count = npos);
595 String& insert(std::size_t index, const std::string& str, std::size_t pos, std::size_t count = npos);
596 String& insert(std::size_t index, const std::wstring& str, std::size_t pos, std::size_t count = npos);
597 String& insert(std::size_t index, const std::u16string& str, std::size_t pos, std::size_t count = npos);
598 String& insert(std::size_t index, const std::u32string& str, std::size_t pos, std::size_t count = npos);
599 String& insert(std::size_t index, const String& str, std::size_t pos, std::size_t count = npos);
600
601 String& insert(std::size_t index, const char* str, std::size_t count);
602 String& insert(std::size_t index, const wchar_t* str, std::size_t count);
603 String& insert(std::size_t index, const char16_t* str, std::size_t count);
604 String& insert(std::size_t index, const char32_t* str, std::size_t count);
605
606 iterator insert(const_iterator pos, char ch);
607 iterator insert(const_iterator pos, wchar_t ch);
608 iterator insert(const_iterator pos, char16_t ch);
609 iterator insert(const_iterator pos, char32_t ch);
610
611 iterator insert(const_iterator pos, std::size_t count, char ch);
612 iterator insert(const_iterator pos, std::size_t count, wchar_t ch);
613 iterator insert(const_iterator pos, std::size_t count, char16_t ch);
614 iterator insert(const_iterator pos, std::size_t count, char32_t ch);
615
616 iterator insert(const_iterator pos, std::initializer_list<char> chars);
617 iterator insert(const_iterator pos, std::initializer_list<wchar_t> chars);
618 iterator insert(const_iterator pos, std::initializer_list<char16_t> chars);
619 iterator insert(const_iterator pos, std::initializer_list<char32_t> chars);
620
621 iterator insert(const_iterator pos, std::string::const_iterator first, std::string::const_iterator last);
622 iterator insert(const_iterator pos, std::wstring::const_iterator first, std::wstring::const_iterator last);
623 iterator insert(const_iterator pos, std::u16string::const_iterator first, std::u16string::const_iterator last);
624 iterator insert(const_iterator pos, std::u32string::const_iterator first, std::u32string::const_iterator last);
625 iterator insert(const_iterator pos, StringView::const_iterator first, StringView::const_iterator last);
626
627 String& erase(std::size_t index = 0, std::size_t count = npos);
628
629 iterator erase(const_iterator position);
630 iterator erase(const_iterator first, const_iterator last);
631
632 void push_back(char ch);
633 void push_back(wchar_t ch);
634 void push_back(char16_t ch);
635 void push_back(char32_t ch);
636
637 void pop_back();
638
639 String& append(std::size_t count, char ch);
640 String& append(std::size_t count, wchar_t ch);
641 String& append(std::size_t count, char16_t ch);
642 String& append(std::size_t count, char32_t ch);
643
644 String& append(StringView sv);
645 String& append(const char32_t* str);
646 String& append(const std::u32string& str);
647 String& append(const String& str);
648
649 String& append(StringView sv, std::size_t pos, std::size_t count = npos);
650 String& append(const std::string& str, std::size_t pos, std::size_t count = npos);
651 String& append(const std::wstring& str, std::size_t pos, std::size_t count = npos);
652 String& append(const std::u16string& str, std::size_t pos, std::size_t count = npos);
653 String& append(const std::u32string& str, std::size_t pos, std::size_t count = npos);
654 String& append(const String& str, std::size_t pos, std::size_t count = npos);
655
656 String& append(const char* str, std::size_t count);
657 String& append(const wchar_t* str, std::size_t count);
658 String& append(const char16_t* str, std::size_t count);
659 String& append(const char32_t* str, std::size_t count);
660
661 String& append(std::string::const_iterator first, std::string::const_iterator last);
662 String& append(std::wstring::const_iterator first, std::wstring::const_iterator last);
663 String& append(std::u16string::const_iterator first, std::u16string::const_iterator last);
664 String& append(std::u32string::const_iterator first, std::u32string::const_iterator last);
665 String& append(StringView::const_iterator first, StringView::const_iterator last);
666
667 String& append(std::initializer_list<char> chars);
668 String& append(std::initializer_list<wchar_t> chars);
669 String& append(std::initializer_list<char16_t> chars);
670 String& append(std::initializer_list<char32_t> chars);
671
672 String& operator+=(const String& str);
673
674 TGUI_NODISCARD int compare(StringView sv) const noexcept;
675 TGUI_NODISCARD int compare(const char32_t* s) const;
676 TGUI_NODISCARD int compare(const std::u32string& str) const noexcept;
677 TGUI_NODISCARD int compare(const String& str) const noexcept;
678
679 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, StringView sv) const;
680 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const char32_t* s) const;
681 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const std::u32string& str) const;
682 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const String& str) const;
683
684 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, StringView sv, std::size_t pos2, std::size_t count2 = npos) const;
685 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;
686 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;
687 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;
688 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;
689 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;
690
691 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const char* s, std::size_t count2) const;
692 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const wchar_t* s, std::size_t count2) const;
693 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const char16_t* s, std::size_t count2) const;
694 TGUI_NODISCARD int compare(std::size_t pos1, std::size_t count1, const char32_t* s, std::size_t count2) const;
695
696 String& replace(std::size_t pos, std::size_t count, StringView sv);
697 String& replace(std::size_t pos, std::size_t count, const char32_t* cstr);
698 String& replace(std::size_t pos, std::size_t count, const std::u32string& str);
699 String& replace(std::size_t pos, std::size_t count, const String& str);
700
701 String& replace(const_iterator first, const_iterator last, StringView sv);
702 String& replace(const_iterator first, const_iterator last, const char32_t* cstr);
703 String& replace(const_iterator first, const_iterator last, const std::u32string& str);
704 String& replace(const_iterator first, const_iterator last, const String& str);
705
706 String& replace(std::size_t pos, std::size_t count, StringView sv, std::size_t pos2, std::size_t count2 = npos);
707 String& replace(std::size_t pos, std::size_t count, const std::string& str, std::size_t pos2, std::size_t count2 = npos);
708 String& replace(std::size_t pos, std::size_t count, const std::wstring& str, std::size_t pos2, std::size_t count2 = npos);
709 String& replace(std::size_t pos, std::size_t count, const std::u16string& str, std::size_t pos2, std::size_t count2 = npos);
710 String& replace(std::size_t pos, std::size_t count, const std::u32string& str, std::size_t pos2, std::size_t count2 = npos);
711 String& replace(std::size_t pos, std::size_t count, const String& str, std::size_t pos2, std::size_t count2 = npos);
712
713 String& replace(const_iterator first, const_iterator last, std::string::const_iterator first2, std::string::const_iterator last2);
714 String& replace(const_iterator first, const_iterator last, std::wstring::const_iterator first2, std::wstring::const_iterator last2);
715 String& replace(const_iterator first, const_iterator last, std::u16string::const_iterator first2, std::u16string::const_iterator last2);
716 String& replace(const_iterator first, const_iterator last, std::u32string::const_iterator first2, std::u32string::const_iterator last2);
717 String& replace(const_iterator first, const_iterator last, StringView::const_iterator first2, StringView::const_iterator last2);
718
719 String& replace(std::size_t pos, std::size_t count, const char* cstr, std::size_t count2);
720 String& replace(std::size_t pos, std::size_t count, const wchar_t* cstr, std::size_t count2);
721 String& replace(std::size_t pos, std::size_t count, const char16_t* cstr, std::size_t count2);
722 String& replace(std::size_t pos, std::size_t count, const char32_t* cstr, std::size_t count2);
723
724 String& replace(const_iterator first, const_iterator last, const char* cstr, std::size_t count2);
725 String& replace(const_iterator first, const_iterator last, const wchar_t* cstr, std::size_t count2);
726 String& replace(const_iterator first, const_iterator last, const char16_t* cstr, std::size_t count2);
727 String& replace(const_iterator first, const_iterator last, const char32_t* cstr, std::size_t count2);
728
729 String& replace(std::size_t pos, std::size_t count, std::size_t count2, char ch);
730 String& replace(std::size_t pos, std::size_t count, std::size_t count2, wchar_t ch);
731 String& replace(std::size_t pos, std::size_t count, std::size_t count2, char16_t ch);
732 String& replace(std::size_t pos, std::size_t count, std::size_t count2, char32_t ch);
733
734 String& replace(const_iterator first, const_iterator last, std::size_t count2, char ch);
735 String& replace(const_iterator first, const_iterator last, std::size_t count2, wchar_t ch);
736 String& replace(const_iterator first, const_iterator last, std::size_t count2, char16_t ch);
737 String& replace(const_iterator first, const_iterator last, std::size_t count2, char32_t ch);
738
739 String& replace(const_iterator first, const_iterator last, std::initializer_list<char> chars);
740 String& replace(const_iterator first, const_iterator last, std::initializer_list<wchar_t> chars);
741 String& replace(const_iterator first, const_iterator last, std::initializer_list<char16_t> chars);
742 String& replace(const_iterator first, const_iterator last, std::initializer_list<char32_t> chars);
743
744 TGUI_NODISCARD String substr(std::size_t pos = 0, std::size_t count = npos) const;
745
746 std::size_t copy(char32_t* dest, std::size_t count, std::size_t pos = 0) const;
747
748 void resize(std::size_t count);
749 void resize(std::size_t count, char ch);
750 void resize(std::size_t count, wchar_t ch);
751 void resize(std::size_t count, char16_t ch);
752 void resize(std::size_t count, char32_t ch);
753
754 void swap(String& other);
755
756 TGUI_NODISCARD bool contains(char c) const noexcept;
757 TGUI_NODISCARD bool contains(wchar_t c) const noexcept;
758 TGUI_NODISCARD bool contains(char16_t c) const noexcept;
759 TGUI_NODISCARD bool contains(char32_t c) const noexcept;
760
761 TGUI_NODISCARD bool contains(StringView sv) const noexcept;
762 TGUI_NODISCARD bool contains(const char32_t* s) const;
763 TGUI_NODISCARD bool contains(const std::u32string& s) const;
764 TGUI_NODISCARD bool contains(const String& s) const;
765
766 TGUI_NODISCARD std::size_t find(StringView sv, std::size_t pos = 0) const noexcept;
767 TGUI_NODISCARD std::size_t find(const char32_t* s, std::size_t pos = 0) const;
768 TGUI_NODISCARD std::size_t find(const std::u32string& str, std::size_t pos = 0) const noexcept;
769 TGUI_NODISCARD std::size_t find(const String& str, std::size_t pos = 0) const noexcept;
770
771 TGUI_NODISCARD std::size_t find(const char* s, std::size_t pos, std::size_t count) const;
772 TGUI_NODISCARD std::size_t find(const wchar_t* s, std::size_t pos, std::size_t count) const;
773 TGUI_NODISCARD std::size_t find(const char16_t* s, std::size_t pos, std::size_t count) const;
774 TGUI_NODISCARD std::size_t find(const char32_t* s, std::size_t pos, std::size_t count) const;
775
776 TGUI_NODISCARD std::size_t find(char ch, std::size_t pos = 0) const noexcept;
777 TGUI_NODISCARD std::size_t find(wchar_t ch, std::size_t pos = 0) const noexcept;
778 TGUI_NODISCARD std::size_t find(char16_t ch, std::size_t pos = 0) const noexcept;
779 TGUI_NODISCARD std::size_t find(char32_t ch, std::size_t pos = 0) const noexcept;
780
781 TGUI_NODISCARD std::size_t find_first_of(StringView sv, std::size_t pos = 0) const noexcept;
782 TGUI_NODISCARD std::size_t find_first_of(const char32_t* s, std::size_t pos = 0) const;
783 TGUI_NODISCARD std::size_t find_first_of(const std::u32string& str, std::size_t pos = 0) const noexcept;
784 TGUI_NODISCARD std::size_t find_first_of(const String& str, std::size_t pos = 0) const noexcept;
785
786 TGUI_NODISCARD std::size_t find_first_of(const char* s, std::size_t pos, std::size_t count) const;
787 TGUI_NODISCARD std::size_t find_first_of(const wchar_t* s, std::size_t pos, std::size_t count) const;
788 TGUI_NODISCARD std::size_t find_first_of(const char16_t* s, std::size_t pos, std::size_t count) const;
789 TGUI_NODISCARD std::size_t find_first_of(const char32_t* s, std::size_t pos, std::size_t count) const;
790
791 TGUI_NODISCARD std::size_t find_first_of(char ch, std::size_t pos = 0) const noexcept;
792 TGUI_NODISCARD std::size_t find_first_of(wchar_t ch, std::size_t pos = 0) const noexcept;
793 TGUI_NODISCARD std::size_t find_first_of(char16_t ch, std::size_t pos = 0) const noexcept;
794 TGUI_NODISCARD std::size_t find_first_of(char32_t ch, std::size_t pos = 0) const noexcept;
795
796 TGUI_NODISCARD std::size_t find_first_not_of(StringView sv, std::size_t pos = 0) const noexcept;
797 TGUI_NODISCARD std::size_t find_first_not_of(const char32_t* s, std::size_t pos = 0) const;
798 TGUI_NODISCARD std::size_t find_first_not_of(const std::u32string& str, std::size_t pos = 0) const noexcept;
799 TGUI_NODISCARD std::size_t find_first_not_of(const String& str, std::size_t pos = 0) const noexcept;
800
801 TGUI_NODISCARD std::size_t find_first_not_of(const char* s, std::size_t pos, std::size_t count) const;
802 TGUI_NODISCARD std::size_t find_first_not_of(const wchar_t* s, std::size_t pos, std::size_t count) const;
803 TGUI_NODISCARD std::size_t find_first_not_of(const char16_t* s, std::size_t pos, std::size_t count) const;
804 TGUI_NODISCARD std::size_t find_first_not_of(const char32_t* s, std::size_t pos, std::size_t count) const;
805
806 TGUI_NODISCARD std::size_t find_first_not_of(char ch, std::size_t pos = 0) const noexcept;
807 TGUI_NODISCARD std::size_t find_first_not_of(wchar_t ch, std::size_t pos = 0) const noexcept;
808 TGUI_NODISCARD std::size_t find_first_not_of(char16_t ch, std::size_t pos = 0) const noexcept;
809 TGUI_NODISCARD std::size_t find_first_not_of(char32_t ch, std::size_t pos = 0) const noexcept;
810
811 TGUI_NODISCARD std::size_t rfind(StringView sv, std::size_t pos = npos) const noexcept;
812 TGUI_NODISCARD std::size_t rfind(const char32_t* s, std::size_t pos = npos) const;
813 TGUI_NODISCARD std::size_t rfind(const std::u32string& str, std::size_t pos = npos) const noexcept;
814 TGUI_NODISCARD std::size_t rfind(const String& str, std::size_t pos = npos) const noexcept;
815
816 TGUI_NODISCARD std::size_t rfind(const char* s, std::size_t pos, std::size_t count) const;
817 TGUI_NODISCARD std::size_t rfind(const wchar_t* s, std::size_t pos, std::size_t count) const;
818 TGUI_NODISCARD std::size_t rfind(const char16_t* s, std::size_t pos, std::size_t count) const;
819 TGUI_NODISCARD std::size_t rfind(const char32_t* s, std::size_t pos, std::size_t count) const;
820
821 TGUI_NODISCARD std::size_t rfind(char ch, std::size_t pos = npos) const noexcept;
822 TGUI_NODISCARD std::size_t rfind(wchar_t ch, std::size_t pos = npos) const noexcept;
823 TGUI_NODISCARD std::size_t rfind(char16_t ch, std::size_t pos = npos) const noexcept;
824 TGUI_NODISCARD std::size_t rfind(char32_t ch, std::size_t pos = npos) const noexcept;
825
826 TGUI_NODISCARD std::size_t find_last_of(StringView sv, std::size_t pos = npos) const noexcept;
827 TGUI_NODISCARD std::size_t find_last_of(const char32_t* s, std::size_t pos = npos) const;
828 TGUI_NODISCARD std::size_t find_last_of(const std::u32string& str, std::size_t pos = npos) const noexcept;
829 TGUI_NODISCARD std::size_t find_last_of(const String& str, std::size_t pos = npos) const noexcept;
830
831 TGUI_NODISCARD std::size_t find_last_of(const char* s, std::size_t pos, std::size_t count) const;
832 TGUI_NODISCARD std::size_t find_last_of(const wchar_t* s, std::size_t pos, std::size_t count) const;
833 TGUI_NODISCARD std::size_t find_last_of(const char16_t* s, std::size_t pos, std::size_t count) const;
834 TGUI_NODISCARD std::size_t find_last_of(const char32_t* s, std::size_t pos, std::size_t count) const;
835
836 TGUI_NODISCARD std::size_t find_last_of(char ch, std::size_t pos = npos) const noexcept;
837 TGUI_NODISCARD std::size_t find_last_of(wchar_t ch, std::size_t pos = npos) const noexcept;
838 TGUI_NODISCARD std::size_t find_last_of(char16_t ch, std::size_t pos = npos) const noexcept;
839 TGUI_NODISCARD std::size_t find_last_of(char32_t ch, std::size_t pos = npos) const noexcept;
840
841 TGUI_NODISCARD std::size_t find_last_not_of(StringView sv, std::size_t pos = npos) const noexcept;
842 TGUI_NODISCARD std::size_t find_last_not_of(const char32_t* s, std::size_t pos = npos) const;
843 TGUI_NODISCARD std::size_t find_last_not_of(const std::u32string& str, std::size_t pos = npos) const noexcept;
844 TGUI_NODISCARD std::size_t find_last_not_of(const String& str, std::size_t pos = npos) const noexcept;
845
846 TGUI_NODISCARD std::size_t find_last_not_of(const char* s, std::size_t pos, std::size_t count) const;
847 TGUI_NODISCARD std::size_t find_last_not_of(const wchar_t* s, std::size_t pos, std::size_t count) const;
848 TGUI_NODISCARD std::size_t find_last_not_of(const char16_t* s, std::size_t pos, std::size_t count) const;
849 TGUI_NODISCARD std::size_t find_last_not_of(const char32_t* s, std::size_t pos, std::size_t count) const;
850
851 TGUI_NODISCARD std::size_t find_last_not_of(char ch, std::size_t pos = npos) const noexcept;
852 TGUI_NODISCARD std::size_t find_last_not_of(wchar_t ch, std::size_t pos = npos) const noexcept;
853 TGUI_NODISCARD std::size_t find_last_not_of(char16_t ch, std::size_t pos = npos) const noexcept;
854 TGUI_NODISCARD std::size_t find_last_not_of(char32_t ch, std::size_t pos = npos) const noexcept;
855
856 TGUI_NODISCARD inline bool starts_with(StringView sv) const noexcept;
857 TGUI_NODISCARD inline bool starts_with(const char32_t* s) const;
858 TGUI_NODISCARD inline bool starts_with(const std::u32string& s) const;
859 TGUI_NODISCARD inline bool starts_with(const String& s) const;
860
861 TGUI_NODISCARD inline bool starts_with(char ch) const noexcept;
862 TGUI_NODISCARD inline bool starts_with(wchar_t ch) const noexcept;
863 TGUI_NODISCARD inline bool starts_with(char16_t ch) const noexcept;
864 TGUI_NODISCARD inline bool starts_with(char32_t ch) const noexcept;
865
866 TGUI_NODISCARD inline bool ends_with(StringView sv) const noexcept;
867 TGUI_NODISCARD inline bool ends_with(const char32_t* s) const;
868 TGUI_NODISCARD inline bool ends_with(const std::u32string& s) const;
869 TGUI_NODISCARD inline bool ends_with(const String& s) const;
870
871 TGUI_NODISCARD inline bool ends_with(char ch) const noexcept;
872 TGUI_NODISCARD inline bool ends_with(wchar_t ch) const noexcept;
873 TGUI_NODISCARD inline bool ends_with(char16_t ch) const noexcept;
874 TGUI_NODISCARD inline bool ends_with(char32_t ch) const noexcept;
875
876 TGUI_NODISCARD std::size_t count(const char ch, const std::size_t pos = 0) const noexcept;
877 TGUI_NODISCARD std::size_t count(const wchar_t ch, const std::size_t pos = 0) const noexcept;
878 TGUI_NODISCARD std::size_t count(const char16_t ch, const std::size_t pos = 0) const noexcept;
879 TGUI_NODISCARD std::size_t count(const char32_t ch, const std::size_t pos = 0) const noexcept;
880
881 inline friend bool operator==(const String& left, StringView right);
882 inline friend bool operator==(const String& left, const char32_t* right);
883 inline friend bool operator==(const String& left, const std::u32string& right);
884 inline friend bool operator==(const String& left, const String& right);
885
886 inline friend bool operator!=(const String& left, StringView right);
887 inline friend bool operator!=(const String& left, const char32_t* right);
888 inline friend bool operator!=(const String& left, const std::u32string& right);
889 inline friend bool operator!=(const String& left, const String& right);
890
891 inline friend bool operator<(const String& left, StringView right);
892 inline friend bool operator<(const String& left, const char32_t* right);
893 inline friend bool operator<(const String& left, const std::u32string& right);
894 inline friend bool operator<(const String& left, const String& right);
895
896 inline friend bool operator<=(const String& left, StringView right);
897 inline friend bool operator<=(const String& left, const char32_t* right);
898 inline friend bool operator<=(const String& left, const std::u32string& right);
899 inline friend bool operator<=(const String& left, const String& right);
900
901 inline friend bool operator>(const String& left, StringView right);
902 inline friend bool operator>(const String& left, const char32_t* right);
903 inline friend bool operator>(const String& left, const std::u32string& right);
904 inline friend bool operator>(const String& left, const String& right);
905
906 inline friend bool operator>=(const String& left, StringView right);
907 inline friend bool operator>=(const String& left, const char32_t* right);
908 inline friend bool operator>=(const String& left, const std::u32string& right);
909 inline friend bool operator>=(const String& left, const String& right);
910
911 inline friend String operator+(const String& left, const String& right);
912 inline friend String operator+(const String& left, String&& right);
913 inline friend String operator+(String&& left, const String& right);
914 inline friend String operator+(String&& left, String&& right);
915
916#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201811L)
917 inline String(const std::u8string& str);
918 inline String(char8_t utfChar);
919 inline String(const char8_t* str);
920 inline String(std::size_t count, char8_t ch);
921 inline String(const std::u8string& str, std::size_t pos);
922 inline String(const std::u8string& str, std::size_t pos, std::size_t count);
923 inline String(const char8_t* str, std::size_t count);
924 inline explicit String(std::initializer_list<char8_t> chars);
925 inline explicit String(std::u8string::const_iterator first, std::u8string::const_iterator last);
926
927 inline explicit operator std::u8string() const;
928
929 TGUI_NODISCARD inline std::u8string toUtf8() const;
930
931 inline String& assign(std::size_t count, char8_t ch);
932 inline String& assign(const std::u8string& str, std::size_t pos, std::size_t count = npos);
933 inline String& assign(const char8_t* str, std::size_t count);
934 inline String& assign(std::initializer_list<char8_t> chars);
935 inline String& assign(std::u8string::const_iterator first, std::u8string::const_iterator last);
936
937 inline String& insert(std::size_t index, std::size_t count, char8_t ch);
938 inline String& insert(std::size_t index, const std::u8string& str, std::size_t pos, std::size_t count = npos);
939 inline String& insert(std::size_t index, const char8_t* str, std::size_t count);
940 inline iterator insert(const_iterator pos, char8_t ch);
941 inline iterator insert(const_iterator pos, std::size_t count, char8_t ch);
942 inline iterator insert(const_iterator pos, std::initializer_list<char8_t> chars);
943 inline iterator insert(const_iterator pos, std::u8string::const_iterator first, std::u8string::const_iterator last);
944
945 inline String& append(std::size_t count, char8_t ch);
946 inline String& append(const std::u8string& str, std::size_t pos, std::size_t count = npos);
947 inline String& append(const char8_t* str, std::size_t count);
948 inline String& append(std::initializer_list<char8_t> chars);
949 inline String& append(std::u8string::const_iterator first, std::u8string::const_iterator last);
950
951 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;
952 TGUI_NODISCARD inline int compare(std::size_t pos1, std::size_t count1, const char8_t* s, std::size_t count2) const;
953
954 inline String& replace(std::size_t pos, std::size_t count, const std::u8string& str, std::size_t pos2, std::size_t count2 = npos);
955 inline String& replace(const_iterator first, const_iterator last, std::u8string::const_iterator first2, std::u8string::const_iterator last2);
956 inline String& replace(std::size_t pos, std::size_t count, const char8_t* cstr, std::size_t count2);
957 inline String& replace(const_iterator first, const_iterator last, const char8_t* cstr, std::size_t count2);
958 inline String& replace(std::size_t pos, std::size_t count, std::size_t count2, char8_t ch);
959 inline String& replace(const_iterator first, const_iterator last, std::size_t count2, char8_t ch);
960 inline String& replace(const_iterator first, const_iterator last, std::initializer_list<char8_t> chars);
961
962 inline void resize(std::size_t count, char8_t ch);
963
964 TGUI_NODISCARD inline bool contains(char8_t c) const noexcept;
965
966 TGUI_NODISCARD inline std::size_t find(const char8_t* s, std::size_t pos, std::size_t count) const;
967 TGUI_NODISCARD inline std::size_t find(char8_t ch, std::size_t pos = 0) const noexcept;
968
969 TGUI_NODISCARD inline std::size_t find_first_of(const char8_t* s, std::size_t pos, std::size_t count) const;
970 TGUI_NODISCARD inline std::size_t find_first_of(char8_t ch, std::size_t pos = 0) const noexcept;
971
972 TGUI_NODISCARD inline std::size_t find_first_not_of(const char8_t* s, std::size_t pos, std::size_t count) const;
973 TGUI_NODISCARD inline std::size_t find_first_not_of(char8_t ch, std::size_t pos = 0) const noexcept;
974
975 TGUI_NODISCARD inline std::size_t rfind(const char8_t* s, std::size_t pos, std::size_t count) const;
976 TGUI_NODISCARD inline std::size_t rfind(char8_t ch, std::size_t pos = npos) const noexcept;
977
978 TGUI_NODISCARD inline std::size_t find_last_of(const char8_t* s, std::size_t pos, std::size_t count) const;
979 TGUI_NODISCARD inline std::size_t find_last_of(char8_t ch, std::size_t pos = npos) const noexcept;
980
981 TGUI_NODISCARD inline std::size_t find_last_not_of(const char8_t* s, std::size_t pos, std::size_t count) const;
982 TGUI_NODISCARD inline std::size_t find_last_not_of(char8_t ch, std::size_t pos = npos) const noexcept;
983
984 TGUI_NODISCARD inline bool starts_with(char8_t ch) const noexcept;
985 TGUI_NODISCARD inline bool ends_with(char8_t ch) const noexcept;
986#endif
987 };
988
990
991 inline bool String::starts_with(StringView sv) const noexcept
992 {
993 return viewStartsWith(StringView(m_string), sv);
994 }
995
996 inline bool String::starts_with(const char32_t* s) const
997 {
998 return viewStartsWith(StringView(m_string), StringView(s));
999 }
1000
1001 inline bool String::starts_with(const std::u32string& s) const
1002 {
1003 return viewStartsWith(StringView(m_string), StringView(s));
1004 }
1005
1006 inline bool String::starts_with(const String& s) const
1007 {
1008 return viewStartsWith(StringView(m_string), StringView(s));
1009 }
1010
1011 inline bool String::starts_with(char ch) const noexcept
1012 {
1013 return viewStartsWith(StringView(m_string), static_cast<char32_t>(ch));
1014 }
1015
1016 inline bool String::starts_with(wchar_t ch) const noexcept
1017 {
1018 return viewStartsWith(StringView(m_string), static_cast<char32_t>(ch));
1019 }
1020
1021 inline bool String::starts_with(char16_t ch) const noexcept
1022 {
1023 return viewStartsWith(StringView(m_string), static_cast<char32_t>(ch));
1024 }
1025
1026 inline bool String::starts_with(char32_t ch) const noexcept
1027 {
1028 return viewStartsWith(StringView(m_string), ch);
1029 }
1030
1031 inline bool String::ends_with(StringView sv) const noexcept
1032 {
1033 return viewEndsWith(StringView(m_string), sv);
1034 }
1035
1036 inline bool String::ends_with(const char32_t* s) const
1037 {
1038 return viewEndsWith(StringView(m_string), StringView(s));
1039 }
1040
1041 inline bool String::ends_with(const std::u32string& s) const
1042 {
1043 return viewEndsWith(StringView(m_string), StringView(s));
1044 }
1045
1046 inline bool String::ends_with(const String& s) const
1047 {
1048 return viewEndsWith(StringView(m_string), StringView(s));
1049 }
1050
1051 inline bool String::ends_with(char ch) const noexcept
1052 {
1053 return viewEndsWith(StringView(m_string), static_cast<char32_t>(ch));
1054 }
1055
1056 inline bool String::ends_with(wchar_t ch) const noexcept
1057 {
1058 return viewEndsWith(StringView(m_string), static_cast<char32_t>(ch));
1059 }
1060
1061 inline bool String::ends_with(char16_t ch) const noexcept
1062 {
1063 return viewEndsWith(StringView(m_string), static_cast<char32_t>(ch));
1064 }
1065
1066 inline bool String::ends_with(char32_t ch) const noexcept
1067 {
1068 return viewEndsWith(StringView(m_string), ch);
1069 }
1070
1071
1072 TGUI_NODISCARD inline bool operator==(const String& left, StringView right)
1073 {
1074 return StringView(left) == right;
1075 }
1076
1077 TGUI_NODISCARD inline bool operator==(const String& left, const char32_t* right)
1078 {
1079 return StringView(left) == right;
1080 }
1081
1082 TGUI_NODISCARD inline bool operator==(const String& left, const std::u32string& right)
1083 {
1084 return StringView(left) == right;
1085 }
1086
1087 TGUI_NODISCARD inline bool operator==(const String& left, const String& right)
1088 {
1089 return left.m_string == right.m_string;
1090 }
1091
1092 TGUI_NODISCARD inline bool operator!=(const String& left, StringView right)
1093 {
1094 return StringView(left) != right;
1095 }
1096
1097 TGUI_NODISCARD inline bool operator!=(const String& left, const char32_t* right)
1098 {
1099 return StringView(left) != right;
1100 }
1101
1102 TGUI_NODISCARD inline bool operator!=(const String& left, const std::u32string& right)
1103 {
1104 return StringView(left) != right;
1105 }
1106
1107 TGUI_NODISCARD inline bool operator!=(const String& left, const String& right)
1108 {
1109 return left.m_string != right.m_string;
1110 }
1111
1112 TGUI_NODISCARD inline bool operator<(const String& left, StringView right)
1113 {
1114 return StringView(left) < right;
1115 }
1116
1117 TGUI_NODISCARD inline bool operator<(const String& left, const char32_t* right)
1118 {
1119 return StringView(left) < right;
1120 }
1121
1122 TGUI_NODISCARD inline bool operator<(const String& left, const std::u32string& right)
1123 {
1124 return StringView(left) < right;
1125 }
1126
1127 TGUI_NODISCARD inline bool operator<(const String& left, const String& right)
1128 {
1129 return left.m_string < right.m_string;
1130 }
1131
1132 TGUI_NODISCARD inline bool operator<=(const String& left, StringView right)
1133 {
1134 return StringView(left) <= right;
1135 }
1136
1137 TGUI_NODISCARD inline bool operator<=(const String& left, const char32_t* right)
1138 {
1139 return StringView(left) <= right;
1140 }
1141
1142 TGUI_NODISCARD inline bool operator<=(const String& left, const std::u32string& right)
1143 {
1144 return StringView(left) <= right;
1145 }
1146
1147 TGUI_NODISCARD inline bool operator<=(const String& left, const String& right)
1148 {
1149 return left.m_string <= right.m_string;
1150 }
1151
1152 TGUI_NODISCARD inline bool operator>(const String& left, StringView right)
1153 {
1154 return StringView(left) > right;
1155 }
1156
1157 TGUI_NODISCARD inline bool operator>(const String& left, const char32_t* right)
1158 {
1159 return StringView(left) > right;
1160 }
1161
1162 TGUI_NODISCARD inline bool operator>(const String& left, const std::u32string& right)
1163 {
1164 return StringView(left) > right;
1165 }
1166
1167 TGUI_NODISCARD inline bool operator>(const String& left, const String& right)
1168 {
1169 return left.m_string > right.m_string;
1170 }
1171
1172 TGUI_NODISCARD inline bool operator>=(const String& left, StringView right)
1173 {
1174 return StringView(left) >= right;
1175 }
1176
1177 TGUI_NODISCARD inline bool operator>=(const String& left, const char32_t* right)
1178 {
1179 return StringView(left) >= right;
1180 }
1181
1182 TGUI_NODISCARD inline bool operator>=(const String& left, const std::u32string& right)
1183 {
1184 return StringView(left) >= right;
1185 }
1186
1187 TGUI_NODISCARD inline bool operator>=(const String& left, const String& right)
1188 {
1189 return left.m_string >= right.m_string;
1190 }
1191
1192 TGUI_NODISCARD inline String operator+(const String& left, const String& right)
1193 {
1194 return {left.m_string + right.m_string};
1195 }
1196 TGUI_NODISCARD inline String operator+(String&& left, String&& right)
1197 {
1198 return {std::move(left.m_string) + std::move(right.m_string)};
1199 }
1200 TGUI_NODISCARD inline String operator+(String&& left, const String& right)
1201 {
1202 return {std::move(left.m_string) + right.m_string};
1203 }
1204 TGUI_NODISCARD inline String operator+(const String& left, String&& right)
1205 {
1206 return {left.m_string + std::move(right.m_string)};
1207 }
1208
1209 // We don't provide operator<< implmentations for basic_ostream<charX_t> streams because
1210 // even clang 15 can't compile them when using libc++.
1211 // We could define them for VS, GCC and for clang with libstdc++, but there is no real use for them.
1212 TGUI_API std::ostream& operator<<(std::ostream& os, const String& str);
1213 TGUI_API std::wostream& operator<<(std::wostream& os, const String& str);
1214
1215 TGUI_API std::istream& operator>>(std::istream& os, String& str);
1216 TGUI_API std::wistream& operator>>(std::wistream& os, String& str);
1217
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: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:318
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:336
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