enum_name
Loading...
Searching...
No Matches
mgutility_enum_name.hpp
1/*
2MIT License
3
4Copyright (c) 2023 mguludag
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef MGUTILITY_ENUM_NAME_HPP
26#define MGUTILITY_ENUM_NAME_HPP
27
28/*
29MIT License
30
31Copyright (c) 2024 mguludag
32
33Permission is hereby granted, free of charge, to any person obtaining a copy
34of this software and associated documentation files (the "Software"), to deal
35in the Software without restriction, including without limitation the rights
36to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37copies of the Software, and to permit persons to whom the Software is
38furnished to do so, subject to the following conditions:
39
40The above copyright notice and this permission notice shall be included in all
41copies or substantial portions of the Software.
42
43THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
49SOFTWARE.
50*/
51
52#ifndef MGUTILITY_REFLECTION_DETAIL_ENUM_NAME_IMPL_HPP
53#define MGUTILITY_REFLECTION_DETAIL_ENUM_NAME_IMPL_HPP
54
55// NOLINTNEXTLINE [unused-includes]
56
57/*
58MIT License
59
60Copyright (c) 2024 mguludag
61
62Permission is hereby granted, free of charge, to any person obtaining a copy
63of this software and associated documentation files (the "Software"), to deal
64in the Software without restriction, including without limitation the rights
65to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66copies of the Software, and to permit persons to whom the Software is
67furnished to do so, subject to the following conditions:
68
69The above copyright notice and this permission notice shall be included in all
70copies or substantial portions of the Software.
71
72THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
78SOFTWARE.
79*/
80
81#ifndef DETAIL_ENUM_FOR_EACH_HPP
82#define DETAIL_ENUM_FOR_EACH_HPP
83
84/*
85MIT License
86
87Copyright (c) 2024 mguludag
88
89Permission is hereby granted, free of charge, to any person obtaining a copy
90of this software and associated documentation files (the "Software"), to deal
91in the Software without restriction, including without limitation the rights
92to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
93copies of the Software, and to permit persons to whom the Software is
94furnished to do so, subject to the following conditions:
95
96The above copyright notice and this permission notice shall be included in all
97copies or substantial portions of the Software.
98
99THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
100IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
101FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
102AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
103LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
104OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
105SOFTWARE.
106*/
107
108#ifndef DETAIL_META_HPP
109#define DETAIL_META_HPP
110
111/*
112MIT License
113
114Copyright (c) 2024 mguludag
115
116Permission is hereby granted, free of charge, to any person obtaining a copy
117of this software and associated documentation files (the "Software"), to deal
118in the Software without restriction, including without limitation the rights
119to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
120copies of the Software, and to permit persons to whom the Software is
121furnished to do so, subject to the following conditions:
122
123The above copyright notice and this permission notice shall be included in all
124copies or substantial portions of the Software.
125
126THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
127IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
128FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
129AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
130LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
131OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
132SOFTWARE.
133*/
134
135#ifndef MGUTILITY_COMMON_DEFINITIONS_HPP
136#define MGUTILITY_COMMON_DEFINITIONS_HPP
137
148#ifdef _MSC_VER
149#ifndef MGUTILITY_CPLUSPLUS
150#define MGUTILITY_CPLUSPLUS _MSVC_LANG
151#endif
152#else
153#ifndef MGUTILITY_CPLUSPLUS
154#define MGUTILITY_CPLUSPLUS __cplusplus
155#endif
156#endif
157
165#if MGUTILITY_CPLUSPLUS == 201103L
166#define MGUTILITY_CNSTXPR
167#elif MGUTILITY_CPLUSPLUS > 201103L
168#define MGUTILITY_CNSTXPR constexpr
169#elif MGUTILITY_CPLUSPLUS < 201103L
170#error "Standards older than C++11 is not supported!"
171#endif
172
181#if (MGUTILITY_CPLUSPLUS >= 201703L && !defined(__clang__)) || \
182 (defined(__clang__) && __clang_major__ > 11 && \
183 MGUTILITY_CPLUSPLUS >= 201703L)
184#define MGUTILITY_CNSTXPR_CLANG_WA constexpr
185#else
186#define MGUTILITY_CNSTXPR_CLANG_WA
187#endif
188
195#if MGUTILITY_CPLUSPLUS > 201703L
196#define MGUTILITY_CNSTEVL consteval
197#else
198#define MGUTILITY_CNSTEVL
199#endif
200
207#if defined(__has_include) && !defined(MGUTILITY_HAS_HAS_INCLUDE)
208#define MGUTILITY_HAS_HAS_INCLUDE
209#endif
210
211#endif // MGUTILITY_COMMON_DEFINITIONS_HPP
212/*
213MIT License
214
215Copyright (c) 2024 mguludag
216
217Permission is hereby granted, free of charge, to any person obtaining a copy
218of this software and associated documentation files (the "Software"), to deal
219in the Software without restriction, including without limitation the rights
220to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
221copies of the Software, and to permit persons to whom the Software is
222furnished to do so, subject to the following conditions:
223
224The above copyright notice and this permission notice shall be included in all
225copies or substantial portions of the Software.
226
227THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
228IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
229FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
230AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
231LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
232OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
233SOFTWARE.
234*/
235
236#ifndef MGUTILITY_DETAIL_UTILITY_HPP
237#define MGUTILITY_DETAIL_UTILITY_HPP
238
239#include <initializer_list>
240#include <type_traits>
241#include <utility>
242
243namespace mgutility {
244namespace detail {
245
251template <std::size_t... Ints> struct index_sequence {};
252
259template <typename Seq1, typename Seq2> struct index_sequence_concat;
260
261template <std::size_t... I1, std::size_t... I2>
263 using type = index_sequence<I1..., (sizeof...(I1) + I2)...>;
264};
265
271template <std::size_t N> struct make_index_sequence_impl;
272
273template <std::size_t N> struct make_index_sequence_impl {
274private:
275 static constexpr std::size_t half = N / 2;
276
277 using first = typename make_index_sequence_impl<half>::type;
278 using second = typename make_index_sequence_impl<N - half>::type;
279
280public:
281 using type = typename index_sequence_concat<first, second>::type;
282};
283
284// base cases
288template <> struct make_index_sequence_impl<0> {
289 using type = index_sequence<>;
290};
291
295template <> struct make_index_sequence_impl<1> {
296 using type = index_sequence<0>;
297};
298
304template <std::size_t N>
305using make_index_sequence = typename make_index_sequence_impl<N>::type;
306} // namespace detail
307
308} // namespace mgutility
309
310#endif // DETAIL_META_HPP
311#include <initializer_list>
312#include <type_traits>
313#include <utility>
314
315namespace mgutility {
316namespace detail {
317
318#ifndef MGUTILITY_ENUM_RANGE_MIN
324// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
325#define MGUTILITY_ENUM_RANGE_MIN 0
326#endif
327
328#ifndef MGUTILITY_ENUM_RANGE_MAX
334// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
335#define MGUTILITY_ENUM_RANGE_MAX 256
336#endif
337
343#ifndef MGUTILITY_ENUM_NAME_BUFFER_SIZE
344// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
345#define MGUTILITY_ENUM_NAME_BUFFER_SIZE 32U
346#endif
347
356#ifndef MGUTILITY_GLOBAL_ENUM_BLOB_SIZE
357// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
358#define MGUTILITY_GLOBAL_ENUM_BLOB_SIZE 8192
359#endif
360
361#ifndef MGUTILITY_INLINE
362#if MGUTILITY_CPLUSPLUS > 201402L
363#define MGUTILITY_INLINE inline
364#else
365#define MGUTILITY_INLINE
366#endif
367#endif
368
374template <typename E> struct is_scoped_enum {
378 static constexpr auto value =
379 // NOLINTNEXTLINE [modernize-type-traits]
380 std::is_enum<E>::value &&
381 // NOLINTNEXTLINE [modernize-type-traits]
382 !std::is_convertible<E, typename std::underlying_type<E>::type>::value;
383};
384
391template <typename T, typename = void> struct has_bit_or : std::false_type {};
392
399template <typename T>
400struct has_bit_or<T, decltype((T{} | T{}), void())> : std::true_type {};
401
402#if MGUTILITY_CPLUSPLUS > 201103L
408template <typename E>
409static constexpr bool is_scoped_enum_v = is_scoped_enum<E>::value;
410#endif
411
422template <bool B, class T = void>
423// NOLINTNEXTLINE [modernize-type-traits]
424using enable_if_t = typename std::enable_if<B, T>::type;
425
431template <typename T>
432// NOLINTNEXTLINE [modernize-type-traits]
433using underlying_type_t = typename std::underlying_type<T>::type;
434
440template <typename T>
441// NOLINTNEXTLINE [modernize-type-traits]
442using remove_const_t = typename std::remove_const<T>::type;
443
450template <typename Enum, Enum... Values> struct enum_sequence {};
451
459template <typename Enum, int Min, typename Seq> struct enum_sequence_from_index;
460
468template <typename Enum, int Min, std::size_t... I>
469struct enum_sequence_from_index<Enum, Min, index_sequence<I...>> {
470private:
471 // NOLINTNEXTLINE [readability-identifier-length]
472 static constexpr int offset(std::size_t i) {
473 return Min + static_cast<int>(i);
474 }
475
476public:
477 using type = enum_sequence<Enum, static_cast<Enum>(offset(I))...>;
478};
479
487template <typename Enum, int Min, int Max>
488using make_enum_sequence = typename enum_sequence_from_index<
489 Enum, Min,
490 make_index_sequence<static_cast<std::size_t>(Max - Min + 1)>>::type;
491} // namespace detail
492
498template <typename T> struct enum_range {
499 static constexpr auto min{MGUTILITY_ENUM_RANGE_MIN};
500 static constexpr auto max{MGUTILITY_ENUM_RANGE_MAX};
501};
502
503template <typename T, typename U> struct pair {
504 T first;
505 U second;
506};
507
508template <typename T>
509#if MGUTILITY_CPLUSPLUS >= 201402L || defined(__GNUC__) && !defined(__clang__)
510using flat_map = std::initializer_list<pair<T, const char *>>;
511#else
512// NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
513using flat_map = pair<T, const char *>[];
514#endif
515
521template <typename T> struct custom_enum {
522 // #if MGUTILITY_CPLUSPLUS > 201402L
523 static MGUTILITY_INLINE constexpr flat_map<T> map = {};
524 // #else
525 // static constexpr flat_map<T> map() noexcept {
526 // return {}; // default: empty map
527 // }
528 // #endif
529};
530
536template <typename T> struct enum_name_buffer {
537 static constexpr auto size = MGUTILITY_ENUM_NAME_BUFFER_SIZE;
538};
539
540} // namespace mgutility
541
542#endif // DETAIL_META_HPP
543/*
544MIT License
545
546Copyright (c) 2025 mguludag
547
548Permission is hereby granted, free of charge, to any person obtaining a copy
549of this software and associated documentation files (the "Software"), to deal
550in the Software without restriction, including without limitation the rights
551to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
552copies of the Software, and to permit persons to whom the Software is
553furnished to do so, subject to the following conditions:
554
555The above copyright notice and this permission notice shall be included in all
556copies or substantial portions of the Software.
557
558THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
559IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
560FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
561AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
562LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
563OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
564SOFTWARE.
565*/
566
567#ifndef MGUTILITY_FIXED_STRING_HPP
568#define MGUTILITY_FIXED_STRING_HPP
569
570/*
571MIT License
572
573Copyright (c) 2024 mguludag
574
575Permission is hereby granted, free of charge, to any person obtaining a copy
576of this software and associated documentation files (the "Software"), to deal
577in the Software without restriction, including without limitation the rights
578to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
579copies of the Software, and to permit persons to whom the Software is
580furnished to do so, subject to the following conditions:
581
582The above copyright notice and this permission notice shall be included in all
583copies or substantial portions of the Software.
584
585THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
586IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
587FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
588AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
589LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
590OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
591SOFTWARE.
592*/
593
594#ifndef MGUTILITY_STRING_VIEW_HPP
595#define MGUTILITY_STRING_VIEW_HPP
596
597#include <cstring>
598// NOLINTNEXTLINE [unused-includes]
599#include <iosfwd>
600#include <string>
601#include <utility>
602
603#if MGUTILITY_CPLUSPLUS > 201402L
604#include <string_view>
605#endif
606
607namespace mgutility {
608namespace detail {
609
617// NOLINTNEXTLINE [readability-identifier-length]
618constexpr auto strlen_constexpr(const char *str, size_t sz = 0) noexcept
619 -> size_t {
620 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
621 return str[sz] == '\0' ? sz : strlen_constexpr(str, ++sz);
622}
623
630constexpr auto is_digit(char character) noexcept -> bool {
631 return character >= '0' && character <= '9';
632}
633
643MGUTILITY_CNSTXPR int strncmp_constexpr(const char *lhs, const char *rhs,
644 size_t count) noexcept {
645 for (size_t i = 0; i < count; ++i) {
646 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
647 if (lhs[i] != rhs[i] || lhs[i] == '\0' || rhs[i] == '\0') {
648 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
649 return static_cast<unsigned char>(lhs[i]) -
650 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
651 static_cast<unsigned char>(rhs[i]);
652 }
653 }
654 return 0;
655}
656
657template <typename Range, typename Pred>
658MGUTILITY_CNSTXPR auto find(const Range &rng, const Pred &pred) -> size_t {
659 for (size_t i = 1; i < rng.size(); ++i) {
660 if (pred == rng[i]) {
661 return i;
662 }
663 }
664 return 0;
665};
666
667} // namespace detail
668
669#if MGUTILITY_CPLUSPLUS < 201703L
670
676// NOLINTNEXTLINE [cppcoreguidelines-special-member-functions]
677template <typename Char = char> class basic_string_view {
678public:
682 // NOLINTNEXTLINE [readability-redundant-inline-specifier]
683 constexpr inline basic_string_view() noexcept : data_(""), size_(0) {}
684
690 // NOLINTNEXTLINE [google-explicit-constructor]
691 constexpr inline basic_string_view(const Char *str) noexcept
692 : data_(str), size_(detail::strlen_constexpr(str)) {}
693
699 // NOLINTNEXTLINE [google-explicit-constructor]
700 constexpr basic_string_view(const std::basic_string<Char> &str) noexcept
701 : data_(str.c_str()), size_(str.size()) {}
702
709 constexpr basic_string_view(const Char *str, size_t len) noexcept
710 : data_(str), size_(len) {}
711
717 constexpr basic_string_view(const basic_string_view &other)
718 : data_(other.data_), size_(other.size_) {}
719
725 constexpr basic_string_view(basic_string_view &&other) noexcept
726 : data_(std::move(other.data_)), size_(other.size_) {}
727
734 MGUTILITY_CNSTXPR inline basic_string_view<Char> &
735 operator=(const basic_string_view &other) noexcept = default;
736
743 MGUTILITY_CNSTXPR inline basic_string_view<Char> &
744 operator=(basic_string_view &&other) noexcept {
745 data_ = std::move(other.data_);
746 size_ = other.size_;
747 return *this;
748 }
749
756 // NOLINTNEXTLINE [readability-const-return-type]
757 constexpr const Char operator[](size_t index) const noexcept {
758 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
759 return data_[index];
760 }
761
767 constexpr const Char *begin() const noexcept { return data_; }
768
774 constexpr const Char *end() const noexcept { return (data_ + size_); }
775
781 constexpr const Char &front() const noexcept { return data_[0]; }
782
788 constexpr const Char &back() const noexcept { return data_[size_ - 1]; }
789
795 constexpr bool empty() const noexcept { return size_ < 1; }
796
802 constexpr size_t size() const noexcept { return size_; }
803
809 constexpr const Char *data() const noexcept { return data_; }
810
819 size_t len = npos) const noexcept {
820 return basic_string_view<Char>(data_ + begin,
821 len == npos ? size_ - begin : len);
822 }
823
831 // NOLINTNEXTLINE [readability-identifier-length]
832 constexpr size_t rfind(Char c, size_t pos = npos) const noexcept {
833#if MGUTILITY_CPLUSPLUS < 201402L
834 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
835 return (pos == npos ? pos = size_ : pos = pos),
836 c == data_[pos] ? pos
837 // NOLINTNEXTLINE [readability-avoid-nested-conditional-operator]
838 : pos == 0U ? npos
839 : rfind(c, --pos);
840#else
841 for (size_t i = (pos == npos ? size_ : pos) - 1; i < size_; --i) {
842 if (data_[i] == c) {
843 return i;
844 }
845 }
846 return npos;
847#endif
848 }
849
857 // NOLINTNEXTLINE [readability-identifier-length]
858 constexpr size_t find(Char c, size_t pos = 0) const noexcept {
859#if MGUTILITY_CPLUSPLUS < 201402L
860 // NOLINTNEXTLINE [readability-avoid-nested-conditional-operator]
861 return c == data_[pos] ? pos : pos < size_ ? find(c, ++pos) : npos;
862#else
863 for (size_t i = pos; i < size_; ++i) {
864 if (data_[i] == c) {
865 return i;
866 }
867 }
868 return npos;
869#endif
870 }
871
879 MGUTILITY_CNSTXPR friend bool
881 basic_string_view<Char> rhs) noexcept {
882 return (lhs.size_ == rhs.size_) &&
883 detail::strncmp_constexpr(lhs.data_, rhs.data_, lhs.size_) == 0;
884 }
885
893 MGUTILITY_CNSTXPR friend bool operator==(basic_string_view<Char> lhs,
894 const Char *rhs) noexcept {
895 return ((lhs.size_ == detail::strlen_constexpr(rhs)) &&
896 (detail::strncmp_constexpr(lhs.data_, rhs, lhs.size_) == 0));
897 }
898
906 MGUTILITY_CNSTXPR friend bool
908 basic_string_view<Char> rhs) noexcept {
909 return !(lhs == rhs);
910 }
911
919 MGUTILITY_CNSTXPR friend bool operator!=(basic_string_view<Char> lhs,
920 const Char *rhs) noexcept {
921 return !(lhs == rhs);
922 }
923
929 // NOLINTNEXTLINE [google-explicit-constructor]
930 operator std::string() { return std::string(data_, size_); }
931
937 // NOLINTNEXTLINE [google-explicit-constructor]
938 operator std::string() const { return std::string(data_, size_); }
939
947 // NOLINTNEXTLINE [readability-identifier-length]
950 // NOLINTNEXTLINE [readability-identifier-length]
951 const basic_string_view<Char> &sv) {
952 // NOLINTNEXTLINE [readability-identifier-length]
953 for (auto c : sv) {
954 os << c;
955 }
956 return os;
957 }
958
959 static constexpr auto npos = -1;
960
961private:
962 size_t size_;
963 const Char *data_;
964};
965
966using string_view = basic_string_view<char>;
967
968#else
969
970using string_view = std::string_view;
971
972#endif
973
974} // namespace mgutility
975
976#endif // STRING_STRING_VIEW_HPP
977
978namespace mgutility {
979
980template <size_t N = 0> class fixed_string {
981 template <size_t> friend class fixed_string;
982
983public:
984 template <size_t M>
985 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
986 MGUTILITY_CNSTXPR static auto make(const char (&str)[M]) -> fixed_string<M> {
987 return fixed_string<M>{str};
988 }
989
990 MGUTILITY_CNSTXPR fixed_string() = default;
991
992 // --- safe pack expansion (no OOB) ---
993 template <std::size_t M, std::size_t... Is>
994 constexpr fixed_string(const char (&str)[M], detail::index_sequence<Is...>)
995 : data_{(Is < M ? str[Is] : '\0')...}, cursor_(M ? M - 1 : 0) {}
996
997 // single literal constructor (handles all M)
998 template <std::size_t M>
999 constexpr fixed_string(const char (&str)[M])
1000 : fixed_string(str, typename detail::make_index_sequence<N>{}) {}
1001
1002 MGUTILITY_CNSTXPR fixed_string(const char *str, std::size_t len)
1003 : data_{}, cursor_(len < N ? len
1004 : N ? N - 1
1005 : 0) {
1006 for (std::size_t i = 0; i < N; ++i) {
1007 data_[i] = (i < len) ? str[i] : '\0';
1008 }
1009 }
1010
1011 MGUTILITY_CNSTXPR fixed_string(mgutility::string_view str)
1012 : fixed_string(str.data(), str.size()) {}
1013
1014 // Constructor to initialize from a string literal
1015 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
1016 MGUTILITY_CNSTXPR explicit fixed_string(const char (&str)[N]) {
1017 for (size_t i = 0; i < N - 1; ++i) {
1018 data_[i] = str[i];
1019 }
1020 cursor_ = N - 1;
1021 data_[cursor_] = '\0';
1022 }
1023
1024 // Concatenation operator
1025 template <size_t M>
1026 MGUTILITY_CNSTXPR auto operator+(const fixed_string<M> &other) const
1027 -> fixed_string<N + M - 1> {
1028 fixed_string<N + M - 1> result{};
1029 size_t idx = 0;
1030 for (; idx < cursor_; ++idx) {
1031 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1032 result.data_[idx] = data_[idx];
1033 }
1034 for (size_t j = 0; j < other.size(); ++j) {
1035 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1036 result.data_[idx + j] = other.data_[j];
1037 }
1038 result.cursor_ = cursor_ + other.size();
1039 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1040 result.data_[result.cursor_] = '\0';
1041 return result;
1042 }
1043
1044 // Concatenation operator
1045 template <size_t M>
1046 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
1047 MGUTILITY_CNSTXPR auto operator+(const char (&str)[M]) const
1048 -> fixed_string<N + M - 1> {
1049 return *this + fixed_string<M>{str};
1050 }
1051
1052 template <size_t M>
1053 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
1054 MGUTILITY_CNSTXPR auto append(const char (&str)[M]) -> fixed_string<N> & {
1055 static_assert(N > M,
1056 "Capacity needs to be greater than string to be appended!");
1057 for (size_t i = 0; i < M - 1; ++i) {
1058 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1059 data_[cursor_++] = str[i];
1060 }
1061 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1062 data_[cursor_] = '\0';
1063 return *this;
1064 }
1065
1066 MGUTILITY_CNSTXPR auto append(string_view str) -> fixed_string<N> & {
1067 auto len = str.size() > N - cursor_ ? N - cursor_ : str.size();
1068 for (std::size_t i = 0; i < len; ++i) {
1069 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1070 data_[cursor_++] = str[i];
1071 }
1072 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1073 data_[cursor_] = '\0';
1074 return *this;
1075 }
1076
1077 MGUTILITY_CNSTXPR auto pop_back() -> void {
1078 if (cursor_ > 0) {
1079 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1080 data_[--cursor_] = '\0';
1081 }
1082 }
1083
1084 MGUTILITY_CNSTXPR auto size() const -> size_t { return cursor_; }
1085
1086 // NOLINTNEXTLINE [readability-identifier-length]
1087 constexpr size_t find(char c, size_t pos = 0) const noexcept {
1088 // NOLINTNEXTLINE [readability-avoid-nested-conditional-operator]
1089 return c == data_[pos] ? pos : (pos < cursor_ ? find(c, ++pos) : npos);
1090 }
1091
1092 // Conversion to std::string_view for easy printing
1093 // NOLINTNEXTLINE[google-explicit-constructor]
1094 MGUTILITY_CNSTXPR operator string_view() const {
1095 return string_view(data_, cursor_);
1096 }
1097
1098 MGUTILITY_CNSTXPR auto view() const -> string_view {
1099 return string_view(data_, cursor_);
1100 }
1101
1102 constexpr const char *data() const noexcept { return data_; }
1103
1104 constexpr bool empty() const noexcept { return cursor_ == 0; }
1105
1106 constexpr const char &operator[](size_t index) const noexcept {
1107 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1108 return data_[index];
1109 }
1110
1111 MGUTILITY_CNSTXPR inline bool operator==(const char *rhs) const {
1112 return view() == rhs;
1113 }
1114
1115 // NOLINTNEXTLINE [readability-identifier-length]
1116 friend std::ostream &operator<<(std::ostream &os,
1117 const fixed_string<N> &str) {
1118 for (size_t i = 0; i < str.cursor_; ++i) {
1119 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
1120 os << str.data_[i];
1121 }
1122 return os;
1123 }
1124
1125 static constexpr auto npos = -1;
1126
1127private:
1128 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
1129 char data_[N]{'\0'};
1130 size_t cursor_{};
1131};
1132
1133} // namespace mgutility
1134
1135#if defined(__cpp_lib_format)
1136
1137#include <format>
1138
1144template <size_t N>
1145struct std::formatter<mgutility::fixed_string<N>>
1146 : formatter<std::string_view> {
1147 auto constexpr format(const mgutility::fixed_string<N> &str,
1148 format_context &ctx) const {
1149 return formatter<std::string_view>::format(str.view().data(), ctx);
1150 }
1151};
1152
1153#endif
1154
1155#if defined(ENUM_NAME_USE_FMT) || \
1156 (defined(MGUTILITY_HAS_HAS_INCLUDE) && __has_include(<fmt/format.h>))
1157#include <fmt/format.h>
1158
1159template <size_t N>
1160struct fmt::formatter<mgutility::fixed_string<N>> : formatter<string_view> {
1161 auto format(const mgutility::fixed_string<N> &str, format_context &ctx) const
1162 -> appender {
1163 return formatter<string_view>::format(str.view().data(), ctx);
1164 }
1165};
1166#endif // MGUTILITY_USE_FMT || __has_include(<fmt/format.h>)
1167
1168#endif // MGUTILITY_FIXED_STRING_HPP
1169
1170// NOLINTNEXTLINE [unused-includes]
1171#include <cstdint>
1172#include <utility>
1173
1174namespace mgutility {
1175namespace detail {
1176
1186template <typename T>
1187// NOLINTNEXTLINE [modernize-type-traits]
1188using string_or_view_t = typename std::conditional<
1191
1198template <typename Enum>
1199using enum_pair = std::pair<Enum, detail::string_or_view_t<Enum>>;
1200} // namespace detail
1201
1207template <typename Enum> class enum_for_each {
1208 using value_type = const detail::enum_pair<Enum>;
1209 using size_type = std::size_t;
1210
1214 struct enum_iter {
1215 using const_iter_type = int;
1216 using iter_type = detail::remove_const_t<const_iter_type>;
1217 using iterator_category = std::forward_iterator_tag;
1218 using value_type = const detail::enum_pair<Enum>;
1219 using difference_type = std::ptrdiff_t;
1220 using pointer = value_type *;
1221 using reference = value_type &;
1222
1227 enum_iter() : m_pos{} {}
1228
1234 explicit enum_iter(iter_type value) : m_pos{value} {}
1235
1241 auto operator++() -> enum_iter & {
1242 ++m_pos;
1243 return *this;
1244 }
1245
1251 auto operator++(int) -> enum_iter {
1252 m_pos++;
1253 return *this;
1254 }
1255
1262 auto operator!=(const enum_iter &other) const -> bool {
1263 return m_pos != other.m_pos;
1264 }
1265
1272 auto operator==(const enum_iter &other) const -> bool {
1273 return m_pos == other.m_pos;
1274 }
1275
1281 auto operator*() const -> value_type;
1282
1283 private:
1284 iter_type m_pos;
1285 };
1286
1287public:
1291 enum_for_each() = default;
1292
1298 auto begin() -> enum_iter & { return m_begin; }
1299
1305 auto end() -> enum_iter & { return m_end; }
1306
1312 auto size() -> std::size_t {
1313 return static_cast<int>(enum_range<Enum>::max) -
1314 static_cast<int>(enum_range<Enum>::min) + 1;
1315 }
1316
1317private:
1318 enum_iter m_begin{
1319 static_cast<int>(enum_range<Enum>::min)};
1320 enum_iter m_end{static_cast<int>(enum_range<Enum>::max) +
1321 1};
1322};
1323} // namespace mgutility
1324
1325#endif // DETAIL_ENUM_FOR_EACH_HPP
1326/*
1327MIT License
1328
1329Copyright (c) 2024 mguludag
1330
1331Permission is hereby granted, free of charge, to any person obtaining a copy
1332of this software and associated documentation files (the "Software"), to deal
1333in the Software without restriction, including without limitation the rights
1334to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1335copies of the Software, and to permit persons to whom the Software is
1336furnished to do so, subject to the following conditions:
1337
1338The above copyright notice and this permission notice shall be included in all
1339copies or substantial portions of the Software.
1340
1341THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1342IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1343FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1344AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1345LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1346OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1347SOFTWARE.
1348*/
1349
1350#ifndef DETAIL_OPTIONAL_HPP
1351#define DETAIL_OPTIONAL_HPP
1352
1353// NOLINTNEXTLINE [unused-includes]
1354
1355// NOLINTNEXTLINE [unused-includes]
1356#include <exception>
1357
1358#if MGUTILITY_CPLUSPLUS >= 201703L
1359#include <optional>
1360#endif
1361
1362namespace mgutility {
1363
1364#if MGUTILITY_CPLUSPLUS < 201703L
1365
1369struct bad_optional_access : public std::exception {
1375 const char *what() const noexcept override { return "optional has no value"; }
1376};
1377
1378struct nullopt_t;
1379
1385template <typename T> class optional {
1386public:
1390 MGUTILITY_CNSTXPR inline explicit optional(nullopt_t & /*unused*/)
1391 : dummy_{0}, has_value_{false} {}
1392
1396 MGUTILITY_CNSTXPR inline optional() : dummy_{0}, has_value_{false} {}
1397
1404 template <typename... Args>
1405 MGUTILITY_CNSTXPR inline explicit optional(Args &&...args)
1406 : value_{T{std::forward<Args>(args)...}}, has_value_{true} {}
1407
1413 MGUTILITY_CNSTXPR inline explicit optional(T &&value)
1414 : value_{std::move(value)}, has_value_{true} {}
1415
1421 MGUTILITY_CNSTXPR inline optional(const optional &other)
1422 : value_{other.value_}, has_value_{other.has_value_} {}
1423
1429 MGUTILITY_CNSTXPR inline optional(optional &&other) noexcept
1430 : value_{other.value_}, has_value_{other.has_value_} {
1431 other.reset();
1432 }
1433
1437 ~optional() = default;
1438
1445 MGUTILITY_CNSTXPR inline optional &operator=(const optional &other) {
1446 value_ = other.value_;
1447 has_value_ = other.has_value_;
1448 return *this;
1449 }
1450
1457 MGUTILITY_CNSTXPR inline optional &operator=(optional &&other) noexcept {
1458 value_ = other.value_;
1459 has_value_ = other.has_value_;
1460 other.reset();
1461 return *this;
1462 }
1463
1469 MGUTILITY_CNSTXPR inline void swap(optional &other) noexcept {
1470 auto val = std::move(other.value_);
1471 other.value_ = std::move(value_);
1472 value_ = std::move(val);
1473
1474 auto hval = other.has_value_;
1475 other.has_value_ = has_value_;
1476 has_value_ = hval;
1477 }
1478
1484 MGUTILITY_CNSTXPR inline T &operator*() { return value_; }
1485
1491 MGUTILITY_CNSTXPR inline T &operator*() const { return value_; }
1492
1499 MGUTILITY_CNSTXPR inline T &value() {
1500 if (!has_value_) {
1501 throw bad_optional_access();
1502 }
1503 return value_;
1504 }
1505
1512 MGUTILITY_CNSTXPR inline T &value() const {
1513 if (!has_value_) {
1514 throw bad_optional_access();
1515 }
1516 return value_;
1517 }
1518
1525 MGUTILITY_CNSTXPR inline T value_or(T &&value) {
1526 return has_value_ ? value_ : std::move(value);
1527 }
1528
1536 MGUTILITY_CNSTXPR inline T value_or(T &&value) const {
1537 return has_value_ ? value_ : std::move(value);
1538 }
1539
1546 MGUTILITY_CNSTXPR inline T value_or(const T &value) {
1547 return has_value_ ? value_ : value;
1548 }
1549
1557 MGUTILITY_CNSTXPR inline T value_or(const T &value) const {
1558 return has_value_ ? value_ : value;
1559 }
1560
1566 MGUTILITY_CNSTXPR inline void emplace(T value) {
1567 value_ = std::move(value);
1568 has_value_ = true;
1569 }
1570
1577 template <typename... Args>
1578 MGUTILITY_CNSTXPR inline void emplace(Args &&...args) {
1579 value_ = std::move(T{std::forward<Args>(args)...});
1580 has_value_ = true;
1581 }
1582
1588 MGUTILITY_CNSTXPR inline bool has_value() const { return has_value_; }
1589
1593 template <typename U = T,
1594 detail::enable_if_t<!std::is_destructible<U>::value, bool> = true>
1595 MGUTILITY_CNSTXPR inline void reset() {
1596 value_ = T{};
1597 has_value_ = false;
1598 }
1599
1603 template <typename U = T,
1604 detail::enable_if_t<std::is_destructible<T>::value, bool> = true>
1605 MGUTILITY_CNSTXPR inline void reset() {
1606 value_.~T();
1607 has_value_ = false;
1608 }
1609
1615 MGUTILITY_CNSTXPR operator bool() { return has_value_; }
1616
1617private:
1618 union {
1619 T value_;
1620 char dummy_[sizeof(T)];
1621 };
1622 bool has_value_;
1623};
1624
1635 template <typename T> MGUTILITY_CNSTXPR operator optional<T>() {
1636 return optional<T>{};
1637 }
1638};
1639
1644
1645#else
1651template <typename T> using optional = std::optional<T>;
1652
1656inline constexpr auto nullopt{std::nullopt};
1657
1658#endif
1659} // namespace mgutility
1660
1661#endif // DETAIL_OPTIONAL_HPP
1662#include <algorithm>
1663#include <array>
1664#include <cstddef>
1665#include <cstring>
1666
1672#if defined(_MSC_VER) && _MSC_VER < 1910
1673#error "Requires MSVC 2017 or newer!"
1679#elif defined(__clang__) && __clang_major__ < 6
1680#error "Requires clang 6 or newer!"
1686#elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 9
1687#error "Requires gcc 9 or newer!"
1693#elif !defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
1694#error "Your compiler is not supported!"
1695#endif
1696
1702#ifdef _MSC_VER
1703#define __PRETTY_FUNCTION__ __FUNCSIG__
1704#endif
1705
1706// NOLINTNEXTLINE [modernize-concat-nested-namespaces]
1707namespace mgutility {
1708namespace detail {
1709
1710#ifndef MGUTILITY_STRLEN
1711// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
1712#define MGUTILITY_STRLEN(x) sizeof(x) - 1
1713#endif
1714
1728template <typename U, int Min, int Max> struct enum_name_parse_result {
1729 static constexpr auto size = std::size_t{Max - Min};
1730 fixed_string<MGUTILITY_GLOBAL_ENUM_BLOB_SIZE> strings;
1731 std::array<pair<std::size_t, std::size_t>, size> ranges;
1732};
1733
1734template <typename T, int Min, int Max>
1735using enum_name_array =
1736 std::array<mgutility::string_view, static_cast<std::size_t>(Max - Min)>;
1737
1742struct enum_type {
1743private:
1751 template <typename Enum, Enum... e>
1752 MGUTILITY_CNSTXPR static auto
1753 raw_name(detail::enum_sequence<Enum, e...> /*unused*/) noexcept
1755#if defined(__GNUC__) && !defined(__clang__) && MGUTILITY_CPLUSPLUS >= 201402L
1756#define PREFIX \
1757 MGUTILITY_STRLEN("static constexpr mgutility::string_view " \
1758 "mgutility::detail::enum_type::raw_name(mgutility::detail:" \
1759 ":enum_sequence<Enum, e ...>) [with Enum = ")
1760#elif defined(__clang__) || defined(__GNUC__)
1761#define PREFIX \
1762 MGUTILITY_STRLEN("static mgutility::string_view " \
1763 "mgutility::detail::enum_type::raw_name(mgutility::detail:" \
1764 ":enum_sequence<Enum, e ...>) [with Enum = ")
1765#elif defined(_MSC_VER)
1766#if MGUTILITY_CPLUSPLUS > 201402L
1767#define PREFIX \
1768 MGUTILITY_STRLEN( \
1769 "class std::basic_string_view<char,struct std::char_traits<char> > " \
1770 "__cdecl mgutility::detail::enum_type::raw_name")
1771#else
1772#define PREFIX \
1773 MGUTILITY_STRLEN("class mgutility::basic_string_view<char> __cdecl " \
1774 "mgutility::detail::enum_type::raw_name")
1775#endif
1776#else
1777#define PREFIX 0
1778#endif
1779
1780 return mgutility::string_view(__PRETTY_FUNCTION__ + PREFIX,
1781 MGUTILITY_STRLEN(__PRETTY_FUNCTION__) -
1782 PREFIX + 1);
1783 }
1784
1791 template <typename Enum, int Min, int Max>
1792 MGUTILITY_CNSTXPR static auto parse() noexcept
1793 -> enum_name_parse_result<detail::underlying_type_t<Enum>, Min, Max> {
1794 using U = detail::underlying_type_t<Enum>;
1795 using result_type = enum_name_parse_result<U, Min, Max>;
1796
1797 MGUTILITY_CNSTXPR auto str =
1798 raw_name<Enum>(detail::make_enum_sequence<Enum, Min, Max>{});
1799
1800#if defined(__clang__) || defined(__GNUC__)
1801#if defined(__clang__)
1802 auto end = str.rfind(']');
1803#elif defined(__GNUC__) && !defined(__clang__)
1804 auto end = str.rfind(';');
1805#endif
1806
1807 auto enum_names = str.substr(0, end);
1808
1809#elif defined(_MSC_VER)
1810 // MSVC: different format
1811 auto pos = str.find(',');
1812 if (pos == mgutility::string_view::npos)
1813 return {};
1814
1815 ++pos;
1816
1817 auto end = str.rfind('>');
1818 auto enum_names = str.substr(pos, end - pos);
1819
1820#else
1821 return {};
1822#endif
1823
1824 if (enum_names.empty()) {
1825 return {};
1826 }
1827
1828 result_type result{};
1829
1830 std::size_t idx = 0;
1831
1832 while (!enum_names.empty() && idx < result.ranges.size()) {
1833 auto pos = enum_names.find(',');
1834 if (pos != mgutility::string_view::npos) {
1835 auto token = enum_names.substr(0, pos);
1836
1837 // remove whitespace
1838 while (!token.empty() && token.front() == ' ') {
1839 token = token.substr(1);
1840 }
1841
1842 while (!token.empty() && token.back() == ' ') {
1843 token = token.substr(0, token.size() - 1);
1844 }
1845
1846 std::size_t begin = token.find('(');
1847 std::size_t end = token.rfind(')');
1848 if (begin != mgutility::string_view::npos ||
1849 end != mgutility::string_view::npos) {
1850 result.ranges[idx++] = {0, 0};
1851 enum_names = enum_names.substr(pos + 1);
1852 continue;
1853 }
1854
1855 std::size_t start = 0;
1856 if (token.find(':') != mgutility::string_view::npos) {
1857 start = token.find(':') + 2;
1858 token = token.substr(start);
1859 }
1860
1861 // Write into the fixed-size global buffer
1862 auto offset = result.strings.size();
1863 result.strings.append(token);
1864 result.ranges[idx++] = {offset, token.size()};
1865
1866 enum_names = enum_names.substr(pos + 1);
1867 continue;
1868 }
1869 enum_names = {};
1870 }
1871
1872 return result;
1873 }
1874
1875public:
1883 template <typename Enum, int Min, int Max>
1884 MGUTILITY_CNSTXPR static auto name() noexcept
1885 -> enum_name_parse_result<detail::underlying_type_t<Enum>, Min, Max> {
1886 return parse<Enum, Min, Max>();
1887 }
1888};
1889
1896template <typename Enum, int Min, int Max> struct enum_array_cache;
1897
1904template <typename Enum, int Min, int Max> struct enum_array_cache {
1905 using underlying = detail::underlying_type_t<Enum>;
1907
1908#if MGUTILITY_CPLUSPLUS > 201402L
1909
1910 static constexpr auto parse_result =
1911 enum_type::template name<Enum, Min, Max>();
1912
1913#else
1914 // C++11: lazy runtime array
1915 static parse_result_t &value() {
1916 static parse_result_t arr = enum_type::template name<Enum, Min, Max>();
1917
1918 return arr;
1919 }
1920#endif
1921
1922 static MGUTILITY_CNSTXPR auto
1923 apply_custom(const parse_result_t &result) noexcept
1924 -> enum_name_array<Enum, Min, Max> {
1925 enum_name_array<Enum, Min, Max> arr{};
1926
1927 for (std::size_t idx = 0; idx < result.ranges.size(); ++idx) {
1928 arr[idx] = result.strings.view().substr(result.ranges[idx].first,
1929 result.ranges[idx].second);
1930 }
1931
1932#if MGUTILITY_CPLUSPLUS >= 201402L
1933 constexpr auto map = mgutility::custom_enum<Enum>::map;
1934 for (const auto &pair : map) {
1935#else
1936 for (const auto &pair : mgutility::custom_enum<Enum>::map) {
1937#endif
1938 if (pair.first >= static_cast<Enum>(Min) &&
1939 pair.first < static_cast<Enum>(Max)) {
1940 arr[static_cast<std::size_t>(pair.first) - Min] = pair.second;
1941 }
1942 }
1943
1944 return arr;
1945 }
1946};
1947
1957template <typename Enum, int Min = mgutility::enum_range<Enum>::min,
1959MGUTILITY_CNSTXPR auto get_enum_array() noexcept
1960 -> enum_name_array<Enum, Min, Max> {
1961#if MGUTILITY_CPLUSPLUS > 201402L
1962 constexpr auto &cache = enum_array_cache<Enum, Min, Max>::parse_result;
1964#else
1967#endif
1968}
1969
1979template <typename Enum, int Min, int Max>
1980MGUTILITY_CNSTXPR inline auto to_enum_impl(mgutility::string_view str) noexcept
1982 MGUTILITY_CNSTXPR_CLANG_WA auto arr = get_enum_array<Enum, Min, Max>();
1983
1984 const auto index{detail::find(arr, str)};
1985 return index == 0 ? mgutility::nullopt
1986 : mgutility::optional<Enum>{static_cast<Enum>(index + Min)};
1987}
1988
1998template <typename Enum, int Min, int Max>
1999MGUTILITY_CNSTXPR auto to_enum_bitmask_impl(mgutility::string_view str) noexcept
2001
2002 // Check if the string contains a '|' character
2003 if (str.find('|') == mgutility::string_view::npos) {
2004 return to_enum_impl<Enum, Min, Max>(str);
2005 }
2006
2008 std::size_t index = 0;
2009
2010 for (std::size_t i = 0; i < str.size(); ++i) {
2011 if (str[i] == '|') {
2012 auto name = str.substr(index, i - index);
2013 auto maybe_enum = to_enum_impl<Enum, Min, Max>(name);
2014
2015 if (!name.empty() && maybe_enum) {
2016 result.emplace(result ? static_cast<Enum>(*result | *maybe_enum)
2017 : *maybe_enum);
2018 }
2019
2020 index = i + 1;
2021 }
2022 }
2023
2024 auto maybe_enum = to_enum_impl<Enum, Min, Max>(str.substr(index));
2025 if (result && maybe_enum) {
2026 result.emplace(static_cast<Enum>(*result | *maybe_enum));
2027 } else {
2028 result.reset();
2029 }
2030
2031 return result;
2032}
2033
2043template <typename Enum, int Min, int Max,
2044 detail::enable_if_t<!detail::has_bit_or<Enum>::value, bool> = true>
2045MGUTILITY_CNSTXPR auto enum_name_impl(Enum enumValue) noexcept
2047 MGUTILITY_CNSTXPR_CLANG_WA auto arr = get_enum_array<Enum, Min, Max>();
2048 const auto index{(Min < 0 ? -Min : Min) + static_cast<int>(enumValue)};
2049 if (index < Min || index > static_cast<int>(arr.size()) - 1) {
2050 return mgutility::string_view{};
2051 }
2052
2053 return arr[static_cast<size_t>(index)];
2054}
2055
2066// NOLINTNEXTLINE [modernize-use-constraints]
2067template <typename Enum, int Min, int Max,
2068 detail::enable_if_t<detail::has_bit_or<Enum>::value, bool> = true>
2069MGUTILITY_CNSTXPR_CLANG_WA auto enum_name_impl(Enum enumValue) noexcept
2071
2072 // Get the array of enum names
2073 MGUTILITY_CNSTXPR_CLANG_WA auto arr = get_enum_array<Enum, Min, Max>();
2074
2075 // Calculate the index in the array
2076 const auto index = (Min < 0 ? -Min : Min) + static_cast<int>(enumValue);
2077
2079
2080 if (index >= 0 && index < static_cast<int>(arr.size())) {
2081 bitmasked_name.append(arr[static_cast<size_t>(index)]);
2082 }
2083
2084 if (!bitmasked_name.empty()) {
2085 return bitmasked_name;
2086 }
2087
2088 for (auto i = 0; i < Max - Min; ++i) {
2089 if (i >= 0 && i < static_cast<int>(arr.size()) && arr[i].size() > 0 &&
2090 (enumValue & static_cast<Enum>(i)) == static_cast<Enum>(i)) {
2091 bitmasked_name.append(arr[i]).append("|");
2092 }
2093 }
2094
2095 // Remove the trailing '|' if present
2096 if (!bitmasked_name.empty()) {
2097 bitmasked_name.pop_back();
2098 }
2099
2100 return bitmasked_name;
2101}
2102} // namespace detail
2103} // namespace mgutility
2104
2105#endif // MGUTILITY_REFLECTION_DETAIL_ENUM_NAME_IMPL_HPP
2106namespace mgutility {
2107
2115template <typename Enum,
2116 // NOLINTNEXTLINE [modernize-type-traits]
2117 detail::enable_if_t<std::is_enum<Enum>::value, bool> = true>
2118constexpr auto to_underlying(Enum enumValue) noexcept
2119 -> detail::underlying_type_t<Enum> {
2120 // NOLINTNEXTLINE [modernize-type-traits]
2121 static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
2122 return static_cast<detail::underlying_type_t<Enum>>(enumValue);
2123}
2124
2134template <int Min, int Max, typename Enum>
2135MGUTILITY_CNSTXPR auto enum_name(Enum enumValue) noexcept
2136 -> detail::string_or_view_t<Enum> {
2137 static_assert(Min < Max, "Max must be greater than Min!");
2138 // NOLINTNEXTLINE [modernize-type-traits]
2139 static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
2140 return detail::enum_name_impl<Enum, Min, Max>(enumValue);
2141}
2142
2152template <typename Enum, int Min = static_cast<int>(enum_range<Enum>::min),
2153 int Max = static_cast<int>(enum_range<Enum>::max)>
2154MGUTILITY_CNSTXPR auto enum_name(Enum enumValue) noexcept
2155 -> detail::string_or_view_t<Enum> {
2156 static_assert(Min < Max, "Max must be greater than Min!");
2157 // NOLINTNEXTLINE [modernize-type-traits]
2158 static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
2159 return detail::enum_name_impl<Enum, Min, Max>(enumValue);
2160}
2161
2168template <typename Enum>
2169auto enum_for_each<Enum>::enum_iter::operator*() const -> value_type {
2170 auto value = static_cast<Enum>(m_pos);
2171 return detail::enum_pair<Enum>{value, enum_name(value)};
2172}
2173
2183template <typename Enum, int Min = static_cast<int>(enum_range<Enum>::min),
2184 int Max = static_cast<int>(enum_range<Enum>::max),
2185 detail::enable_if_t<!detail::has_bit_or<Enum>::value, bool> = true>
2186MGUTILITY_CNSTXPR auto to_enum(mgutility::string_view str) noexcept
2188 static_assert(Min < Max, "Max must be greater than Min!");
2189 // NOLINTNEXTLINE [modernize-type-traits]
2190 static_assert(std::is_enum<Enum>::value, "Type is not an Enum type!");
2191 return detail::to_enum_impl<Enum, Min, Max>(str);
2192}
2193
2203template <typename Enum, int Min = static_cast<int>(enum_range<Enum>::min),
2204 int Max = static_cast<int>(enum_range<Enum>::max),
2205 detail::enable_if_t<detail::has_bit_or<Enum>::value, bool> = true>
2206MGUTILITY_CNSTXPR auto to_enum(mgutility::string_view str) noexcept
2208 static_assert(Min < Max, "Max must be greater than Min!");
2209 // NOLINTNEXTLINE [modernize-type-traits]
2210 static_assert(std::is_enum<Enum>::value, "Type is not an Enum type!");
2211 return detail::to_enum_bitmask_impl<Enum, Min, Max>(str);
2212}
2213
2223template <typename Enum, int Min = static_cast<int>(enum_range<Enum>::min),
2224 int Max = static_cast<int>(enum_range<Enum>::max)>
2225MGUTILITY_CNSTXPR auto enum_cast(int value) noexcept
2227 static_assert(Min < Max, "Max must be greater than Min!");
2228 // NOLINTNEXTLINE [modernize-type-traits]
2229 static_assert(std::is_enum<Enum>::value, "Type is not an Enum type!");
2230 if (enum_name(static_cast<Enum>(value)).empty()) {
2231 return mgutility::nullopt;
2232 }
2233 return mgutility::optional<Enum>{static_cast<Enum>(value)};
2234}
2235
2236namespace operators {
2237template <typename Enum, mgutility::detail::enable_if_t<
2238 // NOLINTNEXTLINE [modernize-type-traits]
2239 std::is_enum<Enum>::value, bool> = true>
2240constexpr auto operator&(const Enum &lhs, const Enum &rhs) -> Enum {
2241 return static_cast<Enum>(mgutility::to_underlying(lhs) &
2243}
2244
2245template <typename Enum, mgutility::detail::enable_if_t<
2246 // NOLINTNEXTLINE [modernize-type-traits]
2247 std::is_enum<Enum>::value, bool> = true>
2248constexpr auto operator|(const Enum &lhs, const Enum &rhs) -> Enum {
2249 return static_cast<Enum>(mgutility::to_underlying(lhs) |
2251}
2252} // namespace operators
2253
2254} // namespace mgutility
2255
2264template <typename Enum, mgutility::detail::enable_if_t<
2265 // NOLINTNEXTLINE [modernize-type-traits]
2266 std::is_enum<Enum>::value, bool> = true>
2267auto operator<<(std::ostream &outStream, Enum enumVal) -> std::ostream & {
2268 // NOLINTNEXTLINE [modernize-type-traits]
2269 static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
2270 outStream << mgutility::enum_name(enumVal);
2271 return outStream;
2272}
2273
2274#if defined(__cpp_lib_format)
2275
2276#include <format>
2277
2283template <typename Enum>
2284 requires std::is_enum_v<Enum>
2285struct std::formatter<Enum> : formatter<std::string_view> {
2286 // NOLINTNEXTLINE [readability-identifier-length]
2287 auto constexpr format(Enum e, format_context &ctx) const {
2288 return formatter<std::string_view>::format(mgutility::enum_name(e), ctx);
2289 }
2290};
2291
2292#endif
2293
2294#if defined(ENUM_NAME_USE_FMT) || \
2295 (defined(MGUTILITY_HAS_HAS_INCLUDE) && __has_include(<fmt/format.h>))
2296#include <fmt/format.h>
2297
2298template <class Enum>
2299struct fmt::formatter<Enum, char,
2300 // NOLINTNEXTLINE [modernize-type-traits]
2301 mgutility::detail::enable_if_t<std::is_enum<Enum>::value>>
2302 : formatter<string_view> {
2303 // NOLINTNEXTLINE [readability-identifier-length]
2304 auto format(const Enum e, format_context &ctx) const -> appender {
2305 return formatter<string_view>::format(
2306 static_cast<mgutility::string_view>(mgutility::enum_name(e)).data(),
2307 ctx);
2308 }
2309};
2310#endif // MGUTILITY_USE_FMT || __has_include(<fmt/format.h>)
2311
2312#endif // MGUTILITY_ENUM_NAME_HPP
A basic string view class template.
Definition mgutility_enum_name.hpp:677
constexpr const Char & back() const noexcept
Returns a reference to the last character.
Definition mgutility_enum_name.hpp:788
constexpr basic_string_view(const Char *str) noexcept
Constructs a basic_string_view from a C-string.
Definition mgutility_enum_name.hpp:691
constexpr const Char * end() const noexcept
Returns an iterator to the end of the string.
Definition mgutility_enum_name.hpp:774
MGUTILITY_CNSTXPR basic_string_view< Char > & operator=(const basic_string_view &other) noexcept=default
Copy assignment operator.
constexpr basic_string_view(const basic_string_view &other)
Copy constructor.
Definition mgutility_enum_name.hpp:717
constexpr size_t size() const noexcept
Returns the size of the string.
Definition mgutility_enum_name.hpp:802
MGUTILITY_CNSTXPR friend bool operator==(basic_string_view< Char > lhs, const Char *rhs) noexcept
Equality operator.
Definition mgutility_enum_name.hpp:893
constexpr bool empty() const noexcept
Checks if the string is empty.
Definition mgutility_enum_name.hpp:795
friend std::ostream & operator<<(std::ostream &os, const basic_string_view< Char > &sv)
Stream insertion operator.
Definition mgutility_enum_name.hpp:949
constexpr basic_string_view(basic_string_view &&other) noexcept
Move constructor.
Definition mgutility_enum_name.hpp:725
constexpr basic_string_view< Char > substr(size_t begin, size_t len=npos) const noexcept
Returns a substring view.
Definition mgutility_enum_name.hpp:818
MGUTILITY_CNSTXPR friend bool operator!=(basic_string_view< Char > lhs, const Char *rhs) noexcept
Inequality operator.
Definition mgutility_enum_name.hpp:919
constexpr size_t find(Char c, size_t pos=0) const noexcept
Finds the first occurrence of a character.
Definition mgutility_enum_name.hpp:858
constexpr const Char & front() const noexcept
Returns a reference to the first character.
Definition mgutility_enum_name.hpp:781
constexpr const Char operator[](size_t index) const noexcept
Accesses the character at the given index.
Definition mgutility_enum_name.hpp:757
constexpr const Char * begin() const noexcept
Returns an iterator to the beginning of the string.
Definition mgutility_enum_name.hpp:767
constexpr basic_string_view() noexcept
Default constructor.
Definition mgutility_enum_name.hpp:683
constexpr size_t rfind(Char c, size_t pos=npos) const noexcept
Finds the last occurrence of a character.
Definition mgutility_enum_name.hpp:832
constexpr const Char * data() const noexcept
Returns a pointer to the underlying data.
Definition mgutility_enum_name.hpp:809
constexpr basic_string_view(const std::basic_string< Char > &str) noexcept
Constructs a basic_string_view from a std::string.
Definition mgutility_enum_name.hpp:700
constexpr basic_string_view(const Char *str, size_t len) noexcept
Constructs a basic_string_view from a C-string and length.
Definition mgutility_enum_name.hpp:709
MGUTILITY_CNSTXPR friend bool operator!=(basic_string_view< Char > lhs, basic_string_view< Char > rhs) noexcept
Inequality operator.
Definition mgutility_enum_name.hpp:907
MGUTILITY_CNSTXPR basic_string_view< Char > & operator=(basic_string_view &&other) noexcept
Move assignment operator.
Definition mgutility_enum_name.hpp:744
MGUTILITY_CNSTXPR friend bool operator==(basic_string_view< Char > lhs, basic_string_view< Char > rhs) noexcept
Equality operator.
Definition mgutility_enum_name.hpp:880
A class template for iterating over enum values.
Definition enum_for_each.hpp:68
auto size() -> std::size_t
Returns the size of the enum range.
Definition mgutility_enum_name.hpp:1312
auto begin() -> enum_iter &
Returns an iterator to the beginning of the enum range.
Definition enum_for_each.hpp:159
auto end() -> enum_iter &
Returns an iterator to the end of the enum range.
Definition mgutility_enum_name.hpp:1305
Definition mgutility_enum_name.hpp:980
A class template that provides optional (nullable) objects.
Definition mgutility_enum_name.hpp:1385
MGUTILITY_CNSTXPR T value_or(T &&value) const
Returns the stored value or a default value if empty (const version).
Definition mgutility_enum_name.hpp:1536
MGUTILITY_CNSTXPR void emplace(Args &&...args)
Constructs the value in-place with arguments.
Definition mgutility_enum_name.hpp:1578
MGUTILITY_CNSTXPR optional(Args &&...args)
Constructs an optional with a value.
Definition mgutility_enum_name.hpp:1405
MGUTILITY_CNSTXPR optional & operator=(const optional &other)
Copy assignment operator.
Definition mgutility_enum_name.hpp:1445
MGUTILITY_CNSTXPR optional & operator=(optional &&other) noexcept
Move assignment operator.
Definition mgutility_enum_name.hpp:1457
MGUTILITY_CNSTXPR optional(T &&value)
Constructs an optional with a value.
Definition mgutility_enum_name.hpp:1413
MGUTILITY_CNSTXPR bool has_value() const
Checks if the optional has a value.
Definition mgutility_enum_name.hpp:1588
MGUTILITY_CNSTXPR T & operator*() const
Dereferences the stored value (const version).
Definition mgutility_enum_name.hpp:1491
MGUTILITY_CNSTXPR void swap(optional &other) noexcept
Swaps the contents of this optional with another.
Definition mgutility_enum_name.hpp:1469
MGUTILITY_CNSTXPR optional()
Constructs an empty optional.
Definition mgutility_enum_name.hpp:1396
MGUTILITY_CNSTXPR T & operator*()
Dereferences the stored value.
Definition mgutility_enum_name.hpp:1484
MGUTILITY_CNSTXPR optional(const optional &other)
Copy constructor.
Definition mgutility_enum_name.hpp:1421
MGUTILITY_CNSTXPR void reset()
Resets the optional, making it empty.
Definition mgutility_enum_name.hpp:1595
MGUTILITY_CNSTXPR optional(optional &&other) noexcept
Move constructor.
Definition mgutility_enum_name.hpp:1429
~optional()=default
Destructor.
MGUTILITY_CNSTXPR optional(nullopt_t &)
Constructs an empty optional.
Definition mgutility_enum_name.hpp:1390
MGUTILITY_CNSTXPR void emplace(T value)
Constructs the value in-place.
Definition mgutility_enum_name.hpp:1566
MGUTILITY_CNSTXPR T & value() const
Accesses the stored value (const version).
Definition mgutility_enum_name.hpp:1512
MGUTILITY_CNSTXPR T & value()
Accesses the stored value.
Definition mgutility_enum_name.hpp:1499
MGUTILITY_CNSTXPR T value_or(T &&value)
Returns the stored value or a default value if empty.
Definition mgutility_enum_name.hpp:1525
MGUTILITY_CNSTXPR T value_or(const T &value) const
Returns the stored value or a default value if empty (const version).
Definition mgutility_enum_name.hpp:1557
MGUTILITY_CNSTXPR T value_or(const T &value)
Returns the stored value or a default value if empty.
Definition mgutility_enum_name.hpp:1546
Definition doctest.h:530
Checks for MSVC compiler version.
Definition enum_for_each.hpp:35
auto nullopt
A global instance of nullopt_t to represent null optional.
Definition mgutility_enum_name.hpp:1643
MGUTILITY_CNSTXPR auto to_enum(mgutility::string_view str) noexcept -> mgutility::optional< Enum >
Converts a string to an enum value.
Definition enum_name.hpp:110
MGUTILITY_CNSTXPR auto enum_cast(int value) noexcept -> mgutility::optional< Enum >
Casts an integer value to an enum value.
Definition enum_name.hpp:149
MGUTILITY_CNSTXPR auto enum_name(Enum enumValue) noexcept -> detail::string_or_view_t< Enum >
Gets the name of an enum value.
Definition enum_name.hpp:59
constexpr auto to_underlying(Enum enumValue) noexcept -> detail::underlying_type_t< Enum >
Converts an enum value to its underlying integer value.
Definition enum_name.hpp:42
Exception thrown when accessing an empty optional.
Definition mgutility_enum_name.hpp:1369
const char * what() const noexcept override
Returns the exception message.
Definition mgutility_enum_name.hpp:1375
Provides the custom names map for an enumeration type.
Definition meta.hpp:240
Caches an array of enum names for a given enum sequence.
Definition mgutility_enum_name.hpp:1904
Parse result for enum names.
Definition enum_name_impl.hpp:103
static MGUTILITY_CNSTXPR auto name() noexcept -> enum_name_parse_result< detail::underlying_type_t< Enum >, Min, Max >
Gets the name of the enum value, checking custom names first.
Definition mgutility_enum_name.hpp:1884
Concatenates two index sequences.
Definition mgutility_enum_name.hpp:259
Represents a compile-time sequence of indices.
Definition mgutility_enum_name.hpp:251
static constexpr auto value
Boolean value indicating if the type is a scoped enumeration.
Definition meta.hpp:97
Implementation helper for creating index sequences.
Definition mgutility_enum_name.hpp:273
Provides the range for an enumeration type.
Definition meta.hpp:217
Represents a null optional.
Definition mgutility_enum_name.hpp:1628
Definition meta.hpp:222