8#ifndef ARP_USE_ARP_SYSTEM_CORE
10#include "Arp/Base/Core/EnumFlagsDictionary.hxx"
15#include "Arp/System/Core/EnumDictionaryBase.hxx"
16#include "Arp/System/Core/TypeName.hxx"
28template<
class T,
char Delimiter = '|'>
29class EnumFlagsDictionary :
public EnumDictionaryBase<T>
32 using Base = EnumDictionaryBase<T>;
50 EnumFlagsDictionary(T flagsMask,
const char* invalidValueString,
const InitializerList& fields);
61 EnumFlagsDictionary(U flagsMask,
const char* invalidValueString,
const InitializerList& fields);
103 bool IsFlag(T value)
const;
104 bool TryGetCombinedEnumString(T value, String& result)
const;
105 bool TryParseCombinedEnumValue(
const String& input, T& value)
const;
106 bool TryFormatFlags(T value, String& result)
const;
109 T flagsMask =
static_cast<T
>(std::numeric_limits<U>::max());
110 T valueMask =
static_cast<T
>(0);
115template<
class T,
char Delimiter>
121template<
class T,
char Delimiter>
122EnumFlagsDictionary<T, Delimiter>::EnumFlagsDictionary(T flagsMask,
const InitializerList& fields)
124 , flagsMask(flagsMask)
125 , valueMask(~flagsMask)
129template<
class T,
char Delimiter>
130EnumFlagsDictionary<T, Delimiter>::EnumFlagsDictionary(T flagsMask,
const char* invalidValueString,
const InitializerList& fields)
131 : Base(invalidValueString, fields)
132 , flagsMask(flagsMask)
133 , valueMask(~flagsMask)
137template<
class T,
char Delimiter>
138EnumFlagsDictionary<T, Delimiter>::EnumFlagsDictionary(U flagsMask,
const InitializerList& fields)
140 , flagsMask(static_cast<T>(flagsMask))
141 , valueMask(static_cast<T>(~flagsMask))
145template<
class T,
char Delimiter>
146EnumFlagsDictionary<T, Delimiter>::EnumFlagsDictionary(U flagsMask,
const char* invalidValueString,
const InitializerList& fields)
147 : Base(invalidValueString, fields)
148 , flagsMask(static_cast<T>(flagsMask))
149 , valueMask(static_cast<T>(~flagsMask))
153template<
class T,
char Delimiter>
154std::ostream& EnumFlagsDictionary<T, Delimiter>::WriteEnumString(std::ostream& os, T value)
const
157 if (this->TryGetEnumString(value, enumString))
163 if (this->invalidValueString.IsEmpty())
165 os << String::Format(
"0x{:02X}",
static_cast<U
>(value));
169 os << this->invalidValueString;
171 os.setstate(std::ios::failbit);
176template<
class T,
char Delimiter>
177inline std::istream& EnumFlagsDictionary<T, Delimiter>::ReadEnumValue(std::istream& is, T& value)
const
181 if (!this->TryParseCombinedEnumValue(s, value))
183 is.setstate(std::ios::failbit);
188template<
class T,
char Delimiter>
189inline String EnumFlagsDictionary<T, Delimiter>::GetEnumString(T value)
const
192 if (!this->TryGetCombinedEnumString(value, result))
194 throw Exception(
"Could not find enum string of enum '{}' for value '{}'.", TypeName<T>(),
static_cast<U
>(value));
200template<
class T,
char Delimiter>
201bool EnumFlagsDictionary<T, Delimiter>::TryGetEnumString(T value, String& result)
const
203 return this->TryGetCombinedEnumString(value, result);
206template<
class T,
char Delimiter>
207T EnumFlagsDictionary<T, Delimiter>::GetEnumValue(
const String& fieldName)
const
210 if (!this->TryGetEnumValue(fieldName, result))
212 throw Exception(
"Could not find enum value of enum '{}' for string '{}'.", TypeName<T>(), fieldName);
217template<
class T,
char Delimiter>
218bool EnumFlagsDictionary<T, Delimiter>::TryGetEnumValue(
const String& fieldName, T& value)
const
220 return this->TryParseCombinedEnumValue(fieldName, value);
223template<
class T,
char Delimiter>
224inline bool EnumFlagsDictionary<T, Delimiter>::IsFlag(T value)
const
226 return (value & this->flagsMask) == value;
229template<
class T,
char Delimiter>
230inline bool EnumFlagsDictionary<T, Delimiter>::TryGetCombinedEnumString(T value, String& result)
const
232 const char* pResult =
nullptr;
233 if (Base::TryGetEnumStringInternal(value, pResult))
240 if (TryFormatFlags(value, result))
245 std::ostringstream oss;
246 oss <<
"0x" << std::uppercase << std::hex << static_cast<U>(value);
251template<
class T,
char Delimiter>
252inline bool EnumFlagsDictionary<T, Delimiter>::TryFormatFlags(T value, String& result)
const
254 std::ostringstream oss;
255 T resultValue = Base::zeroValue;
257 for (
const auto& item : this->fields)
259 if (item.first == Base::zeroValue)
263 if (IsFlag(item.first))
265 if ((value & item.first) == item.first)
267 if (oss.tellp() == std::streampos(0))
273 oss << Delimiter << item.second;
275 resultValue |= item.first;
280 if ((value & ~flagsMask) == item.first)
282 if (oss.tellp() == std::streampos(0))
288 oss << Delimiter << item.second;
290 resultValue |= item.first;
294 if (resultValue != value)
304template<
class T,
char Delimiter>
305inline bool EnumFlagsDictionary<T, Delimiter>::TryParseCombinedEnumValue(
const String& input, T& value)
const
307 static const char delimiters[] = {
'|',
',',
';', Delimiter };
308 static const size_t count =
sizeof(delimiters) /
sizeof(
char);
310 T result = Base::zeroValue;
311 String::Tokens tokens = input.Split(delimiters, count);
312 for (
const String& token : tokens)
314 T flag = Base::zeroValue;
315 if (!this->TryGetEnumValueInternal(token, flag))
std::initializer_list< typename Fields::value_type > InitializerList
The initializer list type of the Fields container.
Definition: EnumDictionaryBase.hxx:24
typename std::underlying_type< T >::type U
The underlying integral type of the enum.
Definition: EnumDictionaryBase.hxx:25
std::ostream & WriteEnumString(std::ostream &os, T value) const
Writes the string of the specified enum value to the given stream.
Definition: EnumFlagsDictionary.ipp:69
T GetEnumValue(const String &fieldName) const
Returns the value of the specified enum string.
Definition: EnumFlagsDictionary.ipp:137
bool TryGetEnumValue(const String &fieldName, T &value) const
Tries to get the enum value of the specified string.
Definition: EnumFlagsDictionary.ipp:152
String GetEnumString(T value) const
Returns the string of the specified enum entry.
Definition: EnumFlagsDictionary.ipp:111
EnumFlagsDictionary(const InitializerList &fields)
Constructor passing the enum fields as initializer list.
Definition: EnumFlagsDictionary.ipp:19
bool TryGetEnumString(T value, String &result) const
Returns the string of the specified enum value or nullptr if the value could not be found.
Definition: EnumFlagsDictionary.ipp:127
std::istream & ReadEnumValue(std::istream &is, T &value) const
Tries to return the enum entry of the specified string.
Definition: EnumFlagsDictionary.ipp:95
Root namespace for the PLCnext API