TGUI 1.11
Loading...
Searching...
No Matches
StringView.hpp
1
2//
3// TGUI - Texus' Graphical User Interface
4// Copyright (C) 2012-2025 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_VIEW_HPP
26#define TGUI_STRING_VIEW_HPP
27
28#include <string>
29#include <cctype> // tolower
30#include <algorithm> // equal, min
31
32#if TGUI_COMPILED_WITH_CPP_VER >= 17
33 #include <string_view>
34#endif
35
37
38#if TGUI_COMPILED_WITH_CPP_VER >= 17
39namespace tgui
40{
41 inline namespace literals
42 {
43 inline namespace string_view_literals
44 {
45 // Allow using operator ""sv
46 // Note that this only affects code placed inside the tgui namespace.
47 using namespace std::literals::string_view_literals;
48 }
49 }
50}
51#endif
52
53namespace tgui
54{
55#if TGUI_COMPILED_WITH_CPP_VER >= 17
56 using StringView = std::u32string_view;
57 using CharStringView = std::string_view;
58#else
59 template <typename Type>
60 struct TypeIdentity
61 {
62 using type = Type;
63 };
64
65 template<typename Type>
66 using TypeIdentity_t = typename TypeIdentity<Type>::type;
67
68 template <typename CharType>
69 class StringViewImpl
70 {
71 public:
72 using const_iterator = const CharType*;
73
74 constexpr StringViewImpl() = default;
75 constexpr StringViewImpl(const StringViewImpl& other) = default;
76
77 constexpr StringViewImpl(const CharType* str, std::size_t strLength) :
78 m_string(str),
79 m_length(strLength)
80 {
81 }
82
83 constexpr StringViewImpl(const CharType* str) :
84 m_string(str),
85 m_length(std::char_traits<CharType>::length(str))
86 {
87 }
88
89 constexpr StringViewImpl(const std::basic_string<CharType>& str) :
90 m_string(str.data()),
91 m_length(str.length())
92 {
93 }
94
95 TGUI_NODISCARD constexpr const_iterator begin() const noexcept
96 {
97 return m_string;
98 }
99 TGUI_NODISCARD constexpr const_iterator cbegin() const noexcept
100 {
101 return m_string;
102 }
103
104 TGUI_NODISCARD constexpr const_iterator end() const noexcept
105 {
106 return m_string + static_cast<std::ptrdiff_t>(m_length);
107 }
108 TGUI_NODISCARD constexpr const_iterator cend() const noexcept
109 {
110 return m_string + static_cast<std::ptrdiff_t>(m_length);
111 }
112
113 TGUI_NODISCARD constexpr const CharType& operator[](std::size_t index) const
114 {
115 return m_string[index];
116 }
117
118 TGUI_NODISCARD constexpr const CharType& front() const
119 {
120 return m_string[0];
121 }
122
123 TGUI_NODISCARD constexpr const CharType& back() const
124 {
125 return m_string[m_length-1];
126 }
127
128 TGUI_NODISCARD constexpr const CharType* data() const noexcept
129 {
130 return m_string;
131 }
132
133 TGUI_NODISCARD constexpr std::size_t size() const noexcept
134 {
135 return m_length;
136 }
137 TGUI_NODISCARD constexpr std::size_t length() const noexcept
138 {
139 return m_length;
140 }
141
142 TGUI_NODISCARD constexpr bool empty() const noexcept
143 {
144 return (m_length == 0);
145 }
146
147 TGUI_NODISCARD constexpr StringViewImpl substr(std::size_t pos = 0, std::size_t count = std::u32string::npos) const
148 {
149 if (count != std::u32string::npos)
150 return StringViewImpl(&m_string[pos], count);
151 else
152 return StringViewImpl(&m_string[pos], m_length - pos);
153 }
154
155 TGUI_NODISCARD constexpr int compare(StringViewImpl strView) const noexcept
156 {
157 const std::size_t rlen = std::min(length(), strView.length());
158 const int ret = std::char_traits<CharType>::compare(data(), strView.data(), rlen);
159 if (ret != 0)
160 return ret;
161
162 if (length() < strView.length())
163 return -1;
164 else if (length() > strView.length())
165 return 1;
166 else
167 return 0;
168 }
169
170 TGUI_NODISCARD constexpr std::size_t find(StringViewImpl strView, std::size_t pos = 0) const noexcept
171 {
172 if (empty() || (strView.length() > m_length))
173 return std::u32string::npos;
174
175 if (strView.empty())
176 return pos;
177
178 for (std::size_t i = pos; i <= m_length - strView.length(); ++i)
179 {
180 if (m_string[i] != strView[0])
181 continue;
182
183 bool found = true;
184 for (std::size_t j = 1; j < strView.length(); ++j)
185 {
186 if (m_string[i+j] != strView[j])
187 {
188 found = false;
189 break;
190 }
191 }
192
193 if (found)
194 return i;
195 }
196
197 return std::u32string::npos;
198 }
199
200 TGUI_NODISCARD constexpr std::size_t find(CharType ch, std::size_t pos = 0) const noexcept
201 {
202 return find(StringViewImpl(&ch, 1), pos);
203 }
204 TGUI_NODISCARD constexpr std::size_t find(const CharType* str, std::size_t pos, std::size_t count) const
205 {
206 return find(StringViewImpl(str, count), pos);
207 }
208 TGUI_NODISCARD constexpr std::size_t find(const CharType* str, std::size_t pos = 0) const
209 {
210 return find(StringViewImpl(str), pos);
211 }
212
213 private:
214 const CharType* m_string = nullptr;
215 std::size_t m_length = 0;
216 };
217
218 template <typename CharType>
219 TGUI_NODISCARD constexpr bool operator==(StringViewImpl<CharType> lhs, TypeIdentity_t<StringViewImpl<CharType>> rhs) noexcept
220 {
221 return lhs.compare(rhs) == 0;
222 }
223
224 template <typename CharType>
225 TGUI_NODISCARD constexpr bool operator!=(StringViewImpl<CharType> lhs, TypeIdentity_t<StringViewImpl<CharType>> rhs) noexcept
226 {
227 return lhs.compare(rhs) != 0;
228 }
229
230 template <typename CharType>
231 TGUI_NODISCARD constexpr bool operator<(StringViewImpl<CharType> lhs, TypeIdentity_t<StringViewImpl<CharType>> rhs) noexcept
232 {
233 return lhs.compare(rhs) < 0;
234 }
235
236 template <typename CharType>
237 TGUI_NODISCARD constexpr bool operator<=(StringViewImpl<CharType> lhs, TypeIdentity_t<StringViewImpl<CharType>> rhs) noexcept
238 {
239 return lhs.compare(rhs) <= 0;
240 }
241
242 template <typename CharType>
243 TGUI_NODISCARD constexpr bool operator>(StringViewImpl<CharType> lhs, TypeIdentity_t<StringViewImpl<CharType>> rhs) noexcept
244 {
245 return lhs.compare(rhs) > 0;
246 }
247
248 template <typename CharType>
249 TGUI_NODISCARD constexpr bool operator>=(StringViewImpl<CharType> lhs, TypeIdentity_t<StringViewImpl<CharType>> rhs) noexcept
250 {
251 return lhs.compare(rhs) >= 0;
252 }
253
254 using StringView = StringViewImpl<char32_t>;
255 using CharStringView = StringViewImpl<char>;
256
257 // Allow using operator ""sv
258 // Note that this only affects code placed inside the tgui namespace.
259#if defined(__clang__)
260# pragma clang diagnostic push
261# pragma clang diagnostic ignored "-Wuser-defined-literals"
262#elif defined(__GNUC__)
263# pragma GCC diagnostic push
264# pragma GCC diagnostic ignored "-Wliteral-suffix"
265#elif defined (_MSC_VER)
266# pragma warning(push)
267# pragma warning(disable: 4455) // literal suffix identifiers that do not start with an underscore are reserved
268#endif
269 inline namespace literals
270 {
271 inline namespace string_view_literals
272 {
273 inline constexpr StringViewImpl<char> operator""sv(const char* str, size_t len) noexcept
274 {
275 return StringViewImpl<char>{str, len};
276 }
277
278 inline constexpr StringViewImpl<wchar_t> operator""sv(const wchar_t* str, size_t len) noexcept
279 {
280 return StringViewImpl<wchar_t>{str, len};
281 }
282
283 inline constexpr StringViewImpl<char16_t> operator""sv(const char16_t* str, size_t len) noexcept
284 {
285 return StringViewImpl<char16_t>{str, len};
286 }
287
288 inline constexpr StringViewImpl<char32_t> operator""sv(const char32_t* str, size_t len) noexcept
289 {
290 return StringViewImpl<char32_t>{str, len};
291 }
292 }
293 }
294#if defined(__clang__)
295# pragma clang diagnostic pop
296#elif defined(__GNUC__)
297# pragma GCC diagnostic pop
298#elif defined (_MSC_VER)
299# pragma warning(pop)
300#endif
301
302#endif // TGUI_COMPILED_WITH_CPP_VER
303
312 TGUI_NODISCARD inline bool viewEqualIgnoreCase(CharStringView view1, CharStringView view2)
313 {
314 return std::equal(view1.begin(), view1.end(), view2.begin(), view2.end(),
315 [](char char1, char char2)
316 {
317 if (char1 == char2)
318 return true;
319 else
320 return std::tolower(static_cast<unsigned char>(char1)) == std::tolower(static_cast<unsigned char>(char2));
321 }
322 );
323 }
324
333 TGUI_NODISCARD inline bool viewEqualIgnoreCase(StringView view1, StringView view2)
334 {
335 return std::equal(view1.begin(), view1.end(), view2.begin(), view2.end(),
336 [](char32_t char1, char32_t char2)
337 {
338 if (char1 == char2)
339 return true;
340 else if ((char1 < 128) && (char2 < 128))
341 return std::tolower(static_cast<unsigned char>(char1)) == std::tolower(static_cast<unsigned char>(char2));
342 else
343 return false;
344 }
345 );
346 }
347
348#if TGUI_COMPILED_WITH_CPP_VER >= 17 && defined(__cpp_lib_starts_ends_with) && (__cpp_lib_starts_ends_with >= 201711L)
357 TGUI_NODISCARD inline bool viewStartsWith(CharStringView viewToLookInto, CharStringView viewToLookFor)
358 {
359 return viewToLookInto.starts_with(viewToLookFor);
360 }
361
370 TGUI_NODISCARD inline bool viewStartsWith(CharStringView viewToLookInto, char charToLookFor)
371 {
372 return viewToLookInto.starts_with(charToLookFor);
373 }
374
383 TGUI_NODISCARD inline bool viewEndsWith(CharStringView viewToLookInto, CharStringView viewToLookFor)
384 {
385 return viewToLookInto.ends_with(viewToLookFor);
386 }
387
396 TGUI_NODISCARD inline bool viewEndsWith(CharStringView viewToLookInto, char charToLookFor)
397 {
398 return viewToLookInto.ends_with(charToLookFor);
399 }
400
409 TGUI_NODISCARD inline bool viewStartsWith(StringView viewToLookInto, StringView viewToLookFor)
410 {
411 return viewToLookInto.starts_with(viewToLookFor);
412 }
413
422 TGUI_NODISCARD inline bool viewStartsWith(StringView viewToLookInto, char32_t charToLookFor)
423 {
424 return viewToLookInto.starts_with(charToLookFor);
425 }
426
435 TGUI_NODISCARD inline bool viewEndsWith(StringView viewToLookInto, StringView viewToLookFor)
436 {
437 return viewToLookInto.ends_with(viewToLookFor);
438 }
439
448 TGUI_NODISCARD inline bool viewEndsWith(StringView viewToLookInto, char32_t charToLookFor)
449 {
450 return viewToLookInto.ends_with(charToLookFor);
451 }
452#else
461 TGUI_NODISCARD inline bool viewStartsWith(CharStringView viewToLookInto, CharStringView viewToLookFor)
462 {
463 if (viewToLookFor.length() > viewToLookInto.length())
464 return false;
465
466 return viewToLookInto.substr(0, viewToLookFor.length()) == viewToLookFor;
467 }
468
477 TGUI_NODISCARD inline bool viewStartsWith(CharStringView viewToLookInto, char charToLookFor)
478 {
479 return !viewToLookInto.empty() && (viewToLookInto.front() == charToLookFor);
480 }
481
490 TGUI_NODISCARD inline bool viewEndsWith(CharStringView viewToLookInto, CharStringView viewToLookFor)
491 {
492 if (viewToLookFor.length() > viewToLookInto.length())
493 return false;
494
495 return CharStringView(viewToLookInto.data() + (viewToLookInto.length() - viewToLookFor.length()), viewToLookFor.length()).compare(viewToLookFor) == 0;
496 }
497
506 TGUI_NODISCARD inline bool viewEndsWith(CharStringView viewToLookInto, char charToLookFor)
507 {
508 return !viewToLookInto.empty() && (viewToLookInto.back() == charToLookFor);
509 }
510
519 TGUI_NODISCARD inline bool viewStartsWith(StringView viewToLookInto, StringView viewToLookFor)
520 {
521 if (viewToLookFor.length() > viewToLookInto.length())
522 return false;
523
524 return viewToLookInto.substr(0, viewToLookFor.length()) == viewToLookFor;
525 }
526
535 TGUI_NODISCARD inline bool viewStartsWith(StringView viewToLookInto, char32_t charToLookFor)
536 {
537 return !viewToLookInto.empty() && (viewToLookInto.front() == charToLookFor);
538 }
539
548 TGUI_NODISCARD inline bool viewEndsWith(StringView viewToLookInto, StringView viewToLookFor)
549 {
550 if (viewToLookFor.length() > viewToLookInto.length())
551 return false;
552
553 return StringView(viewToLookInto.data() + (viewToLookInto.length() - viewToLookFor.length()), viewToLookFor.length()).compare(viewToLookFor) == 0;
554 }
555
564 TGUI_NODISCARD inline bool viewEndsWith(StringView viewToLookInto, char32_t charToLookFor)
565 {
566 return !viewToLookInto.empty() && (viewToLookInto.back() == charToLookFor);
567 }
568#endif
569}
570
572
573#endif // TGUI_STRING_VIEW_HPP
Namespace that contains all TGUI functions and classes.
Definition AbsoluteOrRelativeValue.hpp:36
bool viewStartsWith(CharStringView viewToLookInto, CharStringView viewToLookFor)
Checks whether the view starts with the given substring.
Definition StringView.hpp:461
bool viewEqualIgnoreCase(CharStringView view1, CharStringView view2)
Returns whether two view are equal if letters would have been lowercase.
Definition StringView.hpp:312
bool viewEndsWith(CharStringView viewToLookInto, CharStringView viewToLookFor)
Checks whether the view ends with the given substring.
Definition StringView.hpp:490