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