123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- #include "enum_runtime.h"
- #include <util/generic/algorithm.h>
- #include <util/generic/map.h>
- #include <util/generic/yexception.h>
- #include <util/stream/output.h>
- namespace NEnumSerializationRuntime {
- template <typename TEnumRepresentationType>
- [[noreturn]] static void ThrowUndefinedValueException(const TEnumRepresentationType key, const TStringBuf className) {
- throw yexception() << "Undefined value " << key << " in " << className << ". ";
- }
- template <typename TEnumRepresentationType>
- const TString& TEnumDescriptionBase<TEnumRepresentationType>::ToString(TRepresentationType key) const {
- const auto it = Names.find(key);
- if (Y_LIKELY(it != Names.end())) {
- return it->second;
- }
- ThrowUndefinedValueException(key, ClassName);
- }
- template <typename TEnumRepresentationType>
- std::pair<bool, TEnumRepresentationType> TEnumDescriptionBase<TEnumRepresentationType>::TryFromString(const TStringBuf name) const {
- const auto it = Values.find(name);
- if (it != Values.end()) {
- return {true, it->second};
- }
- return {false, TRepresentationType()};
- }
- template <class TContainer, class TNeedle, class TGetKey>
- static typename TContainer::value_type const* FindPtrInSortedContainer(const TContainer& vec, const TNeedle& needle, TGetKey&& getKey) {
- const auto it = LowerBoundBy(vec.begin(), vec.end(), needle, getKey);
- if (it == vec.end()) {
- return nullptr;
- }
- if (getKey(*it) != needle) {
- return nullptr;
- }
- return std::addressof(*it);
- }
- template <typename TEnumRepresentationType>
- std::pair<bool, TEnumRepresentationType> TEnumDescriptionBase<TEnumRepresentationType>::TryFromStringSorted(const TStringBuf name, const TInitializationData& enumInitData) {
- const auto& vec = enumInitData.ValuesInitializer;
- const auto* ptr = FindPtrInSortedContainer(vec, name, std::mem_fn(&TEnumStringPair::Name));
- if (ptr) {
- return {true, ptr->Key};
- }
- return {false, TRepresentationType()};
- }
- template <typename TEnumRepresentationType>
- std::pair<bool, TEnumRepresentationType> TEnumDescriptionBase<TEnumRepresentationType>::TryFromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData) {
- const auto& vec = enumInitData.ValuesInitializer;
- const auto* ptr = FindIfPtr(vec, [&](const auto& item) { return item.Name == name; });
- if (ptr) {
- return {true, ptr->Key};
- }
- return {false, TRepresentationType()};
- }
- [[noreturn]] static void ThrowUndefinedNameException(const TStringBuf name, const TStringBuf className, const TStringBuf allEnumNames) {
- ythrow yexception() << "Key '" << name << "' not found in enum " << className << ". Valid options are: " << allEnumNames << ". ";
- }
- template <typename TEnumRepresentationType>
- [[noreturn]] static void ThrowUndefinedNameException(const TStringBuf name, const typename TEnumDescriptionBase<TEnumRepresentationType>::TInitializationData& enumInitData) {
- auto exc = __LOCATION__ + yexception() << "Key '" << name << "' not found in enum " << enumInitData.ClassName << ". Valid options are: ";
- const auto& vec = enumInitData.NamesInitializer;
- for (size_t i = 0; i < vec.size(); ++i) {
- if (i != 0) {
- exc << ", ";
- }
- exc << '\'' << vec[i].Name << '\'';
- }
- exc << ". ";
- throw exc;
- }
- template <typename TEnumRepresentationType>
- auto TEnumDescriptionBase<TEnumRepresentationType>::FromString(const TStringBuf name) const -> TRepresentationType {
- const auto findResult = TryFromString(name);
- if (Y_LIKELY(findResult.first)) {
- return findResult.second;
- }
- ThrowUndefinedNameException(name, ClassName, AllEnumNames());
- }
- template <typename TEnumRepresentationType>
- TEnumRepresentationType TEnumDescriptionBase<TEnumRepresentationType>::FromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData) {
- const auto findResult = TryFromStringFullScan(name, enumInitData);
- if (Y_LIKELY(findResult.first)) {
- return findResult.second;
- }
- ThrowUndefinedNameException<TEnumRepresentationType>(name, enumInitData);
- }
- template <typename TEnumRepresentationType>
- TEnumRepresentationType TEnumDescriptionBase<TEnumRepresentationType>::FromStringSorted(const TStringBuf name, const TInitializationData& enumInitData) {
- const auto findResult = TryFromStringSorted(name, enumInitData);
- if (Y_LIKELY(findResult.first)) {
- return findResult.second;
- }
- ThrowUndefinedNameException<TEnumRepresentationType>(name, enumInitData);
- }
- template <typename TEnumRepresentationType>
- TStringBuf TEnumDescriptionBase<TEnumRepresentationType>::ToStringBuf(TRepresentationType key) const {
- return this->ToString(key);
- }
- template <typename TEnumRepresentationType>
- TStringBuf TEnumDescriptionBase<TEnumRepresentationType>::ToStringBufFullScan(const TRepresentationType key, const TInitializationData& enumInitData) {
- const auto& vec = enumInitData.NamesInitializer;
- const auto* ptr = FindIfPtr(vec, [&](const auto& item) { return item.Key == key; });
- if (Y_UNLIKELY(!ptr)) {
- ThrowUndefinedValueException(key, enumInitData.ClassName);
- }
- return ptr->Name;
- }
- template <typename TEnumRepresentationType>
- TStringBuf TEnumDescriptionBase<TEnumRepresentationType>::ToStringBufSorted(const TRepresentationType key, const TInitializationData& enumInitData) {
- const auto& vec = enumInitData.NamesInitializer;
- const auto* ptr = FindPtrInSortedContainer(vec, key, std::mem_fn(&TEnumStringPair::Key));
- if (Y_UNLIKELY(!ptr)) {
- ThrowUndefinedValueException(key, enumInitData.ClassName);
- }
- return ptr->Name;
- }
- template <typename TEnumRepresentationType>
- TStringBuf TEnumDescriptionBase<TEnumRepresentationType>::ToStringBufDirect(const TRepresentationType key, const TInitializationData& enumInitData) {
- const auto& vec = enumInitData.NamesInitializer;
- if (Y_UNLIKELY(vec.empty() || key < vec.front().Key)) {
- ThrowUndefinedValueException(key, enumInitData.ClassName);
- }
- const size_t index = static_cast<size_t>(key - vec.front().Key);
- if (Y_UNLIKELY(index >= vec.size())) {
- ThrowUndefinedValueException(key, enumInitData.ClassName);
- }
- return vec[index].Name;
- }
- template <typename TEnumRepresentationType>
- void TEnumDescriptionBase<TEnumRepresentationType>::Out(IOutputStream* os, const TRepresentationType key) const {
- (*os) << this->ToStringBuf(key);
- }
- template <typename TEnumRepresentationType>
- void TEnumDescriptionBase<TEnumRepresentationType>::OutFullScan(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData) {
- (*os) << ToStringBufFullScan(key, enumInitData);
- }
- template <typename TEnumRepresentationType>
- void TEnumDescriptionBase<TEnumRepresentationType>::OutSorted(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData) {
- (*os) << ToStringBufSorted(key, enumInitData);
- }
- template <typename TEnumRepresentationType>
- void TEnumDescriptionBase<TEnumRepresentationType>::OutDirect(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData) {
- (*os) << ToStringBufDirect(key, enumInitData);
- }
- template <typename TEnumRepresentationType>
- TEnumDescriptionBase<TEnumRepresentationType>::TEnumDescriptionBase(const TInitializationData& enumInitData)
- : ClassName(enumInitData.ClassName)
- {
- const TArrayRef<const TEnumStringPair>& namesInitializer = enumInitData.NamesInitializer;
- const TArrayRef<const TEnumStringPair>& valuesInitializer = enumInitData.ValuesInitializer;
- const TArrayRef<const TStringBuf>& cppNamesInitializer = enumInitData.CppNamesInitializer;
- TMap<TRepresentationType, TString> mapValueToName;
- TMap<TStringBuf, TRepresentationType> mapNameToValue;
- for (const TEnumStringPair& it : namesInitializer) {
- mapValueToName.emplace(it.Key, TString(it.Name));
- }
- for (const TEnumStringPair& it : valuesInitializer) {
- mapNameToValue.emplace(it.Name, it.Key);
- }
- Names = std::move(mapValueToName);
- Values = std::move(mapNameToValue);
- AllValues.reserve(Names.size());
- for (const auto& it : Names) {
- if (!AllNames.empty()) {
- AllNames += ", ";
- }
- AllNames += TString::Join('\'', it.second, '\'');
- AllValues.push_back(it.first);
- }
- AllCppNames.reserve(cppNamesInitializer.size());
- for (const auto& cn : cppNamesInitializer) {
- AllCppNames.push_back(TString::Join(enumInitData.CppNamesPrefix, cn));
- }
- }
- template <typename TEnumRepresentationType>
- TEnumDescriptionBase<TEnumRepresentationType>::~TEnumDescriptionBase() = default;
- // explicit instantiation
- template class TEnumDescriptionBase<int>;
- template class TEnumDescriptionBase<unsigned>;
- template class TEnumDescriptionBase<long long>;
- template class TEnumDescriptionBase<unsigned long long>;
- }
|