Skip to content

Commit

Permalink
perf: 进一步优化 serialize
Browse files Browse the repository at this point in the history
  • Loading branch information
MistEO committed Oct 20, 2023
1 parent 3ae9d5d commit 67a602a
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 31 deletions.
56 changes: 26 additions & 30 deletions include/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,9 @@ namespace literals
template <typename string_t = default_string_t>
const basic_value<string_t> invalid_value();

template <bool stream, typename any_t, typename string_t = default_string_t,
typename streamer_t = _serialization_helper::string_streamer<string_t>>
basic_value<string_t> serialize(any_t&& arg, streamer_t&& streamer = streamer_t());
template <bool loose, typename any_t, typename string_t = default_string_t,
typename string_converter_t = serialization_helper::string_converter<loose, string_t>>
basic_value<string_t> serialize(any_t&& arg, string_converter_t&& string_converter = {});

// ******************************
// * basic_value impl *
Expand Down Expand Up @@ -2527,7 +2527,7 @@ MEOJSON_INLINE const basic_value<string_t> invalid_value()
return basic_value<string_t>(basic_value<string_t>::value_type::invalid, typename basic_value<string_t>::var_t());
}

namespace _serialization_helper
namespace serialization_helper
{
template <typename char_t, typename T>
class has_output_operator
Expand Down Expand Up @@ -2566,40 +2566,36 @@ namespace _serialization_helper
template <typename T>
constexpr bool is_sequence_container<T> = is_container<T> && !is_associative_container<T>;

template <typename string_t>
struct string_streamer
template <bool loose, typename string_t = default_string_t>
struct string_converter
{
using char_t = typename string_t::value_type;
using ostringstream_t = std::basic_ostringstream<char_t, std::char_traits<char_t>, std::allocator<char_t>>;

static constexpr bool stream = loose;

template <typename input_t>
string_t operator()(input_t&& arg) const
{
ostringstream_t os;
os << std::forward<input_t>(arg);
return std::move(os).str();
if constexpr (std::is_constructible_v<string_t, input_t>) {
return arg;
}
else if constexpr (stream && has_output_operator<char_t, input_t>::value) {
ostringstream_t os;
os << std::forward<input_t>(arg);
return std::move(os).str();
}
else {
static_assert(!sizeof(input_t), "Unable to convert type to string.");
}
}
};

template <bool stream, typename input_t, typename string_t, typename streamer_t>
MEOJSON_INLINE string_t to_string(input_t&& arg, streamer_t&& streamer)
{
if constexpr (std::is_constructible_v<string_t, input_t>) {
return arg;
}
else if constexpr (stream) {
return streamer(std::forward<input_t>(arg));
}
else {
static_assert(!sizeof(input_t), "Unable to convert type to string.");
}
}
}

template <bool stream, typename any_t, typename string_t, typename streamer_t>
MEOJSON_INLINE basic_value<string_t> serialize(any_t&& arg, streamer_t&& streamer)
template <bool loose, typename any_t, typename string_t, typename string_converter_t>
MEOJSON_INLINE basic_value<string_t> serialize(any_t&& arg, string_converter_t&& string_converter)
{
using namespace _serialization_helper;
using namespace serialization_helper;

if constexpr (std::is_constructible_v<basic_value<string_t>, any_t>) {
return arg;
Expand All @@ -2615,7 +2611,7 @@ MEOJSON_INLINE basic_value<string_t> serialize(any_t&& arg, streamer_t&& streame
for (auto&& val : arg) {
using value_t = decltype(val);

result.emplace(serialize<stream, value_t, string_t>(std::forward<value_t>(val), streamer));
result.emplace(serialize<loose, value_t, string_t>(std::forward<value_t>(val), string_converter));
}
return result;
}
Expand All @@ -2625,13 +2621,13 @@ MEOJSON_INLINE basic_value<string_t> serialize(any_t&& arg, streamer_t&& streame
using key_t = decltype(key);
using value_t = decltype(val);

result.emplace(to_string<stream, key_t, string_t>(std::forward<key_t>(key), streamer),
serialize<stream, value_t, string_t>(std::forward<value_t>(val), streamer));
result.emplace(string_converter(std::forward<key_t>(key)),
serialize<loose, value_t, string_t>(std::forward<value_t>(val), string_converter));
}
return result;
}
else {
return to_string<stream, any_t, string_t>(std::forward<any_t>(arg), streamer);
return string_converter(std::forward<any_t>(arg));
}
}

Expand Down
2 changes: 1 addition & 1 deletion sample/sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ bool serializing()
{ "key2", { { 3, { 0.4 } }, { 4, { 0.5, 0.6, 0.7 } } } },
};
// the "std::map<int, xxx>" cannot be converted to json because the key is "int",
// you can set the template parameter "stream" of "serialize" to true, which will make a more relaxed conversion.
// you can set the template parameter "loose" of "serialize" to true, which will make a more relaxed conversion.
root["more_complex"] = json::serialize<true>(more_complex);

// for test
Expand Down

0 comments on commit 67a602a

Please sign in to comment.