Skip to content

Commit

Permalink
adaptor api change to() -> into()
Browse files Browse the repository at this point in the history
serdepp serializer optimization
now TAG macro function support TAG_OR
TAG_OR macro deprecated
  • Loading branch information
injae committed Feb 5, 2021
1 parent 0b74180 commit e86970e
Show file tree
Hide file tree
Showing 17 changed files with 450 additions and 192 deletions.
14 changes: 12 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set(CPPM_VERSION 0.0.13)
include(cmake/cppm_loader.cmake)
cppm_project()

project(serdepp VERSION 0.0.1 LANGUAGES C CXX)
project(serdepp VERSION 0.0.2 LANGUAGES C CXX)
cppm_setting()
cppm_cxx_standard(17)
cppm_compiler_option(DEFAULT)
Expand All @@ -14,6 +14,7 @@ find_cppkg(nlohmann_json 3.9.1 MODULE nlohmann_json::nlohmann_json TYPE lib OPT
find_cppkg(toml11 3.6.0 MODULE toml11::toml11 TYPE lib OPTIONAL OFF)

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
find_cppkg(benchmark 1.5.2 MODULE benchmark::benchmark TYPE lib OPTIONAL OFF)
find_cppkg(yaml-cpp 0.6.3 MODULE yaml-cpp TYPE lib OPTIONAL OFF)
endif()

Expand Down Expand Up @@ -51,12 +52,17 @@ SOURCES
examples/overwrite.cpp
)

cppm_target_define(benchmark BINARY
SOURCES
benchmark/benchmark.cpp
)

endif()


set(serdepp_global_deps PUBLIC fmt nlohmann_json toml11)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
list(APPEND serdepp_global_deps PUBLIC yaml-cpp)
list(APPEND serdepp_global_deps PUBLIC benchmark yaml-cpp)
endif()
cppm_target_dependencies(serdepp
${serdepp_global_deps})
Expand All @@ -81,6 +87,10 @@ cppm_target_dependencies(overwrite
${serdepp_global_deps}
serdepp)

cppm_target_dependencies(benchmark
${serdepp_global_deps}
serdepp)


cppm_target_install(serdepp)

76 changes: 70 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
> You can easily add various formats.
## Dependencies
- fmt (optional) (Alpha)
- nlohmann_json (optional)
- toml11 (optional)
- fmt
- nlohmann_json (optional) (CMAKE FLAG: -DSERDEPP_USE_NLOHMANN_JSON=ON)
- toml11 (optional) (CMAKE FLAG: -DSERDEPP_USE_TOML11=ON)

# Examples

Expand Down Expand Up @@ -106,6 +106,24 @@ private:
};
```

## Type Converter
```
// example class
class Test {
void from_string(const std::string& str);
void to_string(const std::string& str);
};
// serde serialize (std::string -> Test) deserialize (Test -> std::string)
template<> struct serializer<Test> : serializer_convertor<Test, std::string> {
using FROM = Test;
using INTO = std::string;
static void from(FROM& from_, INTO& into_) { from_.from_string(into_); }
static void into(INTO& into_, FROM& from_) { into_ = from_.to_string(); }
};
```

## toml11 Example
```cpp
#include "define.h"
Expand All @@ -126,8 +144,7 @@ int main(int argc, char* argv[]) {
auto t = toml::parse(stream);
fmt::print("{}\n",t);
auto xx = serde::serialize_element<ttt>(t, "ttt");

auto yy = serde::deserialize_with_name<toml::value>(xx, "ttt");
auto yy = serde::deserialize_with_name<toml::value>(xx, "ttt");
std::cout << yy << std::endl;

return 0;
Expand Down Expand Up @@ -257,6 +274,53 @@ int main(int argc, char* argv[]) {
toml::value yy = serde::deserialize_with_name<toml::value>(xx, "ttt");
std::cout << yy << std::endl;

return 0;

}
```
## Benchmark
serdepp's serializer vs nlohmann_json's serialer
```
struct TestStruct {
derive_serde(TestStruct, ctx.TAG(str).TAG(i).TAG(vec);)
std::optional<std::string> str;
int i;
std::vector<std::string> vec;
};

namespace ns {
struct TestStruct2 {
std::string str;
int i;
std::vector<std::string> vec;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(TestStruct2, str, i, vec)
};
}
```
```console
2021-02-06T04:16:41+09:00
Running ./benchmark
Run on (12 X 2600 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x6)
L1 Instruction 32 KiB (x6)
L2 Unified 256 KiB (x6)
L3 Unified 12288 KiB (x1)
Load Average: 2.20, 2.20, 2.23
-------------------------------------------------------------------------------
Benchmark Time CPU Iterations
-------------------------------------------------------------------------------
serialize_struct_serde_nlohmann_json 255 ns 254 ns 2784906
serialize_struct_nlohmann_json 169 ns 168 ns 4616775
deserialize_serde_nlohmann_json 1848 ns 1842 ns 424721
deserialize_nlohmann_json 1916 ns 1910 ns 407055
serialize_int_serde_nlohmann_json 3.40 ns 3.38 ns 251813054
serialize_int_nlohmann_json 3.05 ns 3.04 ns 252797931
deserialize_int_serde_nlohmann_json 7.41 ns 7.39 ns 105844107
deserialize_int_nlohmann_json 322 ns 321 ns 2406284
serialize_vec_serde_nlohmann_json 103 ns 102 ns 7604150
serialize_vec_nlohmann_json 114 ns 113 ns 6926373
deserialize_vec_serde_nlohmann_json 997 ns 995 ns 797912
deserialize_vec_nlohmann_json 1122 ns 1119 ns 713405
```


128 changes: 128 additions & 0 deletions benchmark/benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include <benchmark/benchmark.h>
#include <serdepp/adaptor/nlohmann_json.hpp>
#include <serdepp/utility.hpp>
#include <nlohmann/json.hpp>
#include <string>

struct TestStruct {
derive_serde(TestStruct, ctx.TAG(str).TAG(i).TAG(vec);)
std::optional<std::string> str;
int i;
std::vector<std::string> vec;
};

namespace ns {
struct TestStruct2 {
std::string str;
int i;
std::vector<std::string> vec;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(TestStruct2, str, i, vec)
};
}

static void serialize_struct_serde_nlohmann_json(benchmark::State& state) {
using namespace serde;
nlohmann::json test_json = R"({"str":"hello", "i": 10, "vec": [ "one", "two" ]})"_json;
for(auto _ : state) {
auto _v = serde::serialize<TestStruct>(test_json);
}
}

static void serialize_struct_nlohmann_json(benchmark::State& state) {
nlohmann::json test_json = R"({"str":"hello", "i": 10, "vec": [ "one", "two" ]})"_json;
for(auto _ : state) {
auto _v = test_json.get<ns::TestStruct2>();
}
}

static void deserialize_serde_nlohmann_json(benchmark::State& state) {
nlohmann::json test_json = R"({"str":"hello", "i": 10, "vec": [ "one", "two" ]})"_json;
auto value = serde::serialize<TestStruct>(test_json);
for(auto _ : state) {
auto _v = serde::deserialize<nlohmann::json>(value);
}
}

static void deserialize_nlohmann_json(benchmark::State& state) {
nlohmann::json test_json = R"({"str":"hello", "i": 10, "vec": [ "one", "two" ]})"_json;
auto value = test_json.get<ns::TestStruct2>();
for(auto _ : state) {
auto _v = nlohmann::json{value};
}
}


static void serialize_int_serde_nlohmann_json(benchmark::State& state) {
using namespace serde;
nlohmann::json test_type_json = 10;
for(auto _ : state) {
auto _v = serde::serialize<int>(test_type_json);
}
}

static void serialize_int_nlohmann_json(benchmark::State& state) {
nlohmann::json test_type_json = 10;
for(auto _ : state) {
auto _v = test_type_json.get<int>();
}
}

static void deserialize_int_serde_nlohmann_json(benchmark::State& state) {
using namespace serde;
int value = 1000;
for(auto _ : state) {
auto _v = serde::deserialize<nlohmann::json>(value);
}
}

static void deserialize_int_nlohmann_json(benchmark::State& state) {
int value = 1000;
for(auto _ : state) {
auto _v = nlohmann::json{value};
}
}

nlohmann::json test_vec_json = { 10, 11, 12, 13 };

static void serialize_vec_serde_nlohmann_json(benchmark::State& state) {
using namespace serde;
for(auto _ : state) {
auto _v = serde::serialize<std::vector<int>>(test_vec_json);
}
}

static void serialize_vec_nlohmann_json(benchmark::State& state) {
for(auto _ : state) {
auto _v = test_vec_json.get<std::vector<int>>();
}
}

static void deserialize_vec_serde_nlohmann_json(benchmark::State& state) {
using namespace serde;
std::vector<int> value = { 1, 2, 3, 4, 5};
for(auto _ : state) {
auto _v = serde::deserialize<nlohmann::json>(value);
}
}

static void deserialize_vec_nlohmann_json(benchmark::State& state) {
std::vector<int> value = { 1, 2, 3, 4, 5};
for(auto _ : state) {
auto _v = nlohmann::json{value};
}
}

BENCHMARK(serialize_struct_serde_nlohmann_json);
BENCHMARK(serialize_struct_nlohmann_json);
BENCHMARK(deserialize_serde_nlohmann_json);
BENCHMARK(deserialize_nlohmann_json);
BENCHMARK(serialize_int_serde_nlohmann_json);
BENCHMARK(serialize_int_nlohmann_json);
BENCHMARK(deserialize_int_serde_nlohmann_json);
BENCHMARK(deserialize_int_nlohmann_json);
BENCHMARK(serialize_vec_serde_nlohmann_json);
BENCHMARK(serialize_vec_nlohmann_json);
BENCHMARK(deserialize_vec_serde_nlohmann_json);
BENCHMARK(deserialize_vec_nlohmann_json);

BENCHMARK_MAIN();
13 changes: 7 additions & 6 deletions cppm.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
[package]
name = "serdepp"
version = "0.0.1"
version = "0.0.2"
description = "c++ universal serialize deserialize library like rust serde"

#[lib]
# name = "serdepp"
# type = "header-only"
[lib]
name = "serdepp"
type = "static"
source= ["src/to_static.cpp"]


[[example]]
name = "nlohmann_json_example"
source = ["examples/nlohmann_json_example.cpp"]
Expand All @@ -32,6 +28,10 @@
name = "overwrite"
source = ["examples/overwrite.cpp"]

[[example]]
name = "benchmark"
source = ["benchmark/benchmark.cpp"]

#[[bin]]
# name = "yaml-cpp_example"
# source = ["examples/yaml-cpp_example.cpp"]
Expand All @@ -40,12 +40,13 @@
# name = "tomlpp_example"
# source = ["examples/tomlpp_example.cpp"]


[dependencies]
fmt = "7.1.3"
toml11= {version="3.6.0", optional=true}
nlohmann_json= {version="3.9.1", optional=true}
#benchmark="1.5.2"

[dev-dependencies]
# tomlpp="git"
yaml-cpp= {version="0.6.3", optional=true}
benchmark={version="1.5.2", optional=true}
6 changes: 2 additions & 4 deletions include/serdepp/adaptor/fmt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,12 @@ namespace serde {

template<typename T> struct serde_adaptor<literal, T, type::struct_t> {
static void from(literal& s, const std::string& key, T& data) { /*unimplemented*/ }
static void to(literal& s, const std::string& key, T& data) { s.add_child(key, deserialize<literal>(data)); }
static void into(literal& s, const std::string& key, T& data) { s.add_child(key, deserialize<literal>(data)); }
};

template<typename T, typename U> struct serde_adaptor<literal, T, U> {
static void from(literal& s, const std::string& key, T& data){ /*unimplemented*/ }
static void to(literal& s, const std::string& key, T& data) { s.add_child(key,data); }
static void from(literal& s, T& data){ /*unimplemented*/ }
static void to(literal& s, T& data) { s.add_child("", data); }
static void into(literal& s, const std::string& key, T& data) { s.add_child(key,data); }
};
}

Expand Down
25 changes: 14 additions & 11 deletions include/serdepp/adaptor/nlohmann_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,46 @@ namespace serde {
};

template<typename T> struct serde_adaptor<json, T, type::struct_t> {
static auto from(json& s, const std::string& key, T& data) { serialize_to<T>(s[key], data, key);}
static void to(json &s, const std::string& key, T& data) { s[key] = deserialize<json>(data, key); }
static void from(json& s, const std::string& key, T& data) { serialize_to<T>(s[key], data, key);}
static void into(json& s, const std::string& key, T& data) { s[key] = deserialize<json>(data, key); }
};


template<typename T> struct serde_adaptor<json, T> {
static auto from(json& s, const std::string& key, T& data) {
static void from(json& s, const std::string& key, T& data) {
data = key.empty() ? s.get<T>() : s[key].template get<T>();
}
static void to(json& s, const std::string& key, T& data) { (key.empty() ? s : s[key]) = data; }
static void into(json& s, const std::string& key, T& data) { (key.empty() ? s : s[key]) = data; }
};

template<typename T> struct serde_adaptor<json, T, type::seq> {
using E = meta::is_sequence_e<T>;
static auto from(json& s, const std::string& key, T& arr) {
auto table = key.empty() ? s : s[key];
static void from(json& s, const std::string& key, T& arr) {
auto& table = key.empty() ? s : s[key];
arr.reserve(table.size());
for(auto& value: table) { arr.push_back(serialize<E>(value, key)); }
}
static void to(json& s, const std::string& key, T& data) {
static void into(json& s, const std::string& key, T& data) {
json arr;
for(auto& value: data) { arr.push_back(deserialize<json>(value, key)); }
(key.empty() ? s : s[key]) = arr;
(key.empty() ? s : s[key]) = std::move(arr);
}
};

template <typename Map> struct serde_adaptor<json, Map, type::map> {
using T = meta::is_map_e<Map>;
static void from(json& s, const std::string &key, Map& map) {
auto table = key.empty() ? s : s[key];
auto& table = key.empty() ? s : s[key];
for(auto&[key_, value_] : table.items()) { map[key] = serialize<T>(value_, key_); }
}
static void to(json &s, const std::string& key, Map& data) {
static void into(json &s, const std::string& key, Map& data) {
json map;
for(auto& [key_, value] : data) { map[key_] = deserialize<json>(value, key_); }
(key.empty() ? s : s[key]) = map;
}
};
}

// You should use void as a second template argument
// if you don't need compile-time checks on T
#endif
// strt_serde -> tag_to -> strt_serde -> tag_to -> ... -> adaptor_to -> adaptor_to
Loading

0 comments on commit e86970e

Please sign in to comment.