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