CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
String.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
12
14
15#include <iosfwd>
16#include <string>
17#include <string_view>
18
19#if __has_include(<fmt/format.h>)
20#define CE_HAS_FMT 1
21#include <fmt/format.h>
22#endif
23
24namespace CeresEngine {
25
26 template<typename T, typename CharTraits = std::char_traits<T>, typename RawAllocator = DefaultAllocator> class BasicString;
27 template<typename T, typename CharTraits = std::char_traits<T>> class BasicStringView;
28
29 template<typename Self, typename T, typename CharTraits>
31 private:
34
35 public:
37
38 public:
39 template<typename Func> void split(const StringViewType delimiter, Func&& func, bool skipEmpty = false) const;
40 template<typename Func> void split(const T delimiter, Func&& func) const;
41
42 public: // Parsing & formatting
45 template<typename U, typename... Args> [[nodiscard]] U to(Args&&... args) const;
46
47 private:
49 StringViewType view() const { return StringViewType(self()); }
50
52 const Self& self() const { return static_cast<const Self&>(*this); }
53
55 Self& self() { return static_cast<Self&>(*this); }
56 };
57
59 template<typename T, typename CharTraits, typename RawAllocator>
60 class BasicString : public std::basic_string<T, CharTraits, StdAllocator<T, RawAllocator>>, public BasicStringBase<BasicString<T, CharTraits, RawAllocator>, T, CharTraits> {
61 using super = std::basic_string<T, CharTraits, StdAllocator<T, RawAllocator>>;
62
63 public:
65 CE_EXPLICIT(false) BasicString(const super& other) : super(other) {}
66
68 CE_EXPLICIT(false) BasicString(super&& other) : super(std::move(other)) {}
69
70 BasicString(const BasicString& str) = default;
71 BasicString(BasicString&& str) noexcept = default;
72
73 using super::super;
74 using super::operator=;
75
76 BasicString& operator=(const BasicString& str) = default;
78
79#if defined(CE_HAS_FMT)
80 public: // Formatting
82 template<typename... Args> inline BasicString format(Args&&... args) {
83 return fromString(this->get_allocator(), *this, std::forward<Args>(args)...);
84 }
85
87 template<typename S, typename... Args> requires(std::is_same_v<fmt::char_t<S>, T>)
88 [[nodiscard]]static inline BasicString fromFormat(const S& format, Args&&... args) {
89 BasicString string;
90 string.reserve(fmt::formatted_size(fmt::detail::to_string_view(format), args...));
91 fmt::format_to(std::back_inserter(string), fmt::detail::to_string_view(format), std::forward<Args>(args)...);
92 return string;
93 }
94
96 template<typename S, typename... Args> requires(std::is_same_v<fmt::char_t<S>, T>)
97 [[nodiscard]]static inline BasicString fromFormat(RawAllocator& allocator, const S& format, Args&&... args) {
98 BasicString string(allocator);
99 string.reserve(fmt::formatted_size(fmt::detail::to_string_view(format), args...));
100 fmt::format_to(std::back_inserter(string), fmt::detail::to_string_view(format), std::forward<Args>(args)...);
101 return string;
102 }
103#endif
104
105 public: // Parsing & formatting
108 template<typename U, typename... Args> [[nodiscard]] static decltype(auto) from(U value, Args&&... args);
109
110 public:
112 CE_EXPLICIT(false) operator const super&() const { return *this; }
113
115 CE_EXPLICIT(false) operator super&() { return *this; }
116 };
117
118 template<typename T, typename CharTraits, typename RawAllocator>
120 using super = std::basic_string<T, CharTraits, StdAllocator<T, RawAllocator>>;
121 return BasicString<T, CharTraits, RawAllocator>(static_cast<const super&>(lhs) + rhs);
122 }
123
124 template<typename T, typename CharTraits, typename RawAllocator>
126 using super = std::basic_string<T, CharTraits, StdAllocator<T, RawAllocator>>;
127 return BasicString<T, CharTraits, RawAllocator>(lhs + static_cast<const super&>(rhs));
128 }
129
131 template<typename T, typename CharTraits = std::char_traits<T>> using TemporaryBasicString = BasicString<T, CharTraits, TemporaryAllocator>;
132
134 // template<typename T, typename CharTraits = std::char_traits<T>> using BasicStringView = std::basic_string_view<T, CharTraits>;
135 template<typename T, typename CharTraits> class BasicStringView : public std::basic_string_view<T, CharTraits>, public BasicStringBase<BasicStringView<T, CharTraits>, T, CharTraits> {
136 using super = std::basic_string_view<T, CharTraits>;
137
138 public:
139 template<typename RawAllocator> constexpr BasicStringView(const BasicString<T, CharTraits, RawAllocator>& string) : super(string) {}
140
142 template<typename Allocator> CE_EXPLICIT(false) constexpr BasicStringView(const std::basic_string<T, CharTraits, Allocator>& other) : super(other) {}
143
146
149
150 using super::super;
151 };
152
153 // ---------------------------------------------------------------------------------------------
154
155 template<typename Self, typename T, typename CharTraits>
157 return self().find(text) != Self::npos;
158 }
159
160 // ---------------------------------------------------------------------------------------------
161
164
167
171
174
177
180
183
186
187 // ---------------------------------------------------------------------------------------------
188
191
195
198
201
202 // ---------------------------------------------------------------------------------------------
203
206 template<typename T> struct CiCharTraits : public std::char_traits<T> {
207 static bool eq(T c1, T c2) { return std::toupper(c1) == std::toupper(c2); }
208 static bool ne(T c1, T c2) { return std::toupper(c1) != std::toupper(c2); }
209 static bool lt(T c1, T c2) { return std::toupper(c1) < std::toupper(c2); }
210
211 static int compare(const T* s1, const T* s2, size_t n) {
212 while(n-- != 0) {
213 if(std::toupper(*s1) < std::toupper(*s2)) {
214 return -1;
215 }
216
217 if(std::toupper(*s1) > std::toupper(*s2)) {
218 return 1;
219 }
220
221 ++s1;
222 ++s2;
223 }
224 return 0;
225 }
226
227 static const T* find(const T* s, int n, T a) {
228 const auto ua = std::toupper(a);
229 while(n-- > 0) {
230 if(std::toupper(*s) == ua) {
231 return s;
232 }
233 s++;
234 }
235 return nullptr;
236 }
237 };
238
240 template<typename T, typename RawAllocator = DefaultAllocator> using CiBasicString = BasicString<T, CiCharTraits<T>, RawAllocator>;
241
244
247
248 // ---------------------------------------------------------------------------------------------
249
253
256
260
263
266
269
272
275
276 // ---------------------------------------------------------------------------------------------
277
281
285
288
291
292 // ---------------------------------------------------------------------------------------------
293
294 template<typename T, typename RawAllocator> CiBasicStringView<T> toCaseInsensitive(const BasicString<T, RawAllocator>& view) {
295 return CiBasicStringView<T>(view.data(), view.length());
296 }
297 template<typename T, typename RawAllocator> CiBasicStringView<T> toCaseInsensitive(const CiBasicString<T, RawAllocator>& view) {
298 return CiBasicStringView<T>(view.data(), view.length());
299 }
300 template<typename T> CiBasicStringView<T> toCaseInsensitive(BasicStringView<T> view) { return CiBasicStringView<T>(view.data(), view.length()); }
301 template<typename T> CiBasicStringView<T> toCaseInsensitive(CiBasicStringView<T> view) { return view; }
302
303 template<typename T, typename RawAllocator> BasicStringView<T> toCaseSensitive(const CiBasicString<T, RawAllocator>& view) {
304 return BasicStringView<T>(view.data(), view.length());
305 }
306 template<typename T, typename CharTraits, typename RawAllocator> BasicStringView<T> toCaseSensitive(const BasicString<T, CharTraits, RawAllocator>& view) {
307 return BasicStringView<T>(view.data(), view.length());
308 }
309 template<typename T> BasicStringView<T> toCaseSensitive(CiBasicStringView<T> view) { return BasicStringView<T>(view.data(), view.length()); }
310 template<typename T> BasicStringView<T> toCaseSensitive(BasicStringView<T> view) { return view; }
311
312 // ---------------------------------------------------------------------------------------------
313
314 template<size_t N> struct StringLiteral {
315 char value[N];
316 size_t length = N;
317 constexpr StringLiteral(const char (&str)[N]) { std::copy_n(str, N, value); }
318 };
319
320 // ---------------------------------------------------------------------------------------------
321
322 using namespace std::string_literals;
323 using namespace std::string_view_literals;
324
325 inline String operator"" _s(const char* str, const size_t length) { return String(str, length); }
326
327 // ---------------------------------------------------------------------------------------------
328
331 template<typename T> struct StringConversion;
332
334 template<> struct StringConversion<bool> {
335 static String toString(bool value);
336 static bool fromString(StringView string, bool defaultValue = false);
337 };
338
339#define CE_STRING_CONVERSION_DECL(T) \
340 template<> struct StringConversion<T> { \
341 static String toString(T val, unsigned short width = 0, char fill = ' '); \
342 static T fromString(StringView string, T defaultValue = 0); \
343 }
354#if !CE_COMPILER_GNUC
356#endif
357#undef CE_STRING_CONVERSION_DECL
358
360 template<typename C, typename RawAllocator> struct StringConversion<BasicString<C, RawAllocator>> {
362
363 static String toString(const T& value) { return String(value); }
364 static T fromString(StringView string, const T& defaultValue = false) { return T(string); }
365 };
366
367 namespace impl {
368 template<typename T, typename U> concept CSame = std::is_same_v<T, U>;
369
370 template<typename T> concept ToStringMemberCallable = requires(const T& value) { value.toString(); };
371 } // namespace impl
372
374 template<impl::ToStringMemberCallable T> struct StringConversion<T> {
375 static decltype(auto) toString(const T& value) { return value.toString(); }
376 };
377
380 template<typename T> concept ConvertibleToString = requires(T value) { StringConversion<T>::toString(value); };
381
384 template<typename T, typename CharTraits, typename RawAllocator>
385 template<typename U, typename... Args>
386 [[nodiscard]] decltype(auto) BasicString<T, CharTraits, RawAllocator>::from(U value, Args&&... args) {
387 return StringConversion<U>::toString(value, std::forward<Args>(args)...);
388 }
389
392 template<typename T>
393 concept ConvertibleFromString = requires(StringView string) {
394 { StringConversion<T>::fromString(string) } -> impl::CSame<T>;
395 };
396
399 template<typename Self, typename T, typename CharTraits>
400 template<typename U, typename... Args>
402 return StringConversion<U>::fromString(view(), std::forward<Args>(args)...);
403 }
404
405 // ---------------------------------------------------------------------------------------------
406
407 template<typename Self, typename T, typename CharTraits>
408 template<typename Func>
410 using SizeT = typename Self::size_type;
411 StringViewType view = self();
412
415
416 for(SizeT i = 0; i < view.size(); i++) {
417 if(view.substr(i, delimiter.size()) == delimiter) {
420
421 const SizeT index = indexCommaToLeftOfColumn + 1;
422 const SizeT length = indexCommaToRightOfColumn - index;
423 if(skipEmpty && length == 0) {
424 continue;
425 }
426
427 func(view.substr(index, length));
428 i += delimiter.size() - 1;
429 }
430 }
431
432 const SizeT index = indexCommaToLeftOfColumn + 1;
433 const SizeT length = view.size() - indexCommaToRightOfColumn - 1;
434
435 if(skipEmpty && length == 0) {
436 return;
437 }
438
439 func(view.substr(index, length));
440 }
441
442 template<typename Self, typename T, typename CharTraits>
443 template<typename Func>
445 using SizeT = typename Self::size_type;
446 StringViewType view = self();
447
450
451 for(SizeT i = 0; i < view.size(); i++) {
452 if(view.at(i) == delimiter) {
455
456 const SizeT index = indexCommaToLeftOfColumn + 1;
457 const SizeT length = indexCommaToRightOfColumn - index;
458
459 func(view.substr(index, length));
460 }
461 }
462
463 func(view.substr(indexCommaToRightOfColumn + 1, view.size() - indexCommaToRightOfColumn - 1));
464 }
465
466 // ---------------------------------------------------------------------------------------------
467
468 template<typename T, typename RawAllocator> inline BasicString<T, RawAllocator> operator+(const BasicString<T, RawAllocator>& lhs, BasicStringView<T> rhs) {
470 string.append(rhs);
471 return string;
472 }
473
474 template<typename T, typename RawAllocator> inline BasicString<T, RawAllocator> operator+(BasicString<T, RawAllocator>&& lhs, BasicStringView<T> rhs) {
475 return std::move(lhs.append(rhs));
476 }
477
478} // namespace Cere
#define CE_EXPLICIT(EXPR)
Definition Macros.hpp:413
#define CE_STRING_CONVERSION_DECL(T)
Definition String.hpp:339
Definition String.hpp:30
Self & self()
Converts a BasicStringBase into the underlying Type.
Definition String.hpp:55
StringViewType view() const
Converts a BasicStringBase into a StringViewType.
Definition String.hpp:49
BasicStringView< T, CharTraits > StringViewType
Definition String.hpp:33
bool contains(const BasicStringView< T, CharTraits > &text) const
Definition String.hpp:156
U to(Args &&... args) const
Converts the string into it's object representation.
Definition String.hpp:401
void split(const StringViewType delimiter, Func &&func, bool skipEmpty=false) const
Definition String.hpp:409
void split(const T delimiter, Func &&func) const
Definition String.hpp:444
const Self & self() const
Converts a BasicStringBase into the underlying Type.
Definition String.hpp:52
Basic string that uses framework's memory allocators.
Definition String.hpp:60
BasicString(const BasicString &str)=default
static decltype(auto) from(U value, Args &&... args)
Converts a value into it's string representation.
Definition String.hpp:386
BasicString & operator=(BasicString &&str)=default
BasicString(BasicString &&str) noexcept=default
BasicString & operator=(const BasicString &str)=default
std::basic_string< T, CharTraits, StdAllocator< T, RawAllocator > > super
Definition String.hpp:61
Basic string view.
Definition String.hpp:135
constexpr BasicStringView(const BasicString< T, CharTraits, RawAllocator > &string)
Definition String.hpp:139
std::basic_string_view< T, CharTraits > super
Definition String.hpp:136
A concept that checks if the type T can be converted from a StringView by using a StringConverter.
Definition String.hpp:393
A concept that checks if the type T is convertible to a String by using a StringConverter.
Definition String.hpp:380
Definition String.hpp:368
Definition Application.hpp:19
std::uint64_t UInt64
Definition DataTypes.hpp:26
BasicStringView< char > StringView
Narrow string view used for handling narrow encoded text in UTF-8.
Definition String.hpp:190
CiBasicStringView< T > toCaseInsensitive(const BasicString< T, RawAllocator > &view)
Definition String.hpp:294
foonathan::memory::temporary_allocator TemporaryAllocator
Definition Allocator.hpp:110
auto move(Vector3 position)
Moves a entity to the given position.
Definition Helpers.hpp:22
std::int32_t Int32
Definition DataTypes.hpp:21
std::uint16_t UInt16
Definition DataTypes.hpp:20
std::uint8_t UInt8
Definition DataTypes.hpp:17
std::int64_t Int64
Definition DataTypes.hpp:24
BasicStringView< T > toCaseSensitive(const CiBasicString< T, RawAllocator > &view)
Definition String.hpp:303
std::uint32_t UInt32
Definition DataTypes.hpp:23
BasicString< T, CharTraits, RawAllocator > operator+(const BasicString< T, CharTraits, RawAllocator > &lhs, const T *rhs)
Definition String.hpp:119
BasicString< char > String
Narrow string used for handling narrow encoded text in UTF-8.
Definition String.hpp:163
std::int8_t Int8
Definition DataTypes.hpp:15
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
std::int16_t Int16
Definition DataTypes.hpp:18
Definition Span.hpp:668
Case insensitive character traits structure.
Definition String.hpp:206
static const T * find(const T *s, int n, T a)
Definition String.hpp:227
static int compare(const T *s1, const T *s2, size_t n)
Definition String.hpp:211
static bool lt(T c1, T c2)
Definition String.hpp:209
static bool ne(T c1, T c2)
Definition String.hpp:208
static bool eq(T c1, T c2)
Definition String.hpp:207
static T fromString(StringView string, const T &defaultValue=false)
Definition String.hpp:364
static String toString(const T &value)
Definition String.hpp:363
static decltype(auto) toString(const T &value)
Definition String.hpp:375
static bool fromString(StringView string, bool defaultValue=false)
static String toString(bool value)
A template that can be specialized to implement toString and fromString.
Definition String.hpp:331
Definition String.hpp:314
size_t length
Definition String.hpp:316
char value[N]
Definition String.hpp:315
constexpr StringLiteral(const char(&str)[N])
Definition String.hpp:317