diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-06-01 15:35:19 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-06-01 15:35:19 +0300 |
commit | 8e7094c87fa7ad049e6ea600a5f90f1c97d683bd (patch) | |
tree | d3e66d7ea5843080db0f65be0b7752538f69a84b /tools | |
parent | e13a5fc9fa49c7a6508a49f29e21a15fd9dac9ec (diff) | |
download | ydb-8e7094c87fa7ad049e6ea600a5f90f1c97d683bd.tar.gz |
intermediate changes
ref:b1e863e3aa12b888b40dd5ec36411ca050a25bd8
Diffstat (limited to 'tools')
8 files changed, 370 insertions, 56 deletions
diff --git a/tools/enum_parser/enum_parser/main.cpp b/tools/enum_parser/enum_parser/main.cpp index 0943c69c1d..1985f2d42f 100644 --- a/tools/enum_parser/enum_parser/main.cpp +++ b/tools/enum_parser/enum_parser/main.cpp @@ -11,6 +11,7 @@ #include <util/charset/wide.h> #include <util/string/builder.h> +#include <util/string/escape.h> #include <util/string/strip.h> #include <util/string/cast.h> #include <util/string/join.h> @@ -174,7 +175,7 @@ void GenerateEnum( out << "namespace { namespace " << nsName << " {\n"; TVector<TString> nameInitializerPairs; - TVector<TString> valueInitializerPairs; + TVector<std::pair<TString, TString>> valueInitializerPairsUnsorted; // data, sort_key TVector<TString> cppNamesInitializer; TStringStream jItems; @@ -197,18 +198,18 @@ void GenerateEnum( strValue = it.Aliases[0]; OutKey(jEnumItem, "str_value", strValue); } - nameInitializerPairs.push_back("TNameBufs::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(strValue) + ")"); + nameInitializerPairs.push_back("TNameBufsBase::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(strValue) + ")"); cppNamesInitializer.push_back(WrapStringBuf(it.CppName)); for (const auto& alias : it.Aliases) { - valueInitializerPairs.push_back("TNameBufs::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(alias) + ")"); + valueInitializerPairsUnsorted.emplace_back("TNameBufsBase::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(alias) + ")", UnescapeC(alias)); OutItem(jAliases, alias); } FinishItems(jAliases); CloseArray(jAliases); if (!it.Aliases) { - valueInitializerPairs.push_back("TNameBufs::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(it.CppName) + ")"); + valueInitializerPairsUnsorted.emplace_back("TNameBufsBase::EnumStringPair(" + outerScopeStr + it.CppName + ", " + WrapStringBuf(it.CppName) + ")", it.CppName); } OutKey(jEnumItem, "aliases", jAliases.Str(), false); @@ -221,6 +222,8 @@ void GenerateEnum( CloseArray(jItems); OutKey(jEnum, "items", jItems.Str(), false); + const TString nsNameBufsClass = nsName + "::TNameBufs"; + auto defineConstArray = [&out, payloadCache = TMap<std::pair<TString, TVector<TString>>, TString>()](const TStringBuf indent, const TStringBuf elementType, const TStringBuf name, const TVector<TString>& items) mutable { if (items.empty()) { // ISO C++ forbids zero-size array out << indent << "static constexpr const TArrayRef<const " << elementType << "> " << name << ";\n"; @@ -240,23 +243,21 @@ void GenerateEnum( out << "\n"; }; - out << " class TNameBufs : public ::NEnumSerializationRuntime::TEnumDescription<" << name << "> {\n"; - out << " public:\n"; - out << " using TBase = ::NEnumSerializationRuntime::TEnumDescription<" << name << ">;\n\n"; - out << " inline TNameBufs();\n\n"; - - // Instance - out << " static inline const TNameBufs& Instance() {\n"; - out << " return *SingletonWithPriority<TNameBufs, 0>();\n"; // destroy enum serializers last, because it may be used from destructor of another global object - out << " }\n"; - out << " };\n\n"; + out << " using TNameBufsBase = ::NEnumSerializationRuntime::TEnumDescription<" << name << ">;\n\n"; // Initialization data - defineConstArray(" ", "TNameBufs::TBase::TEnumStringPair", "NAMES_INITIALIZATION_PAIRS", nameInitializerPairs); - defineConstArray(" ", "TNameBufs::TBase::TEnumStringPair", "VALUES_INITIALIZATION_PAIRS", valueInitializerPairs); + defineConstArray(" ", "TNameBufsBase::TEnumStringPair", "NAMES_INITIALIZATION_PAIRS", nameInitializerPairs); + { + StableSortBy(valueInitializerPairsUnsorted, [](const auto& pair) -> const TString& { return pair.second; }); + TVector<TString> valueInitializerPairs(Reserve(valueInitializerPairsUnsorted.size())); + for (auto& [value, _] : valueInitializerPairsUnsorted) { + valueInitializerPairs.push_back(std::move(value)); + } + defineConstArray(" ", "TNameBufsBase::TEnumStringPair", "VALUES_INITIALIZATION_PAIRS", valueInitializerPairs); + } defineConstArray(" ", "TStringBuf", "CPP_NAMES_INITIALIZATION_ARRAY", cppNamesInitializer); - out << " static constexpr const TNameBufs::TInitializationData ENUM_INITIALIZATION_DATA{\n"; + out << " static constexpr const TNameBufsBase::TInitializationData ENUM_INITIALIZATION_DATA{\n"; out << " NAMES_INITIALIZATION_PAIRS,\n"; out << " VALUES_INITIALIZATION_PAIRS,\n"; out << " CPP_NAMES_INITIALIZATION_ARRAY,\n"; @@ -264,9 +265,31 @@ void GenerateEnum( out << " " << WrapStringBuf(name) << "\n"; out << " };\n\n"; + // Properties + out << " static constexpr ::NEnumSerializationRuntime::ESortOrder NAMES_ORDER = ::NEnumSerializationRuntime::GetKeyFieldSortOrder(NAMES_INITIALIZATION_PAIRS);\n"; + out << " static constexpr ::NEnumSerializationRuntime::ESortOrder VALUES_ORDER = ::NEnumSerializationRuntime::GetNameFieldSortOrder(VALUES_INITIALIZATION_PAIRS);\n"; + out << "\n"; + + // Data holder + out << " class TNameBufs : public ::NEnumSerializationRuntime::TEnumDescription<" << name << "> {\n"; + out << " public:\n"; + out << " using TBase = ::NEnumSerializationRuntime::TEnumDescription<" << name << ">;\n\n"; + out << " inline TNameBufs();\n\n"; + + // Reference initialization data from class + out << " static constexpr const TNameBufsBase::TInitializationData& EnumInitializationData = ENUM_INITIALIZATION_DATA;\n"; + out << " static constexpr ::NEnumSerializationRuntime::ESortOrder NamesOrder = NAMES_ORDER;\n"; + out << " static constexpr ::NEnumSerializationRuntime::ESortOrder ValuesOrder = VALUES_ORDER;\n\n"; + + // Instance + out << " static inline const TNameBufs& Instance() {\n"; + out << " return *SingletonWithPriority<TNameBufs, 0>();\n"; // destroy enum serializers last, because it may be used from destructor of another global object + out << " }\n"; + out << " };\n\n"; + // Constructor out << " inline TNameBufs::TNameBufs()\n"; - out << " : TBase(ENUM_INITIALIZATION_DATA)\n"; + out << " : TBase(TNameBufs::EnumInitializationData)\n"; out << " {\n"; out << " }\n\n"; @@ -281,17 +304,28 @@ void GenerateEnum( (*headerOutPtr) << "const TString& ToString(" << name << ");\n"; } out << "const TString& ToString(" << name << " x) {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; + out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n"; out << " return names.ToString(x);\n"; out << "}\n\n"; + // specialization for internal FromStringImpl + out << "template<>\n"; + out << name << " FromStringImpl<" << name << ">(const char* data, size_t len) {\n"; + out << " return ::NEnumSerializationRuntime::DispatchFromStringImplFn<" << nsNameBufsClass << ", " << name << ">(data, len);\n"; + out << "}\n\n"; + + // specialization for internal TryFromStringImpl + out << "template<>\n"; + out << "bool TryFromStringImpl<" << name << ">(const char* data, size_t len, " << name << "& result) {\n"; + out << " return ::NEnumSerializationRuntime::DispatchTryFromStringImplFn<" << nsNameBufsClass << ", " << name << ">(data, len, result);\n"; + out << "}\n\n"; + // outer FromString if (headerOutPtr) { (*headerOutPtr) << "bool FromString(const TString& name, " << name << "& ret);\n"; } out << "bool FromString(const TString& name, " << name << "& ret) {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; - out << " return names.FromString(name, ret);\n"; + out << " return ::TryFromStringImpl<" << name << ">(name.data(), name.size(), ret);\n"; out << "}\n\n"; // outer FromString @@ -299,28 +333,13 @@ void GenerateEnum( (*headerOutPtr) << "bool FromString(const TStringBuf& name, " << name << "& ret);\n"; } out << "bool FromString(const TStringBuf& name, " << name << "& ret) {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; - out << " return names.FromString(name, ret);\n"; - out << "}\n\n"; - - // specialization for internal FromStringImpl - out << "template<>\n"; - out << name << " FromStringImpl<" << name << ">(const char* data, size_t len) {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; - out << " return names.FromString(TStringBuf(data, len));\n"; - out << "}\n\n"; - - // specialization for internal TryFromStringImpl - out << "template<>\n"; - out << "bool TryFromStringImpl<" << name << ">(const char* data, size_t len, " << name << "& result) {\n"; - out << " return FromString(TStringBuf(data, len), result);\n"; + out << " return ::TryFromStringImpl<" << name << ">(name.data(), name.size(), ret);\n"; out << "}\n\n"; // outer Out out << "template<>\n"; out << "void Out<" << name << ">(IOutputStream& os, TTypeTraits<" << name << ">::TFuncParam n) {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; - out << " return names.Out(&os, n);\n"; + out << " return ::NEnumSerializationRuntime::DispatchOutFn<" << nsNameBufsClass << ">(os, n);\n"; out << "}\n\n"; // specializations for NEnumSerializationRuntime function family @@ -328,28 +347,28 @@ void GenerateEnum( // template<> GetEnumAllValues out << " template<>\n"; out << " TMappedArrayView<" << name <<"> GetEnumAllValuesImpl<" << name << ">() {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; + out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n"; out << " return names.AllEnumValues();\n"; out << " }\n\n"; // template<> GetEnumAllNames out << " template<>\n"; out << " const TString& GetEnumAllNamesImpl<" << name << ">() {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; + out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n"; out << " return names.AllEnumNames();\n"; out << " }\n\n"; // template<> GetEnumNames<EnumType> out << " template<>\n"; out << " TMappedDictView<" << name << ", TString> GetEnumNamesImpl<" << name << ">() {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; + out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n"; out << " return names.EnumNames();\n"; out << " }\n\n"; // template<> GetEnumAllCppNames, see IGNIETFERRO-534 out << " template<>\n"; out << " const TVector<TString>& GetEnumAllCppNamesImpl<" << name << ">() {\n"; - out << " const " << nsName << "::TNameBufs& names = " << nsName << "::TNameBufs::Instance();\n"; + out << " const " << nsNameBufsClass << "& names = " << nsNameBufsClass << "::Instance();\n"; out << " return names.AllEnumCppNames();\n"; out << " }\n"; diff --git a/tools/enum_parser/enum_serialization_runtime/CMakeLists.txt b/tools/enum_parser/enum_serialization_runtime/CMakeLists.txt index 0da66ac23f..4a351266c6 100644 --- a/tools/enum_parser/enum_serialization_runtime/CMakeLists.txt +++ b/tools/enum_parser/enum_serialization_runtime/CMakeLists.txt @@ -13,5 +13,7 @@ target_link_libraries(tools-enum_parser-enum_serialization_runtime PUBLIC yutil ) target_sources(tools-enum_parser-enum_serialization_runtime PRIVATE + ${CMAKE_SOURCE_DIR}/tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp ${CMAKE_SOURCE_DIR}/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp + ${CMAKE_SOURCE_DIR}/tools/enum_parser/enum_serialization_runtime/ordered_pairs.cpp ) diff --git a/tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp b/tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp new file mode 100644 index 0000000000..cda48368bf --- /dev/null +++ b/tools/enum_parser/enum_serialization_runtime/dispatch_methods.cpp @@ -0,0 +1 @@ +#include "dispatch_methods.h" diff --git a/tools/enum_parser/enum_serialization_runtime/dispatch_methods.h b/tools/enum_parser/enum_serialization_runtime/dispatch_methods.h new file mode 100644 index 0000000000..db752ae710 --- /dev/null +++ b/tools/enum_parser/enum_serialization_runtime/dispatch_methods.h @@ -0,0 +1,57 @@ +#pragma once + +#include "ordered_pairs.h" + +#include <util/generic/strbuf.h> +#include <util/stream/fwd.h> + +namespace NEnumSerializationRuntime { + // compile-time conversion method selection + + constexpr size_t LINEAR_SEARCH_KEYS_SIZE_THRESHOLD = 6; + constexpr size_t LINEAR_SEARCH_VALUES_SIZE_THRESHOLD = 2; + + template <class TNameBufs, typename EEnum> + inline void DispatchOutFn(IOutputStream& os, EEnum n) { + constexpr auto order = TNameBufs::NamesOrder; + if constexpr (order >= ::NEnumSerializationRuntime::ESortOrder::DirectMapping) { + return TNameBufs::OutDirect(&os, n, TNameBufs::EnumInitializationData); + } else if constexpr (std::size(TNameBufs::EnumInitializationData.NamesInitializer) <= LINEAR_SEARCH_KEYS_SIZE_THRESHOLD) { + return TNameBufs::OutFullScan(&os, n, TNameBufs::EnumInitializationData); + } else if constexpr (order >= ::NEnumSerializationRuntime::ESortOrder::Ascending) { + return TNameBufs::OutSorted(&os, n, TNameBufs::EnumInitializationData); + } else { + const TNameBufs& names = TNameBufs::Instance(); + return names.Out(&os, n); + } + } + + template <class TNameBufs, typename EEnum> + inline EEnum DispatchFromStringImplFn(const char* data, size_t len) { + const TStringBuf name{data, len}; + constexpr auto order = TNameBufs::ValuesOrder; + static_assert(order >= ::NEnumSerializationRuntime::ESortOrder::Ascending, "enum_parser produced unsorted output"); // comment this line to use run-time sort for temporary workaround + if constexpr (std::size(TNameBufs::EnumInitializationData.ValuesInitializer) <= LINEAR_SEARCH_VALUES_SIZE_THRESHOLD) { + return TNameBufs::FromStringFullScan(name, TNameBufs::EnumInitializationData); + } else if constexpr (order >= ::NEnumSerializationRuntime::ESortOrder::Ascending) { + return TNameBufs::FromStringSorted(name, TNameBufs::EnumInitializationData); + } else { + const TNameBufs& names = TNameBufs::Instance(); + return names.FromString(name); + } + } + + template <class TNameBufs, typename EEnum> + inline bool DispatchTryFromStringImplFn(const char* data, size_t len, EEnum& result) { + const TStringBuf name{data, len}; + constexpr auto order = TNameBufs::ValuesOrder; + if constexpr (std::size(TNameBufs::EnumInitializationData.ValuesInitializer) <= LINEAR_SEARCH_VALUES_SIZE_THRESHOLD) { + return TNameBufs::TryFromStringFullScan(name, result, TNameBufs::EnumInitializationData); + } else if constexpr (order >= ::NEnumSerializationRuntime::ESortOrder::Ascending) { + return TNameBufs::TryFromStringSorted(name, result, TNameBufs::EnumInitializationData); + } else { + const TNameBufs& names = TNameBufs::Instance(); + return names.FromString(name, result); + } + } +} diff --git a/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp b/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp index 2e7cc7f826..465f46b3e0 100644 --- a/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp +++ b/tools/enum_parser/enum_serialization_runtime/enum_runtime.cpp @@ -1,5 +1,6 @@ #include "enum_runtime.h" +#include <util/generic/algorithm.h> #include <util/generic/map.h> #include <util/generic/yexception.h> #include <util/stream/output.h> @@ -28,11 +29,57 @@ namespace NEnumSerializationRuntime { 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)) { @@ -42,8 +89,79 @@ namespace NEnumSerializationRuntime { } 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->ToString(key); + (*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> diff --git a/tools/enum_parser/enum_serialization_runtime/enum_runtime.h b/tools/enum_parser/enum_serialization_runtime/enum_runtime.h index 83c7a49b0a..cac142608d 100644 --- a/tools/enum_parser/enum_serialization_runtime/enum_runtime.h +++ b/tools/enum_parser/enum_serialization_runtime/enum_runtime.h @@ -1,26 +1,24 @@ #pragma once +#include "dispatch_methods.h" +#include "ordered_pairs.h" + #include <util/generic/array_ref.h> #include <util/generic/strbuf.h> #include <util/generic/string.h> #include <util/generic/vector.h> #include <util/generic/serialized_enum.h> +#include <util/stream/fwd.h> #include <utility> -class IOutputStream; - namespace NEnumSerializationRuntime { /// Stores all information about enumeration except its real type template <typename TEnumRepresentationType> class TEnumDescriptionBase { public: using TRepresentationType = TEnumRepresentationType; - - struct TEnumStringPair { - const TRepresentationType Key; - const TStringBuf Name; - }; + using TEnumStringPair = ::NEnumSerializationRuntime::TEnumStringPair<TRepresentationType>; /// Refers initialization data stored in constexpr-friendly format struct TInitializationData { @@ -36,9 +34,24 @@ namespace NEnumSerializationRuntime { ~TEnumDescriptionBase(); const TString& ToString(TRepresentationType key) const; + + TStringBuf ToStringBuf(TRepresentationType key) const; + static TStringBuf ToStringBufFullScan(const TRepresentationType key, const TInitializationData& enumInitData); + static TStringBuf ToStringBufSorted(const TRepresentationType key, const TInitializationData& enumInitData); + static TStringBuf ToStringBufDirect(const TRepresentationType key, const TInitializationData& enumInitData); + std::pair<bool, TRepresentationType> TryFromString(const TStringBuf name) const; + static std::pair<bool, TRepresentationType> TryFromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData); + static std::pair<bool, TRepresentationType> TryFromStringSorted(const TStringBuf name, const TInitializationData& enumInitData); + TRepresentationType FromString(const TStringBuf name) const; + static TRepresentationType FromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData); + static TRepresentationType FromStringSorted(const TStringBuf name, const TInitializationData& enumInitData); + void Out(IOutputStream* os, const TRepresentationType key) const; + static void OutFullScan(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData); + static void OutSorted(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData); + static void OutDirect(IOutputStream* os, const TRepresentationType key, const TInitializationData& enumInitData); const TString& AllEnumNames() const noexcept { return AllNames; @@ -77,6 +90,15 @@ namespace NEnumSerializationRuntime { using typename TBase::TRepresentationType; using typename TBase::TInitializationData; + private: + static bool MapFindResult(std::pair<bool, TEnumRepresentationType> findResult, EEnum& ret) { + if (findResult.first) { + ret = TCast::CastFromRepresentationType(findResult.second); + return true; + } + return false; + } + public: using TBase::TBase; @@ -85,18 +107,29 @@ namespace NEnumSerializationRuntime { } bool FromString(const TStringBuf name, EEnum& ret) const { - const auto findResult = TBase::TryFromString(name); - if (findResult.first) { - ret = TCast::CastFromRepresentationType(findResult.second); - return true; - } - return false; + return MapFindResult(TBase::TryFromString(name), ret); } EEnum FromString(const TStringBuf name) const { return TCast::CastFromRepresentationType(TBase::FromString(name)); } + static bool TryFromStringFullScan(const TStringBuf name, EEnum& ret, const TInitializationData& enumInitData) { + return MapFindResult(TBase::TryFromStringFullScan(name, enumInitData), ret); + } + + static bool TryFromStringSorted(const TStringBuf name, EEnum& ret, const TInitializationData& enumInitData) { + return MapFindResult(TBase::TryFromStringSorted(name, enumInitData), ret); + } + + static EEnum FromStringFullScan(const TStringBuf name, const TInitializationData& enumInitData) { + return TCast::CastFromRepresentationType(TBase::FromStringFullScan(name, enumInitData)); + } + + static EEnum FromStringSorted(const TStringBuf name, const TInitializationData& enumInitData) { + return TCast::CastFromRepresentationType(TBase::FromStringSorted(name, enumInitData)); + } + TMappedDictView<EEnum, TString> EnumNames() const noexcept { return {TBase::TypelessEnumNames()}; } @@ -109,6 +142,18 @@ namespace NEnumSerializationRuntime { TBase::Out(os, TCast::CastToRepresentationType(key)); } + static void OutFullScan(IOutputStream* os, const EEnum key, const TInitializationData& enumInitData) { + TBase::OutFullScan(os, TCast::CastToRepresentationType(key), enumInitData); + } + + static void OutSorted(IOutputStream* os, const EEnum key, const TInitializationData& enumInitData) { + TBase::OutSorted(os, TCast::CastToRepresentationType(key), enumInitData); + } + + static void OutDirect(IOutputStream* os, const EEnum key, const TInitializationData& enumInitData) { + TBase::OutDirect(os, TCast::CastToRepresentationType(key), enumInitData); + } + static constexpr TEnumStringPair EnumStringPair(const EEnum key, const TStringBuf name) noexcept { return {TCast::CastToRepresentationType(key), name}; } diff --git a/tools/enum_parser/enum_serialization_runtime/ordered_pairs.cpp b/tools/enum_parser/enum_serialization_runtime/ordered_pairs.cpp new file mode 100644 index 0000000000..00d1d05129 --- /dev/null +++ b/tools/enum_parser/enum_serialization_runtime/ordered_pairs.cpp @@ -0,0 +1 @@ +#include "ordered_pairs.h" diff --git a/tools/enum_parser/enum_serialization_runtime/ordered_pairs.h b/tools/enum_parser/enum_serialization_runtime/ordered_pairs.h new file mode 100644 index 0000000000..874c709418 --- /dev/null +++ b/tools/enum_parser/enum_serialization_runtime/ordered_pairs.h @@ -0,0 +1,71 @@ +#pragma once + +#include <util/generic/array_ref.h> +#include <util/generic/strbuf.h> + +namespace NEnumSerializationRuntime { + enum class ESortOrder: int { + Unordered = 0, + Ascending = 1, + StrictlyAscending = 2, + DirectMapping = 3, + }; + + template <typename TEnumRepresentationType> + struct TEnumStringPair { + const TEnumRepresentationType Key; + const TStringBuf Name; + }; + + template <typename TEnumRepresentationType> + constexpr ESortOrder GetKeyFieldSortOrder(const TArrayRef<const TEnumStringPair<TEnumRepresentationType>> initializer) { + if (initializer.empty()) { + return ESortOrder::DirectMapping; + } + bool direct = true; + bool strict = true; + bool sorted = true; + TEnumRepresentationType expected = initializer.data()[0].Key; + for (size_t i = 1; i < initializer.size(); ++i) { + const auto& prev = initializer.data()[i - 1].Key; + const auto& next = initializer.data()[i - 0].Key; + if (++expected != next) { + direct = false; + } + if (prev >= next) { + strict = false; + } + if (prev > next) { + sorted = false; + break; + } + } + return direct ? ESortOrder::DirectMapping + : strict ? ESortOrder::StrictlyAscending + : sorted ? ESortOrder::Ascending + : ESortOrder::Unordered; + } + + template <typename TEnumRepresentationType> + constexpr ESortOrder GetNameFieldSortOrder(const TArrayRef<const TEnumStringPair<TEnumRepresentationType>> initializer) { + if (initializer.empty()) { + return ESortOrder::DirectMapping; + } + bool strict = true; + bool sorted = true; + for (size_t i = 1; i < initializer.size(); ++i) { + const std::string_view prev = initializer.data()[i - 1].Name; + const std::string_view next = initializer.data()[i - 0].Name; + if (prev >= next) { + strict = false; + } + if (prev > next) { + sorted = false; + break; + } + } + return strict ? ESortOrder::StrictlyAscending + : sorted ? ESortOrder::Ascending + : ESortOrder::Unordered; + } +} |