// Copyright 2017 Daniel Parker // Distributed under the Boost license, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // See https://github.com/danielaparker/jsoncons for latest version #ifndef JSONCONS_ENCODE_TRAITS_HPP #define JSONCONS_ENCODE_TRAITS_HPP #include #include #include #include #include // std::enable_if, std::true_type, std::false_type #include #include #include #include #include #include namespace jsoncons { // encode_traits template struct encode_traits { template static void encode(const T& val, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { encode(std::integral_constant::value>(), val, encoder, proto, ec); } private: template static void encode(std::true_type, const T& val, basic_json_visitor& encoder, const Json& /*proto*/, std::error_code& ec) { auto j = json_type_traits::to_json(val); j.dump(encoder, ec); } template static void encode(std::false_type, const T& val, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { auto j = json_type_traits::to_json(val, proto.get_allocator()); j.dump(encoder, ec); } }; // specializations // bool template struct encode_traits::value >::type> { template static void encode(const T& val, basic_json_visitor& encoder, const Json&, std::error_code& ec) { encoder.bool_value(val,semantic_tag::none,ser_context(),ec); } }; // uint template struct encode_traits::value >::type> { template static void encode(const T& val, basic_json_visitor& encoder, const Json&, std::error_code& ec) { encoder.uint64_value(val,semantic_tag::none,ser_context(),ec); } }; // int template struct encode_traits::value >::type> { template static void encode(const T& val, basic_json_visitor& encoder, const Json&, std::error_code& ec) { encoder.int64_value(val,semantic_tag::none,ser_context(),ec); } }; // float or double template struct encode_traits::value >::type> { template static void encode(const T& val, basic_json_visitor& encoder, const Json&, std::error_code& ec) { encoder.double_value(val,semantic_tag::none,ser_context(),ec); } }; // string template struct encode_traits::value && std::is_same::value >::type> { template static void encode(const T& val, basic_json_visitor& encoder, const Json&, std::error_code& ec) { encoder.string_value(val,semantic_tag::none,ser_context(),ec); } }; template struct encode_traits::value && !std::is_same::value >::type> { template static void encode(const T& val, basic_json_visitor& encoder, const Json&, std::error_code& ec) { std::basic_string s; unicode_traits::convert(val.data(), val.size(), s); encoder.string_value(s,semantic_tag::none,ser_context(),ec); } }; // std::pair template struct encode_traits, CharT> { using value_type = std::pair; template static void encode(const value_type& val, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { encoder.begin_array(2,semantic_tag::none,ser_context(),ec); if (ec) return; encode_traits::encode(val.first, encoder, proto, ec); if (ec) return; encode_traits::encode(val.second, encoder, proto, ec); if (ec) return; encoder.end_array(ser_context(),ec); } }; // std::tuple namespace detail { template struct json_serialize_tuple_helper { using char_type = typename Json::char_type; using element_type = typename std::tuple_element::type; using next = json_serialize_tuple_helper; static void encode(const Tuple& tuple, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { encode_traits::encode(std::get(tuple), encoder, proto, ec); if (ec) return; next::encode(tuple, encoder, proto, ec); } }; template struct json_serialize_tuple_helper<0, Size, Json, Tuple> { using char_type = typename Json::char_type; static void encode(const Tuple&, basic_json_visitor&, const Json&, std::error_code&) { } }; } // namespace detail template struct encode_traits, CharT> { using value_type = std::tuple; static constexpr std::size_t size = sizeof...(E); template static void encode(const value_type& val, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { using helper = jsoncons::detail::json_serialize_tuple_helper>; encoder.begin_array(size,semantic_tag::none,ser_context(),ec); if (ec) return; helper::encode(val, encoder, proto, ec); if (ec) return; encoder.end_array(ser_context(),ec); } }; // vector like template struct encode_traits::value && type_traits::is_list_like::value && !type_traits::is_typed_array::value >::type> { using value_type = typename T::value_type; template static void encode(const T& val, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { encoder.begin_array(val.size(),semantic_tag::none,ser_context(),ec); if (ec) return; for (auto it = std::begin(val); it != std::end(val); ++it) { encode_traits::encode(*it, encoder, proto, ec); if (ec) return; } encoder.end_array(ser_context(), ec); } }; template struct encode_traits::value && type_traits::is_list_like::value && type_traits::is_typed_array::value >::type> { using value_type = typename T::value_type; template static void encode(const T& val, basic_json_visitor& encoder, const Json&, std::error_code& ec) { encoder.typed_array(jsoncons::span(val), semantic_tag::none, ser_context(), ec); } }; // std::array template struct encode_traits,CharT> { using value_type = typename std::array::value_type; template static void encode(const std::array& val, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { encoder.begin_array(val.size(),semantic_tag::none,ser_context(),ec); if (ec) return; for (auto it = std::begin(val); it != std::end(val); ++it) { encode_traits::encode(*it, encoder, proto, ec); if (ec) return; } encoder.end_array(ser_context(),ec); } }; // map like template struct encode_traits::value && type_traits::is_map_like::value && type_traits::is_constructible_from_const_pointer_and_size::value >::type> { using mapped_type = typename T::mapped_type; using value_type = typename T::value_type; using key_type = typename T::key_type; template static void encode(const T& val, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { encoder.begin_object(val.size(), semantic_tag::none, ser_context(), ec); if (ec) return; for (auto it = std::begin(val); it != std::end(val); ++it) { encoder.key(it->first); encode_traits::encode(it->second, encoder, proto, ec); if (ec) return; } encoder.end_object(ser_context(), ec); if (ec) return; } }; template struct encode_traits::value && type_traits::is_map_like::value && std::is_integral::value >::type> { using mapped_type = typename T::mapped_type; using value_type = typename T::value_type; using key_type = typename T::key_type; template static void encode(const T& val, basic_json_visitor& encoder, const Json& proto, std::error_code& ec) { encoder.begin_object(val.size(), semantic_tag::none, ser_context(), ec); if (ec) return; for (auto it = std::begin(val); it != std::end(val); ++it) { std::basic_string s; jsoncons::detail::from_integer(it->first,s); encoder.key(s); encode_traits::encode(it->second, encoder, proto, ec); if (ec) return; } encoder.end_object(ser_context(), ec); if (ec) return; } }; } // jsoncons #endif