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