Line data Source code
1 : #ifndef C9F0AFE7_2B64_483A_9B0A_9B7D7DA9DEFC_HPP 2 : #define C9F0AFE7_2B64_483A_9B0A_9B7D7DA9DEFC_HPP 3 : 4 : #include "ExceptionWithLocation.hpp" 5 : #include "Types.hpp" 6 : 7 : #include <cstdint> 8 : #include <string> 9 : #include <unordered_map> 10 : #include <vector> 11 : 12 : namespace cell 13 : { 14 : 15 : template <typename ValueType> class TypeRegistry 16 : { 17 : public: 18 : using KeyType = std::uint16_t; 19 : 20 : public: 21 26 : TypeRegistry() = default; 22 : TypeRegistry(const TypeRegistry&) = delete; 23 22 : TypeRegistry(TypeRegistry&&) = default; 24 : 25 : void setValues(std::vector<ValueType>&& values); 26 : const std::vector<ValueType>& getValues() const; 27 : 28 : KeyType getIDFor(const std::string& name) const; 29 : const ValueType& getByID(KeyType ID) const; 30 : std::vector<KeyType> getIDs() const; 31 : 32 : private: 33 : void buildNameIDMap(const std::vector<ValueType>& values); 34 : 35 : private: 36 : std::vector<ValueType> values_; 37 : std::unordered_map<std::string, KeyType> nameIDMap_; 38 : }; 39 : 40 26 : template <typename ValueType> inline void TypeRegistry<ValueType>::setValues(std::vector<ValueType>&& values) 41 : { 42 26 : if (values.empty()) 43 : { 44 0 : values_.clear(); 45 0 : nameIDMap_.clear(); 46 0 : return; 47 : } 48 : 49 26 : const auto MaxCount = std::numeric_limits<KeyType>::max(); 50 26 : if (values.size() > MaxCount) 51 0 : throw ExceptionWithLocation("Too many types: Registry only supports " + std::to_string(MaxCount) + ", but " + 52 : std::to_string(values.size()) + " were given"); 53 : 54 26 : values_ = std::move(values); 55 26 : buildNameIDMap(values_); 56 : } 57 : 58 : template <typename ValueType> inline const std::vector<ValueType>& TypeRegistry<ValueType>::getValues() const 59 : { 60 : return values_; 61 : } 62 : 63 : template <typename ValueType> 64 102 : inline TypeRegistry<ValueType>::KeyType TypeRegistry<ValueType>::getIDFor(const std::string& name) const 65 : { 66 102 : auto iter = nameIDMap_.find(name); 67 102 : if (iter == nameIDMap_.end()) 68 0 : throw ExceptionWithLocation("Couldn't find type with name \"" + name + "\" in registry"); 69 : 70 102 : return iter->second; 71 : } 72 : 73 363391 : template <typename ValueType> inline const ValueType& TypeRegistry<ValueType>::getByID(KeyType ID) const 74 : { 75 : #ifdef DEBUG 76 363391 : if (static_cast<std::size_t>(ID) >= values_.size()) 77 0 : throw ExceptionWithLocation("Index out of range: " + std::to_string(ID) + ", registry size is " + 78 : std::to_string(values_.size())); 79 : #endif 80 : 81 363391 : return values_[ID]; 82 : } 83 : 84 : template <typename ValueType> 85 : inline std::vector<typename TypeRegistry<ValueType>::KeyType> TypeRegistry<ValueType>::getIDs() const 86 : { 87 : std::vector<KeyType> ids; 88 : ids.reserve(values_.size()); 89 : for (KeyType i = 0; i < static_cast<KeyType>(values_.size()); ++i) 90 : ids.push_back(i); 91 : 92 : return ids; 93 : } 94 : 95 26 : template <typename ValueType> inline void TypeRegistry<ValueType>::buildNameIDMap(const std::vector<ValueType>& values) 96 : { 97 26 : std::unordered_map<std::string, KeyType> nameIDMap; 98 : 99 99 : for (KeyType i = 0; i < static_cast<KeyType>(values.size()); ++i) 100 : { 101 73 : if (nameIDMap.contains(values[i].getName())) 102 0 : throw ExceptionWithLocation("Can't build name map: Duplicate type name \"" + values[i].getName() + "\""); 103 : 104 73 : nameIDMap[values[i].getName()] = i; 105 : } 106 : 107 26 : nameIDMap_ = std::move(nameIDMap); 108 26 : } 109 : 110 : } // namespace cell 111 : #endif /* C9F0AFE7_2B64_483A_9B0A_9B7D7DA9DEFC_HPP */