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 24 : TypeRegistry() = default; 22 : TypeRegistry(const TypeRegistry&) = delete; 23 20 : 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 : 31 : private: 32 : void buildNameIDMap(const std::vector<ValueType>& values); 33 : 34 : private: 35 : std::vector<ValueType> values_; 36 : std::unordered_map<std::string, KeyType> nameIDMap_; 37 : }; 38 : 39 24 : template <typename ValueType> inline void TypeRegistry<ValueType>::setValues(std::vector<ValueType>&& values) 40 : { 41 24 : if (values.empty()) 42 : { 43 0 : values_.clear(); 44 0 : nameIDMap_.clear(); 45 0 : return; 46 : } 47 : 48 24 : const auto MaxCount = std::numeric_limits<KeyType>::max(); 49 24 : if (values.size() > MaxCount) 50 0 : throw ExceptionWithLocation("Too many types: Registry only supports " + std::to_string(MaxCount) + ", but " + 51 : std::to_string(values.size()) + " were given"); 52 : 53 24 : values_ = std::move(values); 54 24 : buildNameIDMap(values_); 55 : } 56 : 57 : template <typename ValueType> inline const std::vector<ValueType>& TypeRegistry<ValueType>::getValues() const 58 : { 59 : return values_; 60 : } 61 : 62 : template <typename ValueType> 63 91 : inline TypeRegistry<ValueType>::KeyType TypeRegistry<ValueType>::getIDFor(const std::string& name) const 64 : { 65 91 : auto iter = nameIDMap_.find(name); 66 91 : if (iter == nameIDMap_.end()) 67 0 : throw ExceptionWithLocation("Couldn't find type with name \"" + name + "\" in registry"); 68 : 69 91 : return iter->second; 70 : } 71 : 72 363295 : template <typename ValueType> inline const ValueType& TypeRegistry<ValueType>::getByID(KeyType ID) const 73 : { 74 : #ifdef DEBUG 75 363295 : if (static_cast<std::size_t>(ID) >= values_.size()) 76 0 : throw ExceptionWithLocation("Index out of range: " + std::to_string(ID) + ", registry size is " + 77 : std::to_string(values_.size())); 78 : #endif 79 : 80 363295 : return values_[ID]; 81 : } 82 : 83 24 : template <typename ValueType> inline void TypeRegistry<ValueType>::buildNameIDMap(const std::vector<ValueType>& values) 84 : { 85 24 : std::unordered_map<std::string, KeyType> nameIDMap; 86 : 87 91 : for (KeyType i = 0; i < static_cast<KeyType>(values.size()); ++i) 88 : { 89 67 : if (nameIDMap.contains(values[i].getName())) 90 0 : throw ExceptionWithLocation("Can't build name map: Duplicate type name \"" + values[i].getName() + "\""); 91 : 92 67 : nameIDMap[values[i].getName()] = i; 93 : } 94 : 95 24 : nameIDMap_ = std::move(nameIDMap); 96 24 : } 97 : 98 : } // namespace cell 99 : #endif /* C9F0AFE7_2B64_483A_9B0A_9B7D7DA9DEFC_HPP */