diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yt/misc/enum.h |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yt/misc/enum.h')
-rw-r--r-- | library/cpp/yt/misc/enum.h | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/library/cpp/yt/misc/enum.h b/library/cpp/yt/misc/enum.h new file mode 100644 index 00000000000..894364aa43b --- /dev/null +++ b/library/cpp/yt/misc/enum.h @@ -0,0 +1,243 @@ +#pragma once + +#include "preprocessor.h" + +#include <util/generic/strbuf.h> + +#include <stdexcept> +#include <type_traits> +#include <array> +#include <vector> + +#include <library/cpp/yt/exception/exception.h> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// +/* + * Smart enumerations augment C++ enum classes with a bunch of reflection + * capabilities accessible via TEnumTraits class specialization. + * + * Please refer to the unit test for an actual example of usage + * (unittests/enum_ut.cpp). + */ + +// Actual overload must be provided with defines DEFINE_ENUM_XXX (see below). +template <class T> +void GetEnumTraitsImpl(T); + +template < + class T, + bool = std::is_enum<T>::value && + !std::is_convertible<T, int>::value && + !std::is_same<void, decltype(GetEnumTraitsImpl(T()))>::value +> +struct TEnumTraits +{ + static constexpr bool IsEnum = false; + static constexpr bool IsBitEnum = false; + static constexpr bool IsStringSerializableEnum = false; +}; + +template <class T> +struct TEnumTraits<T, true> +{ + using TImpl = decltype(GetEnumTraitsImpl(T())); + using TType = T; + using TUnderlying = typename TImpl::TUnderlying; + + static constexpr bool IsEnum = true; + static constexpr bool IsBitEnum = TImpl::IsBitEnum; + static constexpr bool IsStringSerializableEnum = TImpl::IsStringSerializableEnum; + + static constexpr int DomainSize = TImpl::DomainSize; + + static TStringBuf GetTypeName(); + + static const TStringBuf* FindLiteralByValue(TType value); + static bool FindValueByLiteral(TStringBuf literal, TType* result); + + static const std::array<TStringBuf, DomainSize>& GetDomainNames(); + static const std::array<TType, DomainSize>& GetDomainValues(); + + static TType FromString(TStringBuf str); + static TString ToString(TType value); + + // For non-bit enums only. + static constexpr TType GetMinValue(); + static constexpr TType GetMaxValue(); + + // For bit enums only. + static std::vector<TType> Decompose(TType value); + + // LLVM SmallDenseMap interop. + // This should only be used for enums whose underlying type has big enough range + // (see getEmptyKey and getTombstoneKey functions). + struct TDenseMapInfo + { + static inline TType getEmptyKey() + { + return static_cast<TType>(-1); + } + + static inline TType getTombstoneKey() + { + return static_cast<TType>(-2); + } + + static unsigned getHashValue(const TType& key) + { + return static_cast<unsigned>(key) * 37U; + } + + static bool isEqual(const TType& lhs, const TType& rhs) + { + return lhs == rhs; + } + }; +}; + +//////////////////////////////////////////////////////////////////////////////// + +//! Defines a smart enumeration with a specific underlying type. +/*! + * \param name Enumeration name. + * \param seq Enumeration domain encoded as a <em>sequence</em>. + * \param underlyingType Underlying type. + */ +#define DEFINE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ + ENUM__CLASS(name, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(name, underlyingType, false, false, seq) \ + ENUM__MINMAX \ + ENUM__VALIDATE_UNIQUE(name) \ + ENUM__END_TRAITS(name) + +//! Defines a smart enumeration with a specific underlying type. +//! Duplicate enumeration values are allowed. +#define DEFINE_AMBIGUOUS_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ + ENUM__CLASS(name, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(name, underlyingType, false, false, seq) \ + ENUM__MINMAX \ + ENUM__END_TRAITS(name) + +//! Defines a smart enumeration with the default |int| underlying type. +#define DEFINE_ENUM(name, seq) \ + DEFINE_ENUM_WITH_UNDERLYING_TYPE(name, int, seq) + +//! Defines a smart enumeration with a specific underlying type. +/*! + * \param name Enumeration name. + * \param seq Enumeration domain encoded as a <em>sequence</em>. + * \param underlyingType Underlying type. + */ +#define DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ + ENUM__CLASS(name, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(name, underlyingType, true, false, seq) \ + ENUM__DECOMPOSE \ + ENUM__VALIDATE_UNIQUE(name) \ + ENUM__END_TRAITS(name) \ + ENUM__BITWISE_OPS(name) + +//! Defines a smart enumeration with a specific underlying type. +//! Duplicate enumeration values are allowed. +/*! + * \param name Enumeration name. + * \param seq Enumeration domain encoded as a <em>sequence</em>. + * \param underlyingType Underlying type. + */ +#define DEFINE_AMBIGUOUS_BIT_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ + ENUM__CLASS(name, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(name, underlyingType, true, false, seq) \ + ENUM__DECOMPOSE \ + ENUM__END_TRAITS(name) \ + ENUM__BITWISE_OPS(name) + +//! Defines a smart enumeration with the default |unsigned| underlying type. +/*! + * \param name Enumeration name. + * \param seq Enumeration domain encoded as a <em>sequence</em>. + */ +#define DEFINE_BIT_ENUM(name, seq) \ + DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(name, unsigned, seq) + +//! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute. +/*! + * \param name Enumeration name. + * \param seq Enumeration domain encoded as a <em>sequence</em>. + * \param underlyingType Underlying type. + */ +#define DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ + ENUM__CLASS(name, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(name, underlyingType, false, true, seq) \ + ENUM__MINMAX \ + ENUM__VALIDATE_UNIQUE(name) \ + ENUM__END_TRAITS(name) \ + +//! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute. +//! Duplicate enumeration values are allowed. +#define DEFINE_AMBIGUOUS_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ + ENUM__CLASS(name, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(name, underlyingType, false, true, seq) \ + ENUM__MINMAX \ + ENUM__END_TRAITS(name) + +//! Defines a smart enumeration with the default |int| underlying type and IsStringSerializable attribute. +#define DEFINE_STRING_SERIALIZABLE_ENUM(name, seq) \ + DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, int, seq) + +//////////////////////////////////////////////////////////////////////////////// + +//! A statically sized vector with elements of type |T| indexed by +//! the items of enumeration type |E|. +/*! + * Items are value-initialized on construction. + */ +template < + class E, + class T, + E Min = TEnumTraits<E>::GetMinValue(), + E Max = TEnumTraits<E>::GetMaxValue() +> +class TEnumIndexedVector +{ +public: + using TIndex = E; + using TValue = T; + + TEnumIndexedVector(); + TEnumIndexedVector(std::initializer_list<T> elements); + + T& operator[] (E index); + const T& operator[] (E index) const; + + // STL interop. + T* begin(); + const T* begin() const; + T* end(); + const T* end() const; + + static bool IsDomainValue(E value); + +private: + using TUnderlying = typename TEnumTraits<E>::TUnderlying; + static constexpr int N = static_cast<TUnderlying>(Max) - static_cast<TUnderlying>(Min) + 1; + std::array<T, N> Items_; +}; + +//////////////////////////////////////////////////////////////////////////////// + +//! Returns |true| iff the enumeration value is not bitwise zero. +template <typename E, typename = std::enable_if_t<NYT::TEnumTraits<E>::IsBitEnum, E>> +bool Any(E value); + +//! Returns |true| iff the enumeration value is bitwise zero. +template <typename E, typename = std::enable_if_t<NYT::TEnumTraits<E>::IsBitEnum, E>> +bool None(E value); + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT + +#define ENUM_INL_H_ +#include "enum-inl.h" +#undef ENUM_INL_H_ |