From 1b2b422ea13b0e746055c304f8d92759e267a365 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Thu, 20 Apr 2017 12:49:36 +0900 Subject: [PATCH] add from_toml and get function --- tests/CMakeLists.txt | 1 + tests/test_from_toml.cpp | 129 +++++++++++++++++++++++++++++++++++++++ toml/toml.hpp | 99 ++++++++++++++++++++++++++++-- 3 files changed, 223 insertions(+), 6 deletions(-) create mode 100644 tests/test_from_toml.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2007a58..d0f32d7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,7 @@ set(TEST_NAMES test_traits test_value test_to_toml + test_from_toml ) add_definitions("-Wall -Wpedantic") diff --git a/tests/test_from_toml.cpp b/tests/test_from_toml.cpp new file mode 100644 index 0000000..b5323f6 --- /dev/null +++ b/tests/test_from_toml.cpp @@ -0,0 +1,129 @@ +#define BOOST_TEST_MODULE "test_from_toml" +#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST +#include +#else +#define BOOST_TEST_NO_LIB +#include +#endif +#include +#include +#include +#include +#include + +BOOST_AUTO_TEST_CASE(test_from_toml_exact) +{ + toml::Boolean b(true); + toml::Integer i(42); + toml::Float f(3.14); + toml::String s("hoge"); + toml::Datetime d(std::chrono::system_clock::now()); + toml::Array a; + a.emplace_back(2); + a.emplace_back(7); + a.emplace_back(1); + a.emplace_back(8); + a.emplace_back(2); + toml::Table t; + t.emplace("val1", true); + t.emplace("val2", 42); + t.emplace("val3", 3.14); + t.emplace("val4", "piyo"); + + toml::value v1(b); + toml::value v2(i); + toml::value v3(f); + toml::value v4(s); + toml::value v5(d); + toml::value v6(a); + toml::value v7(t); + + toml::Boolean u1; + toml::Integer u2; + toml::Float u3; + toml::String u4; + toml::Datetime u5; + toml::Array u6; + toml::Table u7; + + toml::from_toml(u1, v1); + toml::from_toml(u2, v2); + toml::from_toml(u3, v3); + toml::from_toml(u4, v4); + toml::from_toml(u5, v5); + toml::from_toml(u6, v6); + toml::from_toml(u7, v7); + + BOOST_CHECK_EQUAL(u1, b); + BOOST_CHECK_EQUAL(u2, i); + BOOST_CHECK_EQUAL(u3, f); + BOOST_CHECK_EQUAL(u4, s); + BOOST_CHECK_EQUAL(u6.at(0).cast(), a.at(0).cast()); + BOOST_CHECK_EQUAL(u6.at(1).cast(), a.at(1).cast()); + BOOST_CHECK_EQUAL(u6.at(2).cast(), a.at(2).cast()); + BOOST_CHECK_EQUAL(u6.at(3).cast(), a.at(3).cast()); + BOOST_CHECK_EQUAL(u6.at(4).cast(), a.at(4).cast()); +} + +BOOST_AUTO_TEST_CASE(test_from_toml_cast) +{ + toml::Integer i(42); + toml::Float f(3.14); + toml::Array a; + a.emplace_back(2); + a.emplace_back(7); + a.emplace_back(1); + a.emplace_back(8); + a.emplace_back(2); + toml::Table t; + t.emplace("val1", true); + t.emplace("val2", 42); + t.emplace("val3", 3.14); + t.emplace("val4", "piyo"); + + toml::value vi(i); + toml::value vf(f); + toml::value va(a); + toml::value vt(t); + + int u1; + std::size_t u2; + float u3; + std::list u4; + std::deque u5; + std::map u6; + + std::list expect_list; + expect_list.push_back(2); + expect_list.push_back(7); + expect_list.push_back(1); + expect_list.push_back(8); + expect_list.push_back(2); + + toml::from_toml(u1, vi); + toml::from_toml(u2, vi); + toml::from_toml(u3, vf); + toml::from_toml(u4, va); + toml::from_toml(u5, va); + toml::from_toml(u6, vt); + + BOOST_CHECK_EQUAL(u1, 42); + BOOST_CHECK_EQUAL(u2, 42ul); + BOOST_CHECK_CLOSE_FRACTION(u3, 3.14, 1e-3); + + bool same_list = (u4 == expect_list); + BOOST_CHECK(same_list); + + BOOST_CHECK_EQUAL(u5.at(0), 2); + BOOST_CHECK_EQUAL(u5.at(1), 7); + BOOST_CHECK_EQUAL(u5.at(2), 1); + BOOST_CHECK_EQUAL(u5.at(3), 8); + BOOST_CHECK_EQUAL(u5.at(4), 2); + + BOOST_CHECK_EQUAL(u6["val1"].cast(), true); + BOOST_CHECK_EQUAL(u6["val2"].cast(), 42); + BOOST_CHECK_CLOSE_FRACTION(u6["val3"].cast(), 3.14, 1e-3); + BOOST_CHECK_EQUAL(u6["val4"].cast(), "piyo"); + +} + diff --git a/toml/toml.hpp b/toml/toml.hpp index 229383f..d991f09 100644 --- a/toml/toml.hpp +++ b/toml/toml.hpp @@ -82,7 +82,7 @@ operator<<(std::basic_ostream& os, value_t t) } } -template, +template, typename alloc = std::allocator> inline std::basic_string stringize(value_t t) @@ -735,8 +735,8 @@ inline typename detail::toml_default_type::type const& value::cast() const { if(T != this->type_) - throw type_error("current type: " + stringize(this->type_) + - std::string(" is not query type: ") + stringize(T)); + throw type_error("current type: " + stringize(this->type_) + + std::string(" is not query type: ") + stringize(T)); return switch_cast::invoke(*this); } template @@ -744,12 +744,12 @@ inline typename detail::toml_default_type::type& value::cast() { if(T != this->type_) - throw type_error("current type: " + stringize(this->type_) + - std::string(" is not query type: ") + stringize(T)); + throw type_error("current type: " + stringize(this->type_) + + std::string(" is not query type: ") + stringize(T)); return switch_cast::invoke(*this); } -/* -------------------------------------------------------------------------- */ +/* ------------------------------- to_toml ---------------------------------- */ template(), typename std::enable_if<(vT != toml::value_t::Unknown && @@ -794,5 +794,92 @@ to_toml(std::initializer_list> init) return toml::value(std::move(init)); } +/* ------------------------------ from_toml --------------------------------- */ + +template(), + typename std::enable_if<(vT != toml::value_t::Unknown && + vT != value_t::Empty), std::nullptr_t>::type = nullptr> +void from_toml(T& x, const toml::value& v) +{ + if(v.type() != vT) + throw type_error("from_toml: value type: " + stringize(v.type()) + + std::string(" is not type of arguemnt: ") + stringize(vT)); + x = v.cast(); + return; +} + +template(), + typename std::enable_if<(vT == toml::value_t::Unknown) && + (!toml::detail::is_map::value) && + toml::detail::is_container::value, std::nullptr_t>::type = nullptr> +void from_toml(T& x, const toml::value& v) +{ + // TODO the case of x is not dynamic container case + if(v.type() != value_t::Array) + throw type_error("from_toml: value type: " + stringize(v.type()) + + std::string(" is not type of argument type Array")); + const auto& ar = v.cast(); + for(const auto& val : ar) + { + typename T::value_type v; + from_toml(v, val); + x.push_back(std::move(v)); + } + return; +} + +template(), + typename std::enable_if<(vT == toml::value_t::Unknown) && + toml::detail::is_map::value, std::nullptr_t>::type = nullptr> +void from_toml(T& x, const toml::value& v) +{ + if(v.type() != value_t::Table) + throw type_error("from_toml: value type: " + stringize(v.type()) + + std::string(" is not type of argument type Table")); + x.clear(); + const auto& tb = v.cast(); + for(const auto& kv : tb) + { + x.insert(kv); + } + return; +} + +template(), + typename std::enable_if<(vT != toml::value_t::Unknown && + vT != value_t::Empty), std::nullptr_t>::type = nullptr> +inline T get(const toml::value& v) +{ + return static_cast(v.cast()); +} + +template(), + typename std::enable_if<(vT == toml::value_t::Unknown) && + (!toml::detail::is_map::value) && + toml::detail::is_container::value, std::nullptr_t>::type = nullptr> +T get(const toml::value& v) +{ + if(v.type() != value_t::Array) + throw type_error("from_toml: value type: " + stringize(v.type()) + + std::string(" is not type of argument type Array")); + T tmp; + from_toml(tmp, v); + return tmp; +} + +template(), + typename std::enable_if<(vT == toml::value_t::Unknown) && + toml::detail::is_map::value, std::nullptr_t>::type = nullptr> +T get(const toml::value& v) +{ + if(v.type() != value_t::Table) + throw type_error("from_toml: value type: " + stringize(v.type()) + + std::string(" is not type of argument type Table")); + T tmp; + from_toml(tmp, v); + return tmp; +} + + }// toml #endif// TOML_FOR_MODERN_CPP