// // Struct.cpp // Clock Signal // // Created by Thomas Harte on 13/03/2020. // Copyright © 2020 Thomas Harte. All rights reserved. // #include "Struct.hpp" #include // MARK: - Setters template <> bool Reflection::set(Struct &target, const std::string &name, int value) { const auto target_type = target.type_of(name); if(!target_type) return false; // No need to convert an int or a registered enum. if(*target_type == typeid(int) || !Reflection::Enum::name(*target_type).empty()) { target.set(name, &value); return true; } // Promote to an int64_t. if(*target_type == typeid(int64_t)) { const auto int64 = int64_t(value); target.set(name, &int64); return true; } return false; } template <> bool Reflection::set(Struct &target, const std::string &name, const std::string &value) { const auto target_type = target.type_of(name); if(!target_type) return false; if(Reflection::Enum::name(*target_type).empty()) { return false; } const int enum_value = Reflection::Enum::from_string(*target_type, value); if(enum_value < 0) { return false; } target.set(name, &enum_value); return true; } template <> bool Reflection::set(Struct &target, const std::string &name, const char *value) { const std::string string(value); return set(target, name, string); } template <> bool Reflection::set(Struct &target, const std::string &name, bool value) { const auto target_type = target.type_of(name); if(!target_type) return false; if(*target_type == typeid(bool)) { target.set(name, &value);; } return false; } // MARK: - Fuzzy setter bool Reflection::fuzzy_set(Struct &target, const std::string &name, const std::string &value) { const auto target_type = target.type_of(name); if(!target_type) return false; // If the target is a registered enum, ttry to convert the value. Failing that, // try to match without case sensitivity. if(Reflection::Enum::size(*target_type)) { const int from_string = Reflection::Enum::from_string(*target_type, value); if(from_string >= 0) { target.set(name, &from_string); return true; } const auto all_values = Reflection::Enum::all_values(*target_type); const auto value_location = std::find_if(all_values.begin(), all_values.end(), [&value] (const auto &entry) { if(value.size() != entry.size()) return false; const char *v = value.c_str(); const char *e = entry.c_str(); while(*v) { if(tolower(*v) != tolower(*e)) return false; ++v; ++e; } return true; }); if(value_location != all_values.end()) { const int offset = int(value_location - all_values.begin()); target.set(name, &offset); return true; } return false; } return false; } // MARK: - Getters template bool Reflection::get(Struct &target, const std::string &name, Type &value) { return false; } template <> bool Reflection::get(Struct &target, const std::string &name, bool &value) { const auto target_type = target.type_of(name); if(!target_type) return false; if(*target_type == typeid(bool)) { value = *reinterpret_cast(target.get(name)); return true; } return false; }