Advertisement
hnOsmium0001

registry camel case

Jan 18th, 2021
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.08 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <cstdint>
  4. #include <functional>
  5. #include <limits>
  6. #include <memory>
  7. #include <queue>
  8. #include <string_view>
  9. #include <unordered_map>
  10. #include <utility>
  11.  
  12. constexpr auto kInvalidRegistryId = std::numeric_limits<uint32_t>::max();
  13.  
  14. template <class T>
  15. class RonlyRegistry {
  16. protected:
  17. std::unordered_map<std::string_view, T*> mLookup;
  18. std::vector<std::unique_ptr<T>> mContents;
  19.  
  20. public:
  21. T* lookup(std::string_view name) {
  22. auto iter = this->mLookup.find(name);
  23. if (iter != this->mLookup.end()) {
  24. return iter->second;
  25. } else {
  26. return nullptr;
  27. }
  28. }
  29.  
  30. T* lookup(uint32_t id) {
  31. if (id < this->mContents.size()) {
  32. return this->mContents[id].get();
  33. } else {
  34. return nullptr;
  35. }
  36. }
  37.  
  38. const std::unordered_map<std::string_view, T*>& getLookupTable() const {
  39. return this->mLookup;
  40. }
  41. };
  42.  
  43. template <class T>
  44. class RwRegistry : public RonlyRegistry<T> {
  45. protected:
  46. std::queue<uint32_t> mUnusedIDs;
  47.  
  48. public:
  49. std::pair<uint32_t, T*> registerItem(T value) {
  50. if (this->mLookup.find(value.Name) != this->mLookup.end()) {
  51. // Register failed, entry with name already exists
  52. return { 0, nullptr };
  53. }
  54.  
  55. if (this->mUnusedIDs.empty()) {
  56. this->mContents.push_back(std::unique_ptr<T>(new T(std::move(value))));
  57.  
  58. T* ref = this->mContents.back().get();
  59. this->mLookup.insert({ ref->Name, ref });
  60.  
  61. return { static_cast<uint32_t>(this->mContents.size() - 1), ref };
  62. } else {
  63. uint32_t id = this->mUnusedIDs.front();
  64. this->mUnusedIDs.pop();
  65.  
  66. this->mContents[id] = std::unique_ptr<T>(new T(std::move(value)));
  67.  
  68. T* ref = this->mContents[id].get();
  69. this->mLookup.insert({ ref->Name, ref });
  70.  
  71. return { id, ref };
  72. }
  73. }
  74.  
  75. void unregisterItem(uint32_t id) {
  76. if (id >= this->mContents.size()) return;
  77. if (auto& content = this->mContents[id]) {
  78. this->mLookup.erase(content.Name);
  79. this->mContents.erase(id);
  80. this->mUnusedIDs.push(id);
  81. }
  82. }
  83.  
  84. void unregisterItem(std::string_view name) {
  85. auto iter = this->mLookup.find(name);
  86. if (iter == this->mLookup.end()) {
  87. return;
  88. }
  89.  
  90. auto& content = *iter->second;
  91. // Only erases lookup, `content` is still valid
  92. this->mLookup.erase(name);
  93. uint32_t id = content.TypeId;
  94. this->mContents[id] = nullptr;
  95. this->mUnusedIDs.push(id);
  96. }
  97. };
  98.  
  99. #define MAKE_BASIC_REGISTRY_TOOLS(ItemType) \
  100. static RonlyRegistry<ItemType>& getRegistryView(); \
  101. static ItemType* registerItem(ItemType item); \
  102. static void unregisterItem(std::string_view name)
  103.  
  104. #define MAKE_BASIC_REGISTRY_TOOLS_IMPL(ItemType) \
  105. static RwRegistry<ItemType>& get##ItemType##Registry() { \
  106. static RwRegistry<ItemType> reg; \
  107. return reg; \
  108. } \
  109. RonlyRegistry<ItemType>& ItemType::getRegistryView() { \
  110. return ::get##ItemType##Registry(); \
  111. } \
  112. ItemType* ItemType::registerItem(ItemType item) { \
  113. auto [id, entry] = ::get##ItemType##Registry().registerItem(std::move(item)); \
  114. if (entry) { \
  115. entry->typeId = id; \
  116. return entry; \
  117. } else { \
  118. return nullptr; \
  119. } \
  120. } \
  121. void ItemType::unregisterItem(std::string_view name) { \
  122. ::get##ItemType##Registry().unregisterItem(name); \
  123. }
  124.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement