#pragma once #include #include #include #include #include #include template class TLocalProcessKeyState { template friend class TLocalProcessKey; template friend class TEnumProcessKey; public: static TLocalProcessKeyState& GetInstance() { return *Singleton>(); } size_t GetCount() const { return StartIndex + Names.size(); } TStringBuf GetNameByIndex(size_t index) const { if (index < StartIndex) { return StaticNames[index]; } else { index -= StartIndex; Y_ENSURE(index < Names.size()); return Names[index]; } } size_t GetIndexByName(TStringBuf name) const { auto it = Map.find(name); Y_ENSURE(it != Map.end()); return it->second; } private: size_t Register(TStringBuf name) { auto x = Map.emplace(name, Names.size()+StartIndex); if (x.second) { Names.emplace_back(name); } return x.first->second; } size_t Register(TStringBuf name, ui32 index) { Y_VERIFY(index < StartIndex); auto x = Map.emplace(name, index); Y_VERIFY(x.second || x.first->second == index); StaticNames[index] = name; return x.first->second; } private: static constexpr ui32 StartIndex = 2000; TVector FillStaticNames() { TVector staticNames; staticNames.reserve(StartIndex); for (ui32 i = 0; i < StartIndex; i++) { staticNames.push_back(TStringBuilder() << "Activity_" << i); } return staticNames; } TVector StaticNames = FillStaticNames(); TVector Names; THashMap Map; }; template class TLocalProcessKey { public: static TStringBuf GetName() { return Name; } static size_t GetIndex() { return Index; } private: inline static size_t Index = TLocalProcessKeyState::GetInstance().Register(Name); }; template class TEnumProcessKey { public: static TStringBuf GetName(EnumT key) { return TLocalProcessKeyState::GetInstance().GetNameByIndex(GetIndex(key)); } static size_t GetIndex(EnumT key) { ui32 index = static_cast(key); if (index < TLocalProcessKeyState::StartIndex) { return index; } Y_VERIFY(index < Enum2Index.size()); return Enum2Index[index]; } private: inline static TVector RegisterAll() { static_assert(std::is_enum::value, "Enum is required"); TVector enum2Index; auto names = GetEnumNames(); ui32 maxId = 0; for (const auto& [k, v] : names) { maxId = Max(maxId, static_cast(k)); } enum2Index.resize(maxId+1); for (ui32 i = 0; i <= maxId && i < TLocalProcessKeyState::StartIndex; i++) { enum2Index[i] = i; } for (const auto& [k, v] : names) { ui32 enumId = static_cast(k); enum2Index[enumId] = TLocalProcessKeyState::GetInstance().Register(v, enumId); } return enum2Index; } inline static TVector Enum2Index = RegisterAll(); };