Last active
September 21, 2023 09:29
-
-
Save nstansbury/6d627a447ca3b4ebbcf2c49ae37922c5 to your computer and use it in GitHub Desktop.
C++ KeyValue pair property variant
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| A KeyValue pair property variant in C++ for the RaspberryPi RP2040/Arduino/PlatformIO | |
| PropertyType is the base class that describes the underlying property type | |
| PropertyDescriptor is the variant value for that property name | |
| PropertySet is the unique Key/Value set itself | |
| Internally the PropertyDescriptors are stored as std:shared_ptrs so should be thread-safe | |
| To build in PlatformIO add to platformio.ini: | |
| build_unflags = -fno-rtti | |
| For inspiration and sample code credit to: | |
| https://stackoverflow.com/users/2068573/neil-kirk | |
| For: https://stackoverflow.com/a/24702400/2897944 | |
| Andrew Anderson | |
| for: https://dev.to/aka_dude/let-s-write-tagged-union-in-c-1chf | |
| and: https://gist.github.com/Mr-Andersen/cd5f9d8740e03b3a779bd49da281652d | |
| */ | |
| #include <memory> | |
| #include <string> | |
| #include <map> | |
| template<class T> | |
| class PropertyDescriptor; | |
| class PropertyType { | |
| protected: | |
| std::type_info* type; | |
| public: | |
| template<typename T> | |
| bool typeOf(){ | |
| const std::type_info& typeInfo = *this->type; | |
| return typeid(T) == typeInfo; | |
| } | |
| virtual ~PropertyType() = 0; | |
| }; | |
| inline PropertyType::~PropertyType() {} | |
| template<class T> | |
| class PropertyDescriptor : public PropertyType { | |
| private: | |
| T _value; | |
| public: | |
| explicit PropertyDescriptor(const T value){ | |
| this->type = const_cast<std::type_info*>(&typeid(value)); | |
| this->_value = value; | |
| } | |
| PropertyDescriptor(){} | |
| T value(){ | |
| return this->_value; | |
| } | |
| }; | |
| class PropertySet { | |
| protected: | |
| std::map<std::string, Unique<PropertyType>> _properties; | |
| public: | |
| template<typename T> | |
| void setProperty(std::string name, T value){ | |
| this->_properties[name].reset(new PropertyDescriptor<T>(value)); | |
| } | |
| template<typename T> | |
| const T getProperty(std::string name) const { | |
| auto iter = this->_properties.find(name); | |
| if(iter != this->_properties.end()){ | |
| if(iter->second->typeOf<T>()){ | |
| PropertyDescriptor<T> propertyDesc = dynamic_cast<PropertyDescriptor<T>&>(*iter->second); | |
| return propertyDesc.value(); | |
| } | |
| } | |
| return T(); | |
| } | |
| bool hasProperty(std::string name) const { | |
| auto iter = this->_properties.find(name); | |
| if(iter != this->_properties.end()){ | |
| return true; | |
| } | |
| return false; | |
| } | |
| template<typename T> | |
| bool hasProperty(std::string name) const { | |
| auto iter = this->_properties.find(name); | |
| if(iter != this->_properties.end()){ | |
| if(iter->second->typeOf<T>()){ | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| int size() const { | |
| return this->_properties.size(); | |
| } | |
| }; | |
| int main() { | |
| PropertySet props = PropertySet(); | |
| // Set the property key/value pair | |
| props.setProperty("IntProp", 12345); | |
| props.setProperty("StrProp", std::string("A string property")); | |
| props.setProperty("ArrProp", std::array<int, 5>({1,2,3,4,5})); | |
| // Get the property values based on the key | |
| auto intProp = props.getProperty<int>("IntProp"); | |
| auto strProp = props.getProperty<std::string>("StrProp"); | |
| auto arrProp = props.getProperty<std::array<int, 5>>("ArrProp"); | |
| // Has property "name" of <type> | |
| if(props.hasProperty<int>("IntProp")){ | |
| // .... | |
| } | |
| // Has property "name" of any type | |
| if(props.hasProperty("ArrProp")){ | |
| // .... | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment