diff --git a/include/ylt/standalone/iguana/detail/pb_type.hpp b/include/ylt/standalone/iguana/detail/pb_type.hpp index 2ce5f60b1..2d17cb8e4 100644 --- a/include/ylt/standalone/iguana/detail/pb_type.hpp +++ b/include/ylt/standalone/iguana/detail/pb_type.hpp @@ -1,4 +1,5 @@ #pragma once +#include namespace iguana { @@ -87,6 +88,12 @@ inline bool operator<(const sfixed64_t& lhs, const sfixed64_t& rhs) { return lhs.val < rhs.val; } +template > +constexpr bool is_pb_type_v = + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; + } // namespace iguana // for key in std::unordered_map diff --git a/include/ylt/standalone/iguana/dynamic.hpp b/include/ylt/standalone/iguana/dynamic.hpp new file mode 100644 index 000000000..cfb5b116c --- /dev/null +++ b/include/ylt/standalone/iguana/dynamic.hpp @@ -0,0 +1,171 @@ +#pragma once +#include "reflection.hpp" + +namespace iguana { +using base = detail::base; + +template +IGUANA_INLINE constexpr size_t member_offset(T* t, U T::*member) { + return (char*)&(t->*member) - (char*)t; +} + +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 +struct base_impl : public base { + void to_pb(std::string& str) override { + if constexpr ((ENABLE_FLAG & ENABLE_PB) != 0) { + to_pb_adl((iguana_adl_t*)nullptr, *(static_cast(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(this)), str); + } + else { + throw std::runtime_error("Protobuf Disabled"); + } + } + + void to_json(std::string& str) override { + if constexpr ((ENABLE_FLAG & ENABLE_JSON) != 0) { + to_json_adl((iguana_adl_t*)nullptr, *(static_cast(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(this)), str); + } + else { + throw std::runtime_error("Json Disabled"); + } + } + + void to_xml(std::string& str) override { + if constexpr ((ENABLE_FLAG & ENABLE_XML) != 0) { + to_xml_adl((iguana_adl_t*)nullptr, *(static_cast(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(this)), str); + } + else { + throw std::runtime_error("Xml Disabled"); + } + } + + void to_yaml(std::string& str) override { + if constexpr ((ENABLE_FLAG & ENABLE_YAML) != 0) { + to_yaml_adl((iguana_adl_t*)nullptr, *(static_cast(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(this)), str); + } + else { + throw std::runtime_error("Yaml Disabled"); + } + } + + iguana::detail::field_info get_field_info(std::string_view name) override { + static constexpr auto map = iguana::get_members(); + iguana::detail::field_info info{}; + for (auto& [no, field] : map) { + if (info.offset > 0) { + break; + } + std::visit( + [&](auto val) { + if (val.field_name == name) { + info.offset = member_offset((T*)this, val.member_ptr); + using value_type = typename decltype(val)::value_type; +#if defined(__clang__) || defined(_MSC_VER) || \ + (defined(__GNUC__) && __GNUC__ > 8) + info.type_name = type_string(); +#endif + } + }, + field); + } + + return info; + } + + std::vector get_fields_name() const override { + static constexpr auto map = iguana::get_members(); + + std::vector 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 constexpr auto map = iguana::get_members(); + std::any result; + + for (auto [no, field] : map) { + if (result.has_value()) { + break; + } + std::visit( + [&](auto val) { + if (val.field_name == name) { + using value_type = typename decltype(val)::value_type; + auto const offset = member_offset((T*)this, val.member_ptr); + auto ptr = (((char*)this) + offset); + result = {*((value_type*)ptr)}; + } + }, + field); + } + + return result; + } + + virtual ~base_impl() {} + + size_t cache_size = 0; +}; + +IGUANA_INLINE std::shared_ptr 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 \ No newline at end of file diff --git a/include/ylt/standalone/iguana/iguana.hpp b/include/ylt/standalone/iguana/iguana.hpp new file mode 100644 index 000000000..77dc2bc53 --- /dev/null +++ b/include/ylt/standalone/iguana/iguana.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "iguana/dynamic.hpp" +#include "iguana/json_reader.hpp" +#include "iguana/json_writer.hpp" +#include "iguana/pb_reader.hpp" +#include "iguana/pb_writer.hpp" +#include "iguana/xml_reader.hpp" +#include "iguana/xml_writer.hpp" +#include "iguana/yaml_reader.hpp" +#include "iguana/yaml_writer.hpp" diff --git a/include/ylt/standalone/iguana/json_reader.hpp b/include/ylt/standalone/iguana/json_reader.hpp index 050183492..d433f0170 100644 --- a/include/ylt/standalone/iguana/json_reader.hpp +++ b/include/ylt/standalone/iguana/json_reader.hpp @@ -86,6 +86,11 @@ IGUANA_INLINE void from_json_impl(U &value, It &&it, It &&end) { } } +template , int> = 0> +IGUANA_INLINE void from_json_impl(U &value, It &&it, It &&end) { + from_json_impl(value.val, it, end); +} + template , int> = 0> IGUANA_INLINE void from_json_impl(U &value, It &&it, It &&end) { skip_ws(it, end); @@ -899,4 +904,10 @@ IGUANA_INLINE void from_json_file(T &value, const std::string &filename, } } +template +IGUANA_INLINE void from_json_adl(iguana_adl_t *p, T &t, + std::string_view pb_str) { + iguana::from_json(t, pb_str); +} + } // namespace iguana diff --git a/include/ylt/standalone/iguana/json_util.hpp b/include/ylt/standalone/iguana/json_util.hpp index f1bf3a331..5887599f2 100644 --- a/include/ylt/standalone/iguana/json_util.hpp +++ b/include/ylt/standalone/iguana/json_util.hpp @@ -3,6 +3,7 @@ #pragma once +#include "detail/pb_type.hpp" #include "util.hpp" #include "value.hpp" diff --git a/include/ylt/standalone/iguana/json_writer.hpp b/include/ylt/standalone/iguana/json_writer.hpp index eeaeaa399..498e0a2d7 100644 --- a/include/ylt/standalone/iguana/json_writer.hpp +++ b/include/ylt/standalone/iguana/json_writer.hpp @@ -13,7 +13,7 @@ template -IGUANA_INLINE void to_json_impl(Stream &ss, std::optional &val); +IGUANA_INLINE void to_json_impl(Stream &ss, const std::optional &val); template , int> = 0> @@ -76,6 +76,12 @@ IGUANA_INLINE void to_json_impl(Stream &ss, T value) { ss.append(temp, p - temp); } +template , int> = 0> +IGUANA_INLINE void to_json_impl(Stream &ss, T value) { + to_json_impl(ss, value.val); +} + template , int> = 0> IGUANA_INLINE void to_json_impl(Stream &ss, T v) { @@ -97,12 +103,18 @@ IGUANA_INLINE void to_json_impl(Stream &ss, T &&t) { template , int> = 0> -IGUANA_INLINE void render_key(Stream &ss, T &t) { +IGUANA_INLINE void render_key(Stream &ss, const T &t) { ss.push_back('"'); to_json_impl(ss, t); ss.push_back('"'); } +template , int> = 0> +IGUANA_INLINE void render_key(Stream &ss, const T &t) { + render_key(ss, t.val); +} + template , int> = 0> IGUANA_INLINE void render_key(Stream &ss, T &&t) { @@ -140,7 +152,7 @@ IGUANA_INLINE void to_json_impl(Stream &ss, T val) { } template -IGUANA_INLINE void to_json_impl(Stream &ss, std::optional &val) { +IGUANA_INLINE void to_json_impl(Stream &ss, const std::optional &val) { if (!val) { ss.append("null"); } @@ -282,5 +294,10 @@ IGUANA_INLINE void to_json(T &&t, Stream &s) { to_json_impl(s, t); } +template +IGUANA_INLINE void to_json_adl(iguana_adl_t *p, T &t, std::string &pb_str) { + to_json(t, pb_str); +} + } // namespace iguana #endif // SERIALIZE_JSON_HPP diff --git a/include/ylt/standalone/iguana/pb_reader.hpp b/include/ylt/standalone/iguana/pb_reader.hpp index 6a0a92d9a..83d2425d4 100644 --- a/include/ylt/standalone/iguana/pb_reader.hpp +++ b/include/ylt/standalone/iguana/pb_reader.hpp @@ -3,7 +3,8 @@ #include "pb_util.hpp" namespace iguana { - +template +IGUANA_INLINE void from_pb(T& t, std::string_view pb_str); namespace detail { template @@ -254,4 +255,9 @@ IGUANA_INLINE void from_pb(T& t, std::string_view pb_str) { } } } + +template +IGUANA_INLINE void from_pb_adl(iguana_adl_t* p, T& t, std::string_view pb_str) { + iguana::from_pb(t, pb_str); +} } // namespace iguana diff --git a/include/ylt/standalone/iguana/pb_util.hpp b/include/ylt/standalone/iguana/pb_util.hpp index d1bd3d03b..5fa7365cd 100644 --- a/include/ylt/standalone/iguana/pb_util.hpp +++ b/include/ylt/standalone/iguana/pb_util.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -30,112 +29,8 @@ enum class WireType : uint32_t { Unknown }; -template -IGUANA_INLINE void to_pb(T& t, Stream& out); - -template -IGUANA_INLINE void from_pb(T& t, std::string_view pb_str); - -using base = detail::base; - -template -IGUANA_INLINE constexpr size_t member_offset(T* t, U T::*member) { - return (char*)&(t->*member) - (char*)t; -} - template -struct base_impl : public base { - void to_pb(std::string& str) override { - iguana::to_pb(*(static_cast(this)), str); - } - - void from_pb(std::string_view str) override { - iguana::from_pb(*(static_cast(this)), str); - } - - iguana::detail::field_info get_field_info(std::string_view name) override { - static constexpr auto map = iguana::get_members(); - iguana::detail::field_info info{}; - for (auto [no, field] : map) { - if (info.offset > 0) { - break; - } - std::visit( - [&](auto val) { - if (val.field_name == name) { - info.offset = member_offset((T*)this, val.member_ptr); - using value_type = typename decltype(val)::value_type; -#if defined(__clang__) || defined(_MSC_VER) || \ - (defined(__GNUC__) && __GNUC__ > 8) - info.type_name = type_string(); -#endif - } - }, - field); - } - - return info; - } - - std::vector get_fields_name() const override { - static constexpr auto map = iguana::get_members(); - - std::vector vec; - std::set sets; - - for (auto const& [no, val] : map) { - std::visit( - [&](auto const& field) { - if (auto it = sets.emplace(field.field_name.data(), - field.field_name.size()); - it.second) { - vec.push_back(*it.first); - } - }, - val); - } - return vec; - } - - std::any get_field_any(std::string_view name) const override { - static constexpr auto map = iguana::get_members(); - std::any result; - - for (auto [no, field] : map) { - if (result.has_value()) { - break; - } - std::visit( - [&](auto val) { - if (val.field_name == name) { - using value_type = typename decltype(val)::value_type; - auto const offset = member_offset((T*)this, val.member_ptr); - auto ptr = (((char*)this) + offset); - result = {*((value_type*)ptr)}; - } - }, - field); - } - - return result; - } - - virtual ~base_impl() {} - - size_t cache_size = 0; -}; - -template -constexpr bool inherits_from_base_v = std::is_base_of_v; - -IGUANA_INLINE std::shared_ptr 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(); -} +constexpr bool inherits_from_base_v = std::is_base_of_v; namespace detail { template diff --git a/include/ylt/standalone/iguana/pb_writer.hpp b/include/ylt/standalone/iguana/pb_writer.hpp index db2662ab5..4c39305a6 100644 --- a/include/ylt/standalone/iguana/pb_writer.hpp +++ b/include/ylt/standalone/iguana/pb_writer.hpp @@ -205,6 +205,247 @@ IGUANA_INLINE void to_pb_impl(Type&& t, It&& it, uint32_t*& sz_ptr) { encode_numeric_field(t, it); } } + +#if defined(__clang__) || defined(_MSC_VER) || \ + (defined(__GNUC__) && __GNUC__ > 8) +template +IGUANA_INLINE constexpr std::string_view get_type_string() { + if constexpr (std::is_integral_v) { + if constexpr (std::is_same_v) { + return "bool"; + } + else if constexpr (sizeof(T) <= 4) { + if constexpr (std::is_unsigned_v) { + return "uint32"; + } + else { + return "int32"; + } + } + else { + if constexpr (std::is_unsigned_v) { + return "uint64"; + } + else { + return "int64"; + } + } + } + else if constexpr (std::is_same_v || + std::is_same_v) { + return "string"; + } + else if constexpr (std::is_floating_point_v) { + return type_string(); + } + else { + constexpr auto str_type_name = type_string(); + constexpr size_t pos = str_type_name.rfind("::"); + if constexpr (pos != std::string_view::npos) { + constexpr size_t pos = str_type_name.rfind("::") + 2; + if constexpr (detail::is_signed_varint_v || detail::is_fixed_v) { + return str_type_name.substr(pos, str_type_name.size() - pos - 2); + } + else { + return str_type_name.substr(pos); + } + } + else { + return str_type_name; + } + } +} + +template +IGUANA_INLINE void numeric_to_proto(Stream& out, std::string_view field_name, + uint32_t field_no) { + constexpr auto name = get_type_string(); + out.append(name).append(" "); + out.append(field_name) + .append(" = ") + .append(std::to_string(field_no)) + .append(";\n"); +} + +template +IGUANA_INLINE void build_proto_field(Stream& out, std::string_view str_type, + std::string_view field_name, + uint32_t field_no) { + for (size_t i = 0; i < space_count; i++) { + out.append(" "); + } + + if (!str_type.empty()) { + out.append(str_type); + } + + out.append(" ") + .append(field_name) + .append(" = ") + .append(std::to_string(field_no)) + .append(";\n"); +} + +template +IGUANA_INLINE void build_sub_proto(Map& map, std::string_view str_type, + std::string& sub_str); + +template +IGUANA_INLINE void to_proto_impl( + Stream& out, std::unordered_map& map, + std::string_view field_name = "", uint32_t field_no = 0) { + std::string sub_str; + using T = std::remove_const_t>; + if constexpr (is_reflection_v || is_custom_reflection_v) { + constexpr auto name = get_name(); + out.append("message ").append(name).append(" {\n"); + static constexpr auto tuple = get_members_tuple(); + constexpr size_t SIZE = std::tuple_size_v>; + + for_each_n( + [&out, &sub_str, &map](auto i) mutable { + using field_type = + std::tuple_element_t>; + constexpr auto value = std::get(tuple); + + using U = typename field_type::value_type; + if constexpr (is_reflection_v) { + constexpr auto str_type = get_type_string(); + build_proto_field( + out, str_type, + {value.field_name.data(), value.field_name.size()}, + value.field_no); + + build_sub_proto(map, str_type, sub_str); + } + else if constexpr (variant_v) { + constexpr size_t var_size = std::variant_size_v; + using sub_type = typename field_type::sub_type; + + constexpr auto offset = + get_variant_index(); + + if (offset == 0) { + out.append(" oneof "); + out.append(value.field_name.data(), value.field_name.size()) + .append(" {\n"); + } + + constexpr auto str_type = get_type_string(); + std::string field_name = " one_of_"; + field_name.append(str_type); + + out.append(" "); + build_proto_field(out, str_type, field_name, value.field_no); + + if constexpr (is_reflection_v) { + build_sub_proto(map, str_type, sub_str); + } + + if (offset == var_size - 1) { + out.append(" }\n"); + } + } + else { + to_proto_impl(out, map, + {value.field_name.data(), value.field_name.size()}, + value.field_no); + } + }, + std::make_index_sequence{}); + out.append("}\r\n\r\n"); + } + else if constexpr (is_sequence_container::value) { + out.append(" repeated"); + using item_type = typename T::value_type; + + if constexpr (is_lenprefix_v) { + // non-packed + if constexpr (is_reflection_v) { + constexpr auto str_type = get_type_string(); + build_proto_field(out, str_type, field_name, field_no); + + build_sub_proto(map, str_type, sub_str); + } + else { + to_proto_impl(out, map, field_name, field_no); + } + } + else { + out.append(" "); + numeric_to_proto(out, field_name, field_no); + } + } + else if constexpr (is_map_container::value) { + out.append(" map<"); + using first_type = typename T::key_type; + using second_type = typename T::mapped_type; + + constexpr auto str_first = get_type_string(); + constexpr auto str_second = get_type_string(); + out.append(str_first).append(", ").append(str_second).append(">"); + + build_proto_field<1>(out, "", field_name, field_no); + + if constexpr (is_reflection_v) { + constexpr auto str_type = get_type_string(); + build_sub_proto(map, str_type, sub_str); + } + } + else if constexpr (optional_v) { + to_proto_impl( + out, map, {field_name.data(), field_name.size()}, field_no); + } + else if constexpr (std::is_same_v || + std::is_same_v) { + build_proto_field(out, "string ", field_name, field_no); + } + else if constexpr (enum_v) { + constexpr auto str_type = get_type_string(); + static constexpr auto enum_to_str = get_enum_map>(); + if constexpr (bool_v) { + build_proto_field(out, "int32", field_name, field_no); + } + else { + static_assert(enum_to_str.size() > 0, "empty enum not allowed"); + static_assert((int)(enum_to_str.begin()->first) == 0, + "the first enum value must be zero in proto3"); + build_proto_field(out, str_type, field_name, field_no); + if (map.find(str_type) == map.end()) { + sub_str.append("enum ").append(str_type).append(" {\n"); + for (auto& [k, field_name] : enum_to_str) { + std::string_view name{field_name.data(), field_name.size()}; + size_t pos = name.rfind("::"); + if (pos != std::string_view::npos) { + name = name.substr(pos + 2); + } + sub_str.append(" ") + .append(name) + .append(" = ") + .append(std::to_string(static_cast>(k))) + .append(";\n"); + } + sub_str.append("}\r\n\r\n"); + map.emplace(str_type, std::move(sub_str)); + } + } + } + else { + out.append(" "); + numeric_to_proto(out, field_name, field_no); + } +} + +template +IGUANA_INLINE void build_sub_proto(Map& map, std::string_view str_type, + std::string& sub_str) { + if (map.find(str_type) == map.end()) { + to_proto_impl(sub_str, map); + map.emplace(str_type, std::move(sub_str)); + } +} +#endif } // namespace detail template @@ -216,4 +457,42 @@ IGUANA_INLINE void to_pb(T& t, Stream& out) { detail::to_pb_impl<0>(t, &out[0], sz_ptr); } +#if defined(__clang__) || defined(_MSC_VER) || \ + (defined(__GNUC__) && __GNUC__ > 8) +template +IGUANA_INLINE void to_proto(Stream& out, std::string_view ns = "") { + if (gen_header) { + constexpr std::string_view crlf = "\r\n\r\n"; + out.append(R"(syntax = "proto3";)").append(crlf); + if (!ns.empty()) { + out.append("package ").append(ns).append(";").append(crlf); + } + + out.append(R"(option optimize_for = SPEED;)").append(crlf); + out.append(R"(option cc_enable_arenas = true;)").append(crlf); + } + + std::unordered_map map; + detail::to_proto_impl(out, map); + for (auto& [k, s] : map) { + out.append(s); + } +} + +template +IGUANA_INLINE void to_proto_file(Stream& stream, std::string_view ns = "") { + if (!stream.is_open()) { + return; + } + std::string out; + to_proto(out, ns); + stream.write(out.data(), out.size()); +} +#endif + +template +IGUANA_INLINE void to_pb_adl(iguana_adl_t* p, T& t, Stream& out) { + to_pb(t, out); +} + } // namespace iguana diff --git a/include/ylt/standalone/iguana/reflection.hpp b/include/ylt/standalone/iguana/reflection.hpp index 354d8a119..ceb605a44 100644 --- a/include/ylt/standalone/iguana/reflection.hpp +++ b/include/ylt/standalone/iguana/reflection.hpp @@ -564,6 +564,12 @@ struct field_info { struct base { virtual void to_pb(std::string &str) {} virtual void from_pb(std::string_view str) {} + virtual void to_xml(std::string &str) {} + virtual void from_xml(std::string_view str) {} + virtual void to_json(std::string &str) {} + virtual void from_json(std::string_view str) {} + virtual void to_yaml(std::string &str) {} + virtual void from_yaml(std::string_view str) {} virtual std::vector get_fields_name() const { return {}; } virtual std::any get_field_any(std::string_view name) const { return {}; } virtual iguana::detail::field_info get_field_info(std::string_view name) { @@ -578,14 +584,16 @@ struct base { return *((T *)ptr); } - template + template void set_field_value(std::string_view name, T val) { auto info = get_field_info(name); - check_field(name, info); + check_field(name, info); auto ptr = (((char *)this) + info.offset); - *((T *)ptr) = std::move(val); + static_assert(std::is_constructible_v, "can not assign"); + + *((FiledType *)ptr) = std::move(val); } virtual ~base() {} @@ -756,6 +764,8 @@ namespace iguana { MAKE_META_DATA(STRUCT_NAME, TABLE_NAME, GET_ARG_COUNT(__VA_ARGS__), \ __VA_ARGS__) +struct iguana_adl_t {}; + template inline auto iguana_reflect_type(const T &t); @@ -836,7 +846,7 @@ constexpr inline auto build_fields(T t, S &s, uint32_t &index) { return build_variant_fields(t, s, I + 1, std::make_index_sequence{}); } else { - uint32_t field_no = (I == index) ? (I + 1) : (I + index); + uint32_t field_no = (I == index) ? (I + 1) : (2 + index); index++; return std::tuple(field_t{t, field_no, s}); } diff --git a/include/ylt/standalone/iguana/util.hpp b/include/ylt/standalone/iguana/util.hpp index 3f6768a91..2d89e74d8 100644 --- a/include/ylt/standalone/iguana/util.hpp +++ b/include/ylt/standalone/iguana/util.hpp @@ -297,8 +297,8 @@ IGUANA_INLINE void write_string_with_escape(const Ch* it, SizeType length, template IGUANA_INLINE constexpr bool has_duplicate(const std::array& arr) { - for (int i = 0; i < arr.size(); i++) { - for (int j = i + 1; j < arr.size(); j++) { + for (size_t i = 0; i < arr.size(); i++) { + for (size_t j = i + 1; j < arr.size(); j++) { if (arr[i] == arr[j]) { return true; } diff --git a/include/ylt/standalone/iguana/xml_reader.hpp b/include/ylt/standalone/iguana/xml_reader.hpp index 209b4f894..8b9c908f4 100644 --- a/include/ylt/standalone/iguana/xml_reader.hpp +++ b/include/ylt/standalone/iguana/xml_reader.hpp @@ -9,23 +9,23 @@ namespace iguana { namespace detail { template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name); +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name); template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name); +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name); template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name); +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name); template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name); +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name); template , int> = 0> -IGUANA_INLINE void parse_value(U &&value, It &&begin, It &&end) { +IGUANA_INLINE void xml_parse_value(U &&value, It &&begin, It &&end) { using T = std::decay_t; if constexpr (string_container_v) { if constexpr (string_view_v) { @@ -70,8 +70,8 @@ IGUANA_INLINE void parse_value(U &&value, It &&begin, It &&end) { static constexpr auto str_to_enum = get_enum_map(); if constexpr (bool_v) { // not defined a specialization template - parse_value(reinterpret_cast &>(value), begin, - end); + xml_parse_value(reinterpret_cast &>(value), + begin, end); } else { auto enum_names = std::string_view( @@ -86,6 +86,12 @@ IGUANA_INLINE void parse_value(U &&value, It &&begin, It &&end) { } } } + +template , int> = 0> +IGUANA_INLINE void xml_parse_value(U &&value, It &&begin, It &&end) { + xml_parse_value(value.val, begin, end); +} + template , int> = 0> IGUANA_INLINE void parse_attr(U &&value, It &&it, It &&end) { @@ -98,7 +104,7 @@ IGUANA_INLINE void parse_attr(U &&value, It &&it, It &&end) { auto key_begin = it; auto key_end = skip_pass<'='>(it, end); key_type key; - parse_value(key, key_begin, key_end); + xml_parse_value(key, key_begin, key_end); skip_sapces_and_newline(it, end); auto value_begin = it + 1; @@ -115,28 +121,34 @@ IGUANA_INLINE void parse_attr(U &&value, It &&it, It &&end) { else IGUANA_UNLIKELY { throw std::runtime_error("expected quote or apos"); } value_type v; - parse_value(v, value_begin, value_end); + xml_parse_value(v, value_begin, value_end); value.emplace(std::move(key), std::move(v)); } } template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name) { +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name) { skip_till<'>'>(it, end); ++it; skip_sapces_and_newline(it, end); auto value_begin = it; auto value_end = skip_pass<'<'>(it, end); - parse_value(value, value_begin, value_end); + xml_parse_value(value, value_begin, value_end); match_close_tag(it, end, name); } +template , int> = 0> +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name) { + xml_parse_item(value.val, it, end, name); +} + template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name) { - parse_item(value.emplace_back(), it, end, name); +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name) { + xml_parse_item(value.emplace_back(), it, end, name); skip_sapces_and_newline(it, end); while (it != end) { match<'<'>(it, end); @@ -154,14 +166,27 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, it = start - 1; return; } - parse_item(value.emplace_back(), it, end, name); + xml_parse_item(value.emplace_back(), it, end, name); skip_sapces_and_newline(it, end); } } +template , int> = 0> +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name) { + throw std::bad_function_call(); +} + +template , int> = 0> +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name) { + throw std::bad_function_call(); +} + template , int>> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name) { +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name) { using value_type = typename std::remove_reference_t::value_type; skip_till<'>'>(it, end); if (*(it - 1) == '/') @@ -182,17 +207,17 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, match_close_tag(it, end, name); return; } - parse_value(value.emplace(), value_begin, value_end); + xml_parse_value(value.emplace(), value_begin, value_end); match_close_tag(it, end, name); } else { - parse_item(value.emplace(), it, end, name); + xml_parse_item(value.emplace(), it, end, name); } } template , int>> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name) { +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name) { if constexpr (unique_ptr_v) { value = std::make_unique::element_type>(); } @@ -200,14 +225,14 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, value = std::make_shared::element_type>(); } - parse_item(*value, it, end, name); + xml_parse_item(*value, it, end, name); } template , int>> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, - std::string_view name) { +IGUANA_INLINE void xml_parse_item(U &value, It &&it, It &&end, + std::string_view name) { parse_attr(value.attr(), it, end); - parse_item(value.value(), it, end, name); + xml_parse_item(value.value(), it, end, name); } // /> or skip and until the @@ -368,8 +393,8 @@ IGUANA_INLINE void check_required(std::string_view key_set) { } template , int>> -IGUANA_INLINE void parse_item(T &value, It &&it, It &&end, - std::string_view name) { +IGUANA_INLINE void xml_parse_item(T &value, It &&it, It &&end, + std::string_view name) { using U = std::decay_t; constexpr auto cdata_idx = get_type_index(); skip_till<'>'>(it, end); @@ -400,7 +425,7 @@ IGUANA_INLINE void parse_item(T &value, It &&it, It &&end, if (parse_done || key != st_key) IGUANA_UNLIKELY { return; } if constexpr (!cdata_v) { - parse_item(value.*member_ptr, it, end, key); + xml_parse_item(value.*member_ptr, it, end, key); if constexpr (iguana::has_iguana_required_arr_v) { key_set.append(key).append(", "); } @@ -434,7 +459,7 @@ IGUANA_INLINE void parse_item(T &value, It &&it, It &&end, "type must be memberptr"); using V = std::remove_reference_t; if constexpr (!cdata_v) { - parse_item(value.*member_ptr, it, end, key); + xml_parse_item(value.*member_ptr, it, end, key); if constexpr (iguana::has_iguana_required_arr_v) { key_set.append(key).append(", "); } @@ -472,7 +497,7 @@ IGUANA_INLINE void from_xml(U &value, It &&it, It &&end) { std::string_view key = std::string_view{&*start, static_cast(std::distance(start, it))}; detail::parse_attr(value.attr(), it, end); - detail::parse_item(value.value(), it, end, key); + detail::xml_parse_item(value.value(), it, end, key); } template , int> = 0> @@ -482,7 +507,7 @@ IGUANA_INLINE void from_xml(U &value, It &&it, It &&end) { skip_till_greater_or_space(it, end); std::string_view key = std::string_view{&*start, static_cast(std::distance(start, it))}; - detail::parse_item(value, it, end, key); + detail::xml_parse_item(value, it, end, key); } template , int> = 0> IGUANA_INLINE Num get_number(std::string_view str) { Num num; - detail::parse_value(num, str.begin(), str.end()); + detail::xml_parse_value(num, str.begin(), str.end()); return num; } +template +IGUANA_INLINE void from_xml_adl(iguana_adl_t *p, T &t, + std::string_view pb_str) { + iguana::from_xml(t, pb_str); +} + } // namespace iguana \ No newline at end of file diff --git a/include/ylt/standalone/iguana/xml_util.hpp b/include/ylt/standalone/iguana/xml_util.hpp index dabd47a38..8259e1764 100644 --- a/include/ylt/standalone/iguana/xml_util.hpp +++ b/include/ylt/standalone/iguana/xml_util.hpp @@ -1,4 +1,5 @@ #pragma once +#include "detail/pb_type.hpp" #include "util.hpp" namespace iguana { diff --git a/include/ylt/standalone/iguana/xml_writer.hpp b/include/ylt/standalone/iguana/xml_writer.hpp index 94e35f37b..f9d5009d6 100644 --- a/include/ylt/standalone/iguana/xml_writer.hpp +++ b/include/ylt/standalone/iguana/xml_writer.hpp @@ -63,6 +63,11 @@ template , int> = 0> +IGUANA_INLINE void render_xml_value(Stream &ss, const T &value, + std::string_view name); + template , int> = 0> IGUANA_INLINE void render_xml_value(Stream &ss, T &&t, std::string_view name); @@ -133,6 +138,12 @@ IGUANA_INLINE void render_value(Stream &ss, const T &value) { } } +template , int> = 0> +IGUANA_INLINE void render_value(Stream &ss, const T &value) { + render_value(ss, value); +} + template , int> = 0> inline void render_xml_attr(Stream &ss, const T &value, std::string_view name) { @@ -160,6 +171,20 @@ IGUANA_INLINE void render_xml_value(Stream &ss, const T &value, render_tail(ss, name); } +template >, int> = 0> +IGUANA_INLINE void render_xml_value(Stream &ss, const T &value, + std::string_view name) { + render_xml_value(ss, value.val, name); +} + +template >, int> = 0> +IGUANA_INLINE void render_xml_value(Stream &ss, const T &value, + std::string_view name) { + throw std::bad_function_call(); +} + template , int> = 0> IGUANA_INLINE void render_xml_value(Stream &ss, const T &value, @@ -209,6 +234,20 @@ IGUANA_INLINE void render_xml_value(Stream &ss, const T &value, } } +template , int>> +IGUANA_INLINE void render_xml_value(Stream &ss, const T &value, + std::string_view name) { + throw std::bad_function_call(); +} + +template , int>> +IGUANA_INLINE void render_xml_value(Stream &ss, const T &value, + std::string_view name) { + throw std::bad_function_call(); +} + template , int>> IGUANA_INLINE void render_xml_value(Stream &ss, T &&t, std::string_view name) { @@ -267,4 +306,9 @@ IGUANA_INLINE void to_xml(T &&t, Stream &s) { render_xml_value(s, std::forward(t), root_name); } +template +IGUANA_INLINE void to_xml_adl(iguana_adl_t *p, T &t, std::string &pb_str) { + to_xml(t, pb_str); +} + } // namespace iguana diff --git a/include/ylt/standalone/iguana/yaml_reader.hpp b/include/ylt/standalone/iguana/yaml_reader.hpp index 0a0d47fa7..4e1f050a7 100644 --- a/include/ylt/standalone/iguana/yaml_reader.hpp +++ b/include/ylt/standalone/iguana/yaml_reader.hpp @@ -14,6 +14,20 @@ IGUANA_INLINE void from_yaml(T &value, It &&it, It &&end, namespace detail { +template , int> = 0> +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { + throw std::bad_function_call(); +} + +template , int> = 0> +IGUANA_INLINE void yaml_parse_value(U &value, It &&value_begin, + It &&value_end) { + throw std::bad_function_call(); +} + template , int> = 0> IGUANA_INLINE void parse_escape_str(U &value, It &&it, It &&end) { auto start = it; @@ -105,10 +119,12 @@ IGUANA_INLINE void parse_block_str(U &value, It &&it, It &&end, template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces); +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces); template , int> = 0> -IGUANA_INLINE void parse_value(U &value, It &&value_begin, It &&value_end) { +IGUANA_INLINE void yaml_parse_value(U &value, It &&value_begin, + It &&value_end) { if (value_begin == value_end) IGUANA_UNLIKELY { return; } auto size = std::distance(value_begin, value_end); @@ -116,10 +132,17 @@ IGUANA_INLINE void parse_value(U &value, It &&value_begin, It &&value_end) { detail::from_chars(start, start + size, value); } +template , int> = 0> +IGUANA_INLINE void yaml_parse_value(U &value, It &&value_begin, + It &&value_end) { + yaml_parse_value(value.val, value_begin, value_end); +} + // string_view should be used for string with ' " ? template , int> = 0> -IGUANA_INLINE void parse_value(U &value, It &&value_begin, It &&value_end) { +IGUANA_INLINE void yaml_parse_value(U &value, It &&value_begin, + It &&value_end) { using T = std::decay_t; auto start = value_begin; auto end = value_end; @@ -152,19 +175,21 @@ IGUANA_INLINE void parse_value(U &value, It &&value_begin, It &&value_end) { } template , int> = 0> -IGUANA_INLINE void parse_value(U &value, It &&value_begin, It &&value_end) { +IGUANA_INLINE void yaml_parse_value(U &value, It &&value_begin, + It &&value_end) { if (static_cast(std::distance(value_begin, value_end)) != 1) IGUANA_UNLIKELY { throw std::runtime_error("Expected one character"); } value = *value_begin; } template , int> = 0> -IGUANA_INLINE void parse_value(U &value, It &&value_begin, It &&value_end) { +IGUANA_INLINE void yaml_parse_value(U &value, It &&value_begin, + It &&value_end) { static constexpr auto str_to_enum = get_enum_map>(); if constexpr (bool_v) { // not defined a specialization template using T = std::underlying_type_t>; - parse_value(reinterpret_cast(value), value_begin, value_end); + yaml_parse_value(reinterpret_cast(value), value_begin, value_end); } else { auto enum_names = std::string_view( @@ -181,7 +206,8 @@ IGUANA_INLINE void parse_value(U &value, It &&value_begin, It &&value_end) { } template , int> = 0> -IGUANA_INLINE void parse_value(U &&value, It &&value_begin, It &&value_end) { +IGUANA_INLINE void yaml_parse_value(U &&value, It &&value_begin, + It &&value_end) { auto bool_v = std::string_view( &*value_begin, static_cast(std::distance(value_begin, value_end))); @@ -196,12 +222,14 @@ IGUANA_INLINE void parse_value(U &&value, It &&value_begin, It &&value_end) { } template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { from_yaml(value, it, end, min_spaces); } template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { using T = std::decay_t; if constexpr (string_v) { if (skip_space_till_end(it, end)) @@ -224,27 +252,36 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { skip_space_and_lines(it, end, min_spaces); auto start = it; auto value_end = skip_till_newline(it, end); - parse_value(value, start, value_end); + yaml_parse_value(value, start, value_end); } } else { skip_space_and_lines(it, end, min_spaces); auto start = it; auto value_end = skip_till_newline(it, end); - parse_value(value, start, value_end); + yaml_parse_value(value, start, value_end); } } +template , int> = 0> +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { + yaml_parse_item(value.val, it, end, min_spaces); +} + template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces); +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces); template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces); +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces); // minspaces : The minimum indentation template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { value.clear(); auto spaces = skip_space_and_lines(it, end, min_spaces); using value_type = typename std::remove_cv_t::value_type; @@ -259,13 +296,13 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { } if constexpr (plain_v) { auto start = it; - auto value_end = skip_till<',', ']'>(it, end); - parse_value(value.emplace_back(), start, value_end); + auto value_end = yaml_skip_till<',', ']'>(it, end); + yaml_parse_value(value.emplace_back(), start, value_end); if (*(it - 1) == ']') IGUANA_UNLIKELY { return; } } else { - parse_item(value.emplace_back(), it, end, spaces + 1); + yaml_parse_item(value.emplace_back(), it, end, spaces + 1); skip_space_and_lines(it, end, min_spaces); if (*it == ',') IGUANA_LIKELY { ++it; } @@ -289,15 +326,15 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { subspaces = skip_space_and_lines(it, end, spaces + 1); if constexpr (string_v) { // except string_v because of scalar blocks - parse_item(value.emplace_back(), it, end, spaces + 1); + yaml_parse_item(value.emplace_back(), it, end, spaces + 1); } else if constexpr (plain_v) { auto start = it; auto value_end = skip_till_newline(it, end); - parse_value(value.emplace_back(), start, value_end); + yaml_parse_value(value.emplace_back(), start, value_end); } else { - parse_item(value.emplace_back(), it, end, subspaces); + yaml_parse_item(value.emplace_back(), it, end, subspaces); } } } @@ -306,7 +343,8 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { } template , int> = 0> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { auto spaces = skip_space_and_lines(it, end, min_spaces); if (*it == '[') { ++it; @@ -316,11 +354,11 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { skip_space_and_lines(it, end, min_spaces); if constexpr (plain_v) { auto start = it; - auto value_end = skip_till<',', ']'>(it, end); - parse_value(v, start, value_end); + auto value_end = yaml_skip_till<',', ']'>(it, end); + yaml_parse_value(v, start, value_end); } else { - parse_item(v, it, end, spaces + 1); + yaml_parse_item(v, it, end, spaces + 1); skip_space_and_lines(it, end, min_spaces); ++it; // skip , } @@ -337,15 +375,15 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { [[maybe_unused]] auto subspaces = skip_space_and_lines(it, end, spaces + 1); if constexpr (string_v) { - parse_item(v, it, end, spaces + 1); + yaml_parse_item(v, it, end, spaces + 1); } else if constexpr (plain_v) { auto start = it; auto value_end = skip_till_newline(it, end); - parse_value(v, start, value_end); + yaml_parse_value(v, start, value_end); } else { - parse_item(v, it, end, subspaces); + yaml_parse_item(v, it, end, subspaces); } }); } @@ -355,7 +393,8 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { } template , int>> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { using T = std::remove_reference_t; using key_type = typename T::key_type; using value_type = typename T::mapped_type; @@ -370,19 +409,19 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { return; } auto start = it; - auto value_end = skip_till<':'>(it, end); + auto value_end = yaml_skip_till<':'>(it, end); key_type key; - parse_value(key, start, value_end); + yaml_parse_value(key, start, value_end); subspaces = skip_space_and_lines(it, end, min_spaces); if constexpr (plain_v) { start = it; - value_end = skip_till<',', '}'>(it, end); - parse_value(value[key], start, value_end); + value_end = yaml_skip_till<',', '}'>(it, end); + yaml_parse_value(value[key], start, value_end); if (*(it - 1) == '}') IGUANA_UNLIKELY { return; } } else { - parse_item(value[key], it, end, min_spaces); + yaml_parse_item(value[key], it, end, min_spaces); subspaces = skip_space_and_lines(it, end, min_spaces); if (*it == ',') IGUANA_LIKELY { ++it; } @@ -399,17 +438,17 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { return; } auto start = it; - auto value_end = skip_till<':'>(it, end); + auto value_end = yaml_skip_till<':'>(it, end); key_type key; - parse_value(key, start, value_end); + yaml_parse_value(key, start, value_end); subspaces = skip_space_and_lines(it, end, min_spaces); if constexpr (plain_v && !string_v) { start = it; value_end = skip_till_newline(it, end); - parse_value(value[key], start, value_end); + yaml_parse_value(value[key], start, value_end); } else { - parse_item(value[key], it, end, spaces + 1); + yaml_parse_item(value[key], it, end, spaces + 1); } subspaces = skip_space_and_lines(it, end, min_spaces); } @@ -417,7 +456,8 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { } template , int>> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { using T = std::remove_reference_t; if constexpr (unique_ptr_v) { value = std::make_unique(); @@ -427,11 +467,12 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { } static_assert(!string_v, "smart_ptr is not allowed"); - parse_item(*value, it, end, min_spaces); + yaml_parse_item(*value, it, end, min_spaces); } template , int>> -IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { +IGUANA_INLINE void yaml_parse_item(U &value, It &&it, It &&end, + size_t min_spaces) { using T = std::remove_reference_t; using value_type = typename T::value_type; auto spaces = skip_space_and_lines(it, end, min_spaces); @@ -454,7 +495,7 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { } if constexpr (string_v || !plain_v) { it = start; - parse_item(value.emplace(), it, end, min_spaces); + yaml_parse_item(value.emplace(), it, end, min_spaces); } else { if (value_end == end) @@ -462,7 +503,7 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) { // if value_end isn't touched value_end = skip_till_newline(it, end); } - parse_value(value.emplace(), start, value_end); + yaml_parse_value(value.emplace(), start, value_end); } } @@ -494,7 +535,7 @@ IGUANA_INLINE void from_yaml(T &value, It &&it, It &&end, size_t min_spaces) { auto spaces = skip_space_and_lines(it, end, min_spaces); while (it != end) { auto start = it; - auto keyend = skip_till<':'>(it, end); + auto keyend = yaml_skip_till<':'>(it, end); std::string_view key = std::string_view{ &*start, static_cast(std::distance(start, keyend))}; static constexpr auto frozen_map = get_iguana_struct_map(); @@ -506,7 +547,8 @@ IGUANA_INLINE void from_yaml(T &value, It &&it, It &&end, size_t min_spaces) { [&](auto &&member_ptr) IGUANA__INLINE_LAMBDA { using V = std::decay_t; if constexpr (std::is_member_pointer_v) { - detail::parse_item(value.*member_ptr, it, end, spaces + 1); + detail::yaml_parse_item(value.*member_ptr, it, end, + spaces + 1); } else { static_assert(!sizeof(V), "type not supported"); @@ -535,7 +577,7 @@ IGUANA_INLINE void from_yaml(T &value, It &&it, It &&end, size_t min_spaces) { template , int> = 0> IGUANA_INLINE void from_yaml(T &value, It &&it, It &&end) { - detail::parse_item(value, it, end, 0); + detail::yaml_parse_item(value, it, end, 0); } template @@ -567,4 +609,10 @@ IGUANA_INLINE void from_yaml(T &value, const View &view, } } +template +IGUANA_INLINE void from_yaml_adl(iguana_adl_t *p, T &t, + std::string_view pb_str) { + iguana::from_yaml(t, pb_str); +} + } // namespace iguana diff --git a/include/ylt/standalone/iguana/yaml_util.hpp b/include/ylt/standalone/iguana/yaml_util.hpp index 0f2be3708..920a99185 100644 --- a/include/ylt/standalone/iguana/yaml_util.hpp +++ b/include/ylt/standalone/iguana/yaml_util.hpp @@ -1,8 +1,13 @@ #pragma once +#include "detail/pb_type.hpp" #include "util.hpp" namespace iguana { + +template +constexpr inline bool yaml_not_support_v = variant_v; + // return true when it==end template IGUANA_INLINE bool skip_space_till_end(It &&it, It &&end) { @@ -42,7 +47,7 @@ IGUANA_INLINE auto skip_till_newline(It &&it, It &&end) { } template -IGUANA_INLINE auto skip_till(It &&it, It &&end) { +IGUANA_INLINE auto yaml_skip_till(It &&it, It &&end) { if (it == end) IGUANA_UNLIKELY { return it; } std::decay_t res = it; @@ -93,7 +98,7 @@ IGUANA_INLINE size_t skip_space_and_lines(It &&it, It &&end, size_t minspaces) { // skip the --- line if ((it != end) && (*it == '-')) IGUANA_UNLIKELY { - auto line_end = skip_till(it, end); + auto line_end = yaml_skip_till(it, end); auto line = std::string_view( &*start, static_cast(std::distance(start, line_end))); if (line != "---") { diff --git a/include/ylt/standalone/iguana/yaml_writer.hpp b/include/ylt/standalone/iguana/yaml_writer.hpp index a0794f2c3..1feed6d47 100644 --- a/include/ylt/standalone/iguana/yaml_writer.hpp +++ b/include/ylt/standalone/iguana/yaml_writer.hpp @@ -5,6 +5,12 @@ namespace iguana { +template , int> = 0> +IGUANA_INLINE void render_yaml_value(Stream &ss, T &&t, size_t min_spaces = 0) { + throw std::bad_function_call(); +} + template , int> = 0> IGUANA_INLINE void to_yaml(T &&t, Stream &s, size_t min_spaces = 0); @@ -41,6 +47,12 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, T value, size_t min_spaces) { ss.push_back('\n'); } +template , int> = 0> +IGUANA_INLINE void render_yaml_value(Stream &ss, T value, size_t min_spaces) { + render_yaml_value(ss, value.val, min_spaces); +} + template IGUANA_INLINE void render_yaml_value(Stream &ss, char value, size_t min_spaces) { @@ -191,4 +203,9 @@ IGUANA_INLINE void to_yaml(T &&t, Stream &s) { static_assert(!sizeof(T), "don't suppport this type"); } +template +IGUANA_INLINE void to_yaml_adl(iguana_adl_t *p, const T &t, + std::string &pb_str) { + to_yaml(t, pb_str); +} } // namespace iguana diff --git a/include/ylt/struct_pb/struct_pb_impl.hpp b/include/ylt/struct_pb/struct_pb_impl.hpp index 909995d8c..ee5342058 100644 --- a/include/ylt/struct_pb/struct_pb_impl.hpp +++ b/include/ylt/struct_pb/struct_pb_impl.hpp @@ -14,6 +14,7 @@ * limitations under the License. */ #pragma once +#include #include #include namespace struct_pb = iguana; diff --git a/src/struct_pb/tests/CMakeLists.txt b/src/struct_pb/tests/CMakeLists.txt index a845733ca..91e2cb1ac 100644 --- a/src/struct_pb/tests/CMakeLists.txt +++ b/src/struct_pb/tests/CMakeLists.txt @@ -19,7 +19,8 @@ endif() set(TEST_PROTO main.cpp) -if (Protobuf_FOUND) +if (TEST_STRUCT_PB_WITH_PROTO) + message(STATUS "Gen proto files") add_definitions(-DSTRUCT_PB_WITH_PROTO) message(STATUS "Found Protobuf: ${Protobuf_VERSION}") include_directories(${Protobuf_INCLUDE_DIRS}) diff --git a/src/struct_pb/tests/main.cpp b/src/struct_pb/tests/main.cpp index 58098b3a2..7d95be6ef 100644 --- a/src/struct_pb/tests/main.cpp +++ b/src/struct_pb/tests/main.cpp @@ -1156,6 +1156,101 @@ TEST_CASE("test variant") { } } +#if defined(__clang__) || defined(_MSC_VER) || \ + (defined(__GNUC__) && __GNUC__ > 8) +struct person PUBLIC(person) { + person() = default; + person(int32_t a, std::string b, int c, double d) + : id(a), name(std::move(b)), age(c), salary(d) {} + int32_t id; + std::string name; + int age; + double salary; +}; +REFLECTION(person, id, name, age, salary); + +enum Color { Red = 0, Black = 2, Green = 4 }; + +namespace iguana { +template <> +struct enum_value { + constexpr static std::array value = {0, 2, 4}; +}; +} // namespace iguana + +struct vector_t { + int id; + Color color; + std::variant variant; + std::vector ids; + std::vector pairs; + std::vector strs; + std::map map; + std::string name; + std::optional op_val; +}; +REFLECTION(vector_t, id, color, variant, ids, pairs, strs, map, name, op_val); + +TEST_CASE("struct to proto") { + { + std::string str; + iguana::to_proto(str, "pb"); + std::cout << str; + CHECK(str.find(R"(syntax = "proto3";)") != std::string::npos); + CHECK(str.find("message vector_t") != std::string::npos); + CHECK(str.find("map map = 9;") != std::string::npos); + CHECK(str.find("Green = 4;") != std::string::npos); + + std::ofstream file("test_vector.proto", std::ios::binary); + iguana::to_proto_file(file, "pb"); + file.sync_with_stdio(true); + file.flush(); + file.close(); + + size_t size = std::filesystem::file_size("test_vector.proto"); + std::ifstream in("test_vector.proto", std::ios::binary); + std::string read_str; + read_str.resize(size); + in.read(read_str.data(), size); + CHECK(read_str.find("map map = 9;") != std::string::npos); + CHECK(read_str.find("Green = 4;") != std::string::npos); + } + { + std::string str; + iguana::to_proto(str, "pb"); + std::cout << str; + CHECK(str.find("message_t z = 3;") != std::string::npos); + CHECK(str.find("message message_t") != std::string::npos); + CHECK(str.find("pair_t t = 2;") != std::string::npos); + CHECK(str.find("message pair_t") != std::string::npos); + } + { + std::string str; + iguana::to_proto(str, "pb"); + std::cout << str; + CHECK(str.find("sint64 z = 3;") != std::string::npos); + + iguana::to_proto(str); + std::cout << str; + CHECK(str.find("fixed64 z = 3;") != std::string::npos); + + iguana::to_proto(str); + std::cout << str; + CHECK(str.find("sfixed64 z = 3;") != std::string::npos); + + iguana::to_proto(str); + std::cout << str; + CHECK(str.find("pair_t t = 2;") != std::string::npos); + } + { + std::string str; + iguana::to_proto(str); + std::cout << str; + CHECK(str.find("int32 age = 3;") != std::string::npos); + } +} +#endif + // doctest comments // 'function' : must be 'attribute' - see issue #182 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007)