include/ylt/standalone/iguana/dynamic.hpp (156 lines of code) (raw):

#pragma once #include "common.hpp" namespace iguana { using base = detail::base; constexpr inline uint8_t ENABLE_JSON = 0x01; constexpr inline uint8_t ENABLE_YAML = 0x02; constexpr inline uint8_t ENABLE_XML = 0x04; constexpr inline uint8_t ENABLE_PB = 0x08; constexpr inline uint8_t ENABLE_ALL = 0x0F; template <typename T, uint8_t ENABLE_FLAG = ENABLE_PB> struct base_impl : public base { base_impl() { [[maybe_unused]] static bool r = register_type<T>(); } void to_pb(std::string& str) const override { if constexpr ((ENABLE_FLAG & ENABLE_PB) != 0) { to_pb_adl((iguana_adl_t*)nullptr, *(static_cast<T const*>(this)), str); } else { throw std::runtime_error("Protobuf Disabled"); } } void from_pb(std::string_view str) override { if constexpr ((ENABLE_FLAG & ENABLE_PB) != 0) { from_pb_adl((iguana_adl_t*)nullptr, *(static_cast<T*>(this)), str); } else { throw std::runtime_error("Protobuf Disabled"); } } void to_json(std::string& str) const override { if constexpr ((ENABLE_FLAG & ENABLE_JSON) != 0) { to_json_adl((iguana_adl_t*)nullptr, *(static_cast<T const*>(this)), str); } else { throw std::runtime_error("Json Disabled"); } } void from_json(std::string_view str) override { if constexpr ((ENABLE_FLAG & ENABLE_JSON) != 0) { from_json_adl((iguana_adl_t*)nullptr, *(static_cast<T*>(this)), str); } else { throw std::runtime_error("Json Disabled"); } } void to_xml(std::string& str) const override { if constexpr ((ENABLE_FLAG & ENABLE_XML) != 0) { to_xml_adl((iguana_adl_t*)nullptr, *(static_cast<T const*>(this)), str); } else { throw std::runtime_error("Xml Disabled"); } } void from_xml(std::string_view str) override { if constexpr ((ENABLE_FLAG & ENABLE_XML) != 0) { from_xml_adl((iguana_adl_t*)nullptr, *(static_cast<T*>(this)), str); } else { throw std::runtime_error("Xml Disabled"); } } void to_yaml(std::string& str) const override { if constexpr ((ENABLE_FLAG & ENABLE_YAML) != 0) { to_yaml_adl((iguana_adl_t*)nullptr, *(static_cast<T const*>(this)), str); } else { throw std::runtime_error("Yaml Disabled"); } } void from_yaml(std::string_view str) override { if constexpr ((ENABLE_FLAG & ENABLE_YAML) != 0) { from_yaml_adl((iguana_adl_t*)nullptr, *(static_cast<T*>(this)), str); } else { throw std::runtime_error("Yaml Disabled"); } } iguana::detail::field_info get_field_info( std::string_view name) const override { static auto map = detail::get_members(ylt::reflection::internal::wrapper<T>::value); iguana::detail::field_info info{}; for (auto const& [no, field] : map) { if (info.offset > 0) { break; } std::visit( [&](auto const& val) { if (val.field_name == name) { info.offset = val.offset; using value_type = typename std::remove_reference_t<decltype(val)>::value_type; #if defined(__clang__) || defined(_MSC_VER) || \ (defined(__GNUC__) && __GNUC__ > 8) info.type_name = type_string<value_type>(); #endif } }, field); } return info; } std::vector<std::string_view> get_fields_name() const override { static auto map = detail::get_members(ylt::reflection::internal::wrapper<T>::value); std::vector<std::string_view> vec; for (auto const& [no, val] : map) { std::visit( [&](auto const& field) { std::string_view const current_name{field.field_name.data(), field.field_name.size()}; if (vec.empty() || (vec.back() != current_name)) { vec.push_back(current_name); } }, val); } return vec; } std::any get_field_any(std::string_view name) const override { static auto map = detail::get_members(ylt::reflection::internal::wrapper<T>::value); std::any result; for (auto const& [no, field] : map) { if (result.has_value()) { break; } std::visit( [&](auto const& val) { if (val.field_name == name) { using value_type = typename std::remove_reference_t<decltype(val)>::value_type; auto ptr = (char*)this + val.offset; result = *((value_type*)ptr); } }, field); } return result; } virtual ~base_impl() {} mutable size_t cache_size = 0; private: virtual void dummy() { // make sure init T before main, and can register_type before main. [[maybe_unused]] static auto t = ylt::reflection::internal::wrapper<T>::value; } }; IGUANA_INLINE std::shared_ptr<base> create_instance(std::string_view name) { auto it = iguana::detail::g_pb_map.find(name); if (it == iguana::detail::g_pb_map.end()) { throw std::invalid_argument(std::string(name) + "not inheried from iguana::base_impl"); } return it->second(); } } // namespace iguana