Advertisement
hnOsmium0001

registry

Oct 12th, 2020
1,321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.31 KB | None | 0 0
  1.  
  2. #include <cstdint>
  3. #include <functional>
  4. #include <limits>
  5. #include <memory>
  6. #include <queue>
  7. #include <string_view>
  8. #include <unordered_map>
  9. #include <utility>
  10.  
  11. constexpr unsigned int INVALID_REGISTRY_ID = std::numeric_limits<unsigned int>::max();
  12.  
  13. template <class T>
  14. class RonlyRegistry {
  15. protected:
  16.     std::unordered_map<std::string_view, T*> mLookup;
  17.     std::vector<std::unique_ptr<T>> mContents;
  18.  
  19. public:
  20.     auto Lookup(std::string_view name) -> T* {
  21.         auto iter = mLookup.find(name);
  22.         if (iter != mLookup.end()) {
  23.             return iter->second;
  24.         } else {
  25.             return nullptr;
  26.         }
  27.     }
  28.  
  29.     auto Lookup(unsigned int id) -> T* {
  30.         if (id < mContents.size()) {
  31.             return mContents[id].get();
  32.         } else {
  33.             return nullptr;
  34.         }
  35.     }
  36.  
  37.     __declspec(property(get = GetLookupTable)) std::unordered_map<std::string_view, T*> const& LookupTable;
  38.     auto GetLookupTable() const -> std::unordered_map<std::string_view, T*> const& {
  39.         return mLookup;
  40.     }
  41. };
  42.  
  43. template <class T>
  44. class RwRegistry : public RonlyRegistry<T> {
  45. protected:
  46.     std::queue<unsigned int> mUnusedIDs;
  47.  
  48. public:
  49.     auto Register(T value) -> std::pair<unsigned int, T*> {
  50.         if (mLookup.find(value.Name) != mLookup.end()) {
  51.             // Register failed, entry with name already exists
  52.             return { 0, nullptr };
  53.         }
  54.  
  55.         if (mUnusedIDs.empty()) {
  56.             mContents.push_back(std::unique_ptr<T>(new T(std::move(value))));
  57.  
  58.             T* ref = mContents.back().get();
  59.             mLookup.insert({ ref->Name, ref });
  60.  
  61.             return { static_cast<unsigned int>(mContents.size() - 1), ref };
  62.         } else {
  63.             unsigned int id = mUnusedIDs.front();
  64.             mUnusedIDs.pop();
  65.  
  66.             mContents[id] = std::unique_ptr<T>(new T(std::move(value)));
  67.  
  68.             T* ref = mContents[id].get();
  69.             mLookup.insert({ ref->Name, ref });
  70.  
  71.             return { id, ref };
  72.         }
  73.     }
  74.  
  75.     auto Unregister(unsigned int id) -> void {
  76.         if (id >= mContents.size()) return;
  77.         if (auto& content = mContents[id]) {
  78.             mLookup.erase(content.Name);
  79.             mContents.erase(id);
  80.             mUnusedIDs.push(id);
  81.         }
  82.     }
  83.  
  84.     auto Unregister(std::string_view name) -> void {
  85.         auto iter = mLookup.find(name);
  86.         if (iter == mLookup.end()) {
  87.             return;
  88.         }
  89.  
  90.         auto& content = *iter->second;
  91.         // Only erases lookup, `content` is still valid
  92.         mLookup.erase(name);
  93.         unsigned int id = content.TypeId;
  94.         mContents[id] = nullptr;
  95.         mUnusedIDs.push(id);
  96.     }
  97. };
  98.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement