Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdint>
- #include <functional>
- #include <limits>
- #include <memory>
- #include <queue>
- #include <string_view>
- #include <unordered_map>
- #include <utility>
- constexpr unsigned int INVALID_REGISTRY_ID = std::numeric_limits<unsigned int>::max();
- template <class T>
- class RonlyRegistry {
- protected:
- std::unordered_map<std::string_view, T*> mLookup;
- std::vector<std::unique_ptr<T>> mContents;
- public:
- auto Lookup(std::string_view name) -> T* {
- auto iter = mLookup.find(name);
- if (iter != mLookup.end()) {
- return iter->second;
- } else {
- return nullptr;
- }
- }
- auto Lookup(unsigned int id) -> T* {
- if (id < mContents.size()) {
- return mContents[id].get();
- } else {
- return nullptr;
- }
- }
- __declspec(property(get = GetLookupTable)) std::unordered_map<std::string_view, T*> const& LookupTable;
- auto GetLookupTable() const -> std::unordered_map<std::string_view, T*> const& {
- return mLookup;
- }
- };
- template <class T>
- class RwRegistry : public RonlyRegistry<T> {
- protected:
- std::queue<unsigned int> mUnusedIDs;
- public:
- auto Register(T value) -> std::pair<unsigned int, T*> {
- if (mLookup.find(value.Name) != mLookup.end()) {
- // Register failed, entry with name already exists
- return { 0, nullptr };
- }
- if (mUnusedIDs.empty()) {
- mContents.push_back(std::unique_ptr<T>(new T(std::move(value))));
- T* ref = mContents.back().get();
- mLookup.insert({ ref->Name, ref });
- return { static_cast<unsigned int>(mContents.size() - 1), ref };
- } else {
- unsigned int id = mUnusedIDs.front();
- mUnusedIDs.pop();
- mContents[id] = std::unique_ptr<T>(new T(std::move(value)));
- T* ref = mContents[id].get();
- mLookup.insert({ ref->Name, ref });
- return { id, ref };
- }
- }
- auto Unregister(unsigned int id) -> void {
- if (id >= mContents.size()) return;
- if (auto& content = mContents[id]) {
- mLookup.erase(content.Name);
- mContents.erase(id);
- mUnusedIDs.push(id);
- }
- }
- auto Unregister(std::string_view name) -> void {
- auto iter = mLookup.find(name);
- if (iter == mLookup.end()) {
- return;
- }
- auto& content = *iter->second;
- // Only erases lookup, `content` is still valid
- mLookup.erase(name);
- unsigned int id = content.TypeId;
- mContents[id] = nullptr;
- mUnusedIDs.push(id);
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement