Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Enumeration.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4
5#include <wchar.h>
6
8
10
11 /*
12 ********************************************************************************
13 ******************************** Common::Inc ***********************************
14 ********************************************************************************
15 */
16 template <typename ENUM>
17 inline constexpr ENUM Inc (ENUM e)
18 {
19 return ToEnum<ENUM> (ToInt (e) + 1);
20 }
21
22 /*
23 ********************************************************************************
24 ****************************** Common::ToInt ***********************************
25 ********************************************************************************
26 */
27 template <typename ENUM>
28 inline constexpr underlying_type_t<ENUM> ToInt (ENUM e)
29 {
30 // http://stroika-bugs.sophists.com/browse/STK-549
31 //static_assert (ENUM::eSTART <= e and e <= ENUM::eEND);
32 return static_cast<typename underlying_type<ENUM>::type> (e);
33 }
34
35 /*
36 ********************************************************************************
37 ************************* Common::GetDistanceSpanned ***************************
38 ********************************************************************************
39 */
40 template <typename ENUM>
41 constexpr make_unsigned_t<underlying_type_t<ENUM>> GetDistanceSpanned ()
42 {
43 return static_cast<make_unsigned_t<underlying_type_t<ENUM>>> (ENUM::eCOUNT);
44 }
45
46 /*
47 ********************************************************************************
48 ******************************* Common::ToEnum *********************************
49 ********************************************************************************
50 */
51 template <typename ENUM>
52 inline constexpr ENUM ToEnum (underlying_type_t<ENUM> e)
53 {
54 // http://stroika-bugs.sophists.com/browse/STK-549
55 //static_assert (ENUM::eSTART <= static_cast<ENUM> (e) and static_cast<ENUM> (e) <= ENUM::eEND);
56 return static_cast<ENUM> (e);
57 }
58
59 /*
60 ********************************************************************************
61 *************************** Common::OffsetFromStart ****************************
62 ********************************************************************************
63 */
64 template <typename ENUM>
65 inline constexpr make_unsigned_t<underlying_type_t<ENUM>> OffsetFromStart (ENUM e)
66 {
67 DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
68 // http://stroika-bugs.sophists.com/browse/STK-549
69 //static_assert (ENUM::eSTART <= e and e <= ENUM::eEND);
70 return static_cast<make_unsigned_t<underlying_type_t<ENUM>>> (ToInt (e) - ToInt (ENUM::eSTART));
71 DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
72 }
73
74 /*
75 ********************************************************************************
76 ********************************* Common::EnumNames ****************************
77 ********************************************************************************
78 */
79 template <typename ENUM_TYPE>
80 inline EnumNames<ENUM_TYPE>::EnumNames (const initializer_list<EnumName<ENUM_TYPE>>& origEnumNames)
81#if 0
82 : fEnumNames_{origEnumNames}
83#endif
84 {
85#if 1
86 // @todo find some way to INITIALZIE the static array.... - needed for constexpr function!
87 // @see qCANNOT_FIGURE_OUT_HOW_TO_INIT_STD_ARRAY_FROM_STD_INITIALIZER_
88 //
89 // Tried fEnumNames_{origEnumNames} and tried template <typename... E> CTOR
90 auto oi = fEnumNames_.begin ();
91 for (EnumName<ENUM_TYPE> i : origEnumNames) {
92 Require (oi != fEnumNames_.end ());
93 *oi = i;
94 ++oi;
95 }
96#endif
97 RequireItemsOrderedByEnumValue_ ();
98 }
99 template <typename ENUM_TYPE>
100 constexpr EnumNames<ENUM_TYPE>::EnumNames (const typename EnumNames<ENUM_TYPE>::BasicArrayInitializer& init)
101 : fEnumNames_{init}
102 {
103 RequireItemsOrderedByEnumValue_ ();
104 }
105 template <typename ENUM_TYPE>
106 template <size_t N>
107 constexpr EnumNames<ENUM_TYPE>::EnumNames (const EnumName<ENUM_TYPE> origEnumNames[N])
108 : fEnumNames_{origEnumNames}
109 {
110 RequireItemsOrderedByEnumValue_ ();
111 }
112 template <typename ENUM_TYPE>
113 inline EnumNames<ENUM_TYPE>::operator initializer_list<EnumName<ENUM_TYPE>> () const
114 {
115 return fEnumNames_;
116 }
117 template <typename ENUM_TYPE>
118 inline typename EnumNames<ENUM_TYPE>::const_iterator EnumNames<ENUM_TYPE>::begin () const
119 {
120 return fEnumNames_.begin ();
121 }
122 template <typename ENUM_TYPE>
123 inline typename EnumNames<ENUM_TYPE>::const_iterator EnumNames<ENUM_TYPE>::end () const
124 {
125 return fEnumNames_.end ();
126 }
127 template <typename ENUM_TYPE>
128 constexpr size_t EnumNames<ENUM_TYPE>::size () const
129 {
130 return fEnumNames_.size ();
131 }
132 template <typename ENUM_TYPE>
133 constexpr const wchar_t* EnumNames<ENUM_TYPE>::PeekName (ENUM_TYPE e) const
134 {
135 if (e == ENUM_TYPE::eEND) {
136 return nullptr;
137 }
139 Require (OffsetFromStart<ENUM_TYPE> (e) < fEnumNames_.size ());
140 auto refImpl = [this] (ENUM_TYPE e) -> const wchar_t* {
141 for (const auto& i : fEnumNames_) {
142 if (i.first == e) {
143 return i.second;
144 }
145 }
146 return nullptr;
147 };
148 Ensure (refImpl (e) == fEnumNames_[OffsetFromStart<ENUM_TYPE> (e)].second);
149 }
150 return fEnumNames_[OffsetFromStart<ENUM_TYPE> (e)].second;
151 }
152 template <typename ENUM_TYPE>
153 inline const wchar_t* EnumNames<ENUM_TYPE>::GetName (ENUM_TYPE e) const
154 {
155 auto tmp = PeekName (e);
156 RequireNotNull (tmp);
157 return tmp;
158 }
159 template <typename ENUM_TYPE>
160 optional<ENUM_TYPE> EnumNames<ENUM_TYPE>::PeekValue (const wchar_t* name) const
161 {
162 /*
163 * NB: this is only safe returning an internal pointer, because the pointer is internal to
164 * static, immutable data - the basic_array associated with this EnumNames<> structure.
165 */
166 RequireNotNull (name);
167 for (const_iterator i = fEnumNames_.begin (); i != fEnumNames_.end (); ++i) {
168 if (::wcscmp (i->second, name) == 0) {
169 return i->first;
170 }
171 }
172 return nullopt;
173 }
174 template <typename ENUM_TYPE>
175 inline ENUM_TYPE EnumNames<ENUM_TYPE>::GetValue (const wchar_t* name) const
176 {
177 optional<ENUM_TYPE> tmp = PeekValue (name);
178 Require (tmp.has_value ());
179 return *tmp;
180 }
181 template <typename ENUM_TYPE>
182 template <typename NOT_FOUND_EXCEPTION>
183 inline ENUM_TYPE EnumNames<ENUM_TYPE>::GetValue (const wchar_t* name, const NOT_FOUND_EXCEPTION& notFoundException) const
184 {
185 RequireNotNull (name);
186 optional<ENUM_TYPE> tmp = PeekValue (name);
187 if (!tmp) [[unlikely]] {
188 //Execution::Throw (notFoundException);
189 throw (notFoundException);
190 }
191 return *tmp;
192 }
193 template <typename ENUM_TYPE>
194 constexpr void EnumNames<ENUM_TYPE>::RequireItemsOrderedByEnumValue_ () const
195 {
196 DISABLE_COMPILER_MSC_WARNING_START (4996); // hack for when deprecated enum is used in EnumNames...
197 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
198 DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
199 Require (static_cast<size_t> (ENUM_TYPE::eCOUNT) == fEnumNames_.size ());
200 using IndexType = make_unsigned_t<underlying_type_t<ENUM_TYPE>>;
201 if (not is_constant_evaluated ()) {
202 for (IndexType i = 0; i < static_cast<IndexType> (ENUM_TYPE::eCOUNT); ++i) {
203 Require (OffsetFromStart<ENUM_TYPE> (fEnumNames_[i].first) == i);
204 }
205 }
206 DISABLE_COMPILER_MSC_WARNING_END (4996);
207 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
208 DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
209 }
210
211 /*
212 ********************************************************************************
213 ****************************** Common::DefaultNames ****************************
214 ********************************************************************************
215 */
216 template <typename ENUM_TYPE>
217 constexpr DefaultNames<ENUM_TYPE>::DefaultNames ()
218 : EnumNames<ENUM_TYPE>{k}
219 {
220 }
221
222}
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Definition Assertions.h:48
#define RequireNotNull(p)
Definition Assertions.h:347
constexpr make_unsigned_t< underlying_type_t< ENUM > > OffsetFromStart(ENUM e)
offset of given enum from ENUM::eSTART
constexpr ENUM ToEnum(underlying_type_t< ENUM > e)
Cast the given int to the given ENUM type - (like static_cast<int>()) - but check range.
constexpr ENUM Inc(ENUM e)
Increment the given enumeration safely, without a bunch of casts.