From a19b94511b35748eb63872c305c16a9ec83868cb Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Mon, 3 Jun 2019 20:58:35 +0900 Subject: [PATCH 1/8] fix: add space between operator"" and _toml In C++11, it is required. --- toml/literal.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toml/literal.hpp b/toml/literal.hpp index 0e61cc9..fb47014 100644 --- a/toml/literal.hpp +++ b/toml/literal.hpp @@ -11,7 +11,7 @@ inline namespace literals inline namespace toml_literals { -inline ::toml::value operator""_toml(const char* str, std::size_t len) +inline ::toml::value operator"" _toml(const char* str, std::size_t len) { ::toml::detail::location> loc(/* filename = */ std::string("TOML literal encoded in a C++ code"), From 014d882f8fae659fc41511eb66699279d67bc55c Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 7 Jun 2019 00:06:14 +0900 Subject: [PATCH 2/8] feat: enable to find value by recursive search --- tests/test_get_related_func.cpp | 80 ++++++++++++++++++++++++++++++--- toml/get.hpp | 26 +++++++++++ 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/tests/test_get_related_func.cpp b/tests/test_get_related_func.cpp index 30eb362..e6e448c 100644 --- a/tests/test_get_related_func.cpp +++ b/tests/test_get_related_func.cpp @@ -12,8 +12,9 @@ #include #include -BOOST_AUTO_TEST_CASE(test_find) +BOOST_AUTO_TEST_CASE(test_find_for_value) { + // value itself is not a table { toml::value v(true); bool thrown = false; @@ -27,22 +28,87 @@ BOOST_AUTO_TEST_CASE(test_find) } BOOST_CHECK(thrown); } - + // the value corresponding to the key is not the expected type { - toml::table v{{"num", 42}}; - BOOST_CHECK_EQUAL(42, toml::find(v, "num")); - toml::find(v, "num") = 54; - BOOST_CHECK_EQUAL(54, toml::find(v, "num")); + toml::value v{{"key", 42}}; + bool thrown = false; + try + { + toml::find(v, "key"); + } + catch(toml::type_error const& te) + { + thrown = true; + } + BOOST_CHECK(thrown); } { toml::value v = toml::table{{"num", 42}}; BOOST_CHECK_EQUAL(42, toml::find(v, "num")); - toml::find(v, "num") = 54; + + // reference that can be used to modify the content + auto& num = toml::find(v, "num"); + num = 54; BOOST_CHECK_EQUAL(54, toml::find(v, "num")); } + + // recursively search tables + { + toml::value v = toml::table{ + {"a", toml::table{ + {"b", toml::table{ + {"c", toml::table{ + {"d", 42} + }} + }} + }} + }; + BOOST_CHECK_EQUAL(42, toml::find(v, "a", "b", "c", "d")); + + // reference that can be used to modify the content + auto& num = toml::find(v, "a", "b", "c", "d"); + num = 54; + BOOST_CHECK_EQUAL(54, toml::find(v, "a", "b", "c", "d")); + + const std::string a("a"), b("b"), c("c"), d("d"); + auto& num2 = toml::find(v, a, b, c, d); + num2 = 42; + BOOST_CHECK_EQUAL(42, toml::find(v, a, b, c, d)); + } } +BOOST_AUTO_TEST_CASE(test_find_for_table) +{ + // the value corresponding to the key is not the expected type + { + toml::table v{{"key", 42}}; + bool thrown = false; + try + { + toml::find(v, "key"); + } + catch(toml::type_error const& te) + { + thrown = true; + } + BOOST_CHECK(thrown); + } + + { + toml::table v{{"num", 42}}; + BOOST_CHECK_EQUAL(42, toml::find(v, "num")); + + // reference that can be used to modify the content + auto& num = toml::find(v, "num"); + num = 54; + BOOST_CHECK_EQUAL(54, toml::find(v, "num")); + } + + // recursive search is not provided for tables. +} + + BOOST_AUTO_TEST_CASE(test_get_or) { // requires conversion int -> uint diff --git a/toml/get.hpp b/toml/get.hpp index cf2cec4..326f2a9 100644 --- a/toml/get.hpp +++ b/toml/get.hpp @@ -430,6 +430,32 @@ find(toml::value&& v, const toml::key& ky) return ::toml::get(std::move(tab[ky])); } +// -------------------------------------------------------------------------- +// toml::find(toml::value, toml::key, Ts&& ... keys) +// +// Note: C++ draft N3337 (14.1.11) says that... +// > If a template-parameter of a class template or alias template has a default +// > template-argument, each subsequent template-parameter shall either have a +// > default template-argument supplied or be a template parameter pack. +// So the template parameter pack can appear after a default template argument. +template +decltype(::toml::get(std::declval())) +find(const ::toml::value& v, const ::toml::key& ky, Ts&& ... keys) +{ + return ::toml::find(::toml::find(v, ky), std::forward(keys)...); +} +template +decltype(::toml::get(std::declval<::toml::value&>())) +find(::toml::value& v, const ::toml::key& ky, Ts&& ... keys) +{ + return ::toml::find(::toml::find(v, ky), std::forward(keys)...); +} +template +decltype(::toml::get(std::declval<::toml::value&&>())) +find(::toml::value&& v, const ::toml::key& ky, Ts&& ... keys) +{ + return ::toml::find(::toml::find(std::move(v), ky), std::forward(keys)...); +} // ============================================================================ // get_or(value, fallback) From 62c993e096cd28e88264364152df6058ad703380 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 7 Jun 2019 00:10:12 +0900 Subject: [PATCH 3/8] feat: add as|is_floating and deprecate as|is_float to make the function names consistent with snake_case_typenames --- toml/value.hpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/toml/value.hpp b/toml/value.hpp index e42e6f5..280c71b 100644 --- a/toml/value.hpp +++ b/toml/value.hpp @@ -616,7 +616,7 @@ class value bool is_uninitialized() const noexcept {return this->is(value_t::Empty );} bool is_boolean() const noexcept {return this->is(value_t::Boolean );} bool is_integer() const noexcept {return this->is(value_t::Integer );} - bool is_float() const noexcept {return this->is(value_t::Float );} + bool is_floating() const noexcept {return this->is(value_t::Float );} bool is_string() const noexcept {return this->is(value_t::String );} bool is_offset_datetime() const noexcept {return this->is(value_t::OffsetDatetime);} bool is_local_datetime() const noexcept {return this->is(value_t::LocalDatetime );} @@ -636,7 +636,7 @@ class value boolean const& as_boolean() const& noexcept {return this->boolean_;} integer const& as_integer() const& noexcept {return this->integer_;} - floating const& as_float() const& noexcept {return this->floating_;} + floating const& as_floating() const& noexcept {return this->floating_;} string const& as_string() const& noexcept {return this->string_;} offset_datetime const& as_offset_datetime() const& noexcept {return this->offset_datetime_;} local_datetime const& as_local_datetime() const& noexcept {return this->local_datetime_;} @@ -647,7 +647,7 @@ class value boolean & as_boolean() & noexcept {return this->boolean_;} integer & as_integer() & noexcept {return this->integer_;} - floating & as_float() & noexcept {return this->floating_;} + floating & as_floating() & noexcept {return this->floating_;} string & as_string() & noexcept {return this->string_;} offset_datetime& as_offset_datetime() & noexcept {return this->offset_datetime_;} local_datetime & as_local_datetime() & noexcept {return this->local_datetime_;} @@ -658,7 +658,7 @@ class value boolean && as_boolean() && noexcept {return std::move(this->boolean_);} integer && as_integer() && noexcept {return std::move(this->integer_);} - floating && as_float() && noexcept {return std::move(this->floating_);} + floating && as_floating() && noexcept {return std::move(this->floating_);} string && as_string() && noexcept {return std::move(this->string_);} offset_datetime&& as_offset_datetime() && noexcept {return std::move(this->offset_datetime_);} local_datetime && as_local_datetime() && noexcept {return std::move(this->local_datetime_);} @@ -667,6 +667,15 @@ class value array && as_array() && noexcept {return std::move(this->array_.value());} table && as_table() && noexcept {return std::move(this->table_.value());} + TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating() instead.") + bool is_float() const noexcept {return this->is(value_t::Float);} + TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating() instead.") + floating& as_float() & noexcept {return this->floating_;} + TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating() instead.") + floating&& as_float() && noexcept {return std::move(this->floating_);} + TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating() instead.") + floating const& as_float() const& noexcept {return this->floating_;} + std::string comment() const { return this->region_info_->comment(); From 7db8388d1755d76ed493eef1c70cc78f0790fa08 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 7 Jun 2019 13:27:10 +0900 Subject: [PATCH 4/8] fix: avoid deprecated stuff in the internal code --- toml/value.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/toml/value.hpp b/toml/value.hpp index 280c71b..76b3d38 100644 --- a/toml/value.hpp +++ b/toml/value.hpp @@ -782,9 +782,9 @@ struct switch_cast template<> struct switch_cast { - static ::toml::floating& invoke(value& v) {return v.as_float();} - static ::toml::floating const& invoke(value const& v) {return v.as_float();} - static ::toml::floating&& invoke(value&& v) {return std::move(v).as_float();} + static ::toml::floating& invoke(value& v) {return v.as_floating();} + static ::toml::floating const& invoke(value const& v) {return v.as_floating();} + static ::toml::floating&& invoke(value&& v) {return std::move(v).as_floating();} }; template<> struct switch_cast @@ -880,7 +880,7 @@ inline bool operator==(const toml::value& lhs, const toml::value& rhs) } case value_t::Float : { - return lhs.as_float() == rhs.as_float(); + return lhs.as_floating() == rhs.as_floating(); } case value_t::String : { @@ -930,7 +930,7 @@ inline bool operator<(const toml::value& lhs, const toml::value& rhs) } case value_t::Float : { - return lhs.as_float() < rhs.as_float(); + return lhs.as_floating() < rhs.as_floating(); } case value_t::String : { @@ -1027,7 +1027,7 @@ visit(Visitor&& visitor, const toml::value& v) { case value_t::Boolean : {return visitor(v.as_boolean ());} case value_t::Integer : {return visitor(v.as_integer ());} - case value_t::Float : {return visitor(v.as_float ());} + case value_t::Float : {return visitor(v.as_floating ());} case value_t::String : {return visitor(v.as_string ());} case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());} case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());} @@ -1051,7 +1051,7 @@ visit(Visitor&& visitor, toml::value& v) { case value_t::Boolean : {return visitor(v.as_boolean ());} case value_t::Integer : {return visitor(v.as_integer ());} - case value_t::Float : {return visitor(v.as_float ());} + case value_t::Float : {return visitor(v.as_floating ());} case value_t::String : {return visitor(v.as_string ());} case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());} case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());} @@ -1075,7 +1075,7 @@ visit(Visitor&& visitor, toml::value&& v) { case value_t::Boolean : {return visitor(std::move(v.as_boolean ()));} case value_t::Integer : {return visitor(std::move(v.as_integer ()));} - case value_t::Float : {return visitor(std::move(v.as_float ()));} + case value_t::Float : {return visitor(std::move(v.as_floating ()));} case value_t::String : {return visitor(std::move(v.as_string ()));} case value_t::OffsetDatetime: {return visitor(std::move(v.as_offset_datetime()));} case value_t::LocalDatetime : {return visitor(std::move(v.as_local_datetime ()));} From 897aecf5d47d34da5c145c3e7757a030c9905b8c Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 7 Jun 2019 13:32:02 +0900 Subject: [PATCH 5/8] test: avoid deprecated functions in the test codes --- tests/test_literals.cpp | 4 ++-- tests/test_value.cpp | 42 ++++++++++++++++++++--------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/test_literals.cpp b/tests/test_literals.cpp index 2342a44..3323168 100644 --- a/tests/test_literals.cpp +++ b/tests/test_literals.cpp @@ -78,8 +78,8 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal) const toml::value v1 = u8"3.1415"_toml; const toml::value v2 = u8"6.02e+23"_toml; - BOOST_CHECK(v1.is_float()); - BOOST_CHECK(v2.is_float()); + BOOST_CHECK(v1.is_floating()); + BOOST_CHECK(v2.is_floating()); BOOST_CHECK_CLOSE(toml::get(v1), 3.1415, 0.00001); BOOST_CHECK_CLOSE(toml::get(v2), 6.02e23, 0.0001); } diff --git a/tests/test_value.cpp b/tests/test_value.cpp index 0471291..71f0083 100644 --- a/tests/test_value.cpp +++ b/tests/test_value.cpp @@ -96,12 +96,12 @@ BOOST_AUTO_TEST_CASE(test_value_boolean) BOOST_CHECK(v1.is()); BOOST_CHECK(v2.is()); BOOST_CHECK(v1.is_integer()); - BOOST_CHECK(v2.is_float()); + BOOST_CHECK(v2.is_floating()); BOOST_CHECK_EQUAL(v1.cast(), 42); BOOST_CHECK_EQUAL(v2.cast(), 3.14); BOOST_CHECK_EQUAL(v1.as_integer(), 42); - BOOST_CHECK_EQUAL(v2.as_float(), 3.14); + BOOST_CHECK_EQUAL(v2.as_floating(), 3.14); } BOOST_AUTO_TEST_CASE(test_value_integer) @@ -205,13 +205,13 @@ BOOST_AUTO_TEST_CASE(test_value_float) BOOST_CHECK(v2.is(toml::value_t::Float)); BOOST_CHECK(v1.is()); BOOST_CHECK(v2.is()); - BOOST_CHECK(v1.is_float()); - BOOST_CHECK(v2.is_float()); + BOOST_CHECK(v1.is_floating()); + BOOST_CHECK(v2.is_floating()); BOOST_CHECK_EQUAL (v1.cast(), 3.14); BOOST_CHECK_CLOSE_FRACTION(v2.cast(), 3.14, 1e-2); - BOOST_CHECK_EQUAL (v1.as_float(), 3.14); - BOOST_CHECK_CLOSE_FRACTION(v2.as_float(), 3.14, 1e-2); + BOOST_CHECK_EQUAL (v1.as_floating(), 3.14); + BOOST_CHECK_CLOSE_FRACTION(v2.as_floating(), 3.14, 1e-2); v1 = 2.718f; v2 = 2.718; @@ -222,13 +222,13 @@ BOOST_AUTO_TEST_CASE(test_value_float) BOOST_CHECK(v2.is(toml::value_t::Float)); BOOST_CHECK(v1.is()); BOOST_CHECK(v2.is()); - BOOST_CHECK(v1.is_float()); - BOOST_CHECK(v2.is_float()); + BOOST_CHECK(v1.is_floating()); + BOOST_CHECK(v2.is_floating()); BOOST_CHECK_CLOSE_FRACTION(v1.cast(), 2.718, 1e-3); BOOST_CHECK_EQUAL (v2.cast(), 2.718); - BOOST_CHECK_CLOSE_FRACTION(v1.as_float(), 2.718, 1e-3); - BOOST_CHECK_EQUAL (v2.as_float(), 2.718); + BOOST_CHECK_CLOSE_FRACTION(v1.as_floating(), 2.718, 1e-3); + BOOST_CHECK_EQUAL (v2.as_floating(), 2.718); toml::value v3(v1); toml::value v4(v2); @@ -241,13 +241,13 @@ BOOST_AUTO_TEST_CASE(test_value_float) BOOST_CHECK(v4.is(toml::value_t::Float)); BOOST_CHECK(v3.is()); BOOST_CHECK(v4.is()); - BOOST_CHECK(v3.is_float()); - BOOST_CHECK(v4.is_float()); + BOOST_CHECK(v3.is_floating()); + BOOST_CHECK(v4.is_floating()); BOOST_CHECK_CLOSE_FRACTION(v3.cast(), 2.718, 1e-3); BOOST_CHECK_EQUAL (v4.cast(), 2.718); - BOOST_CHECK_CLOSE_FRACTION(v3.as_float(), 2.718, 1e-3); - BOOST_CHECK_EQUAL (v4.as_float(), 2.718); + BOOST_CHECK_CLOSE_FRACTION(v3.as_floating(), 2.718, 1e-3); + BOOST_CHECK_EQUAL (v4.as_floating(), 2.718); toml::value v5(std::move(v1)); toml::value v6(std::move(v2)); @@ -258,13 +258,13 @@ BOOST_AUTO_TEST_CASE(test_value_float) BOOST_CHECK(v6.is(toml::value_t::Float)); BOOST_CHECK(v5.is()); BOOST_CHECK(v6.is()); - BOOST_CHECK(v5.is_float()); - BOOST_CHECK(v6.is_float()); + BOOST_CHECK(v5.is_floating()); + BOOST_CHECK(v6.is_floating()); BOOST_CHECK_CLOSE_FRACTION(v5.cast(), 2.718, 1e-3); BOOST_CHECK_EQUAL (v6.cast(), 2.718); - BOOST_CHECK_CLOSE_FRACTION(v5.as_float(), 2.718, 1e-3); - BOOST_CHECK_EQUAL (v6.as_float(), 2.718); + BOOST_CHECK_CLOSE_FRACTION(v5.as_floating(), 2.718, 1e-3); + BOOST_CHECK_EQUAL (v6.as_floating(), 2.718); v1 = true; v2 = false; @@ -792,7 +792,7 @@ BOOST_AUTO_TEST_CASE(test_value_table) BOOST_CHECK_EQUAL(v1.cast().at("bar").cast(), 3.14); BOOST_CHECK_EQUAL(v1.cast().at("baz").cast().str, "qux"); BOOST_CHECK_EQUAL(v1.as_table().at("foo").as_integer(), 42); - BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_float(), 3.14); + BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_floating(), 3.14); BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "qux"); @@ -806,7 +806,7 @@ BOOST_AUTO_TEST_CASE(test_value_table) BOOST_CHECK_EQUAL(v1.cast().at("foo").cast(), 2.71); BOOST_CHECK_EQUAL(v1.cast().at("bar").cast(), 54); BOOST_CHECK_EQUAL(v1.cast().at("baz").cast().str, "quux"); - BOOST_CHECK_EQUAL(v1.as_table().at("foo").as_float(), 2.71); + BOOST_CHECK_EQUAL(v1.as_table().at("foo").as_floating(), 2.71); BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_integer(), 54); BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "quux"); @@ -822,7 +822,7 @@ BOOST_AUTO_TEST_CASE(test_value_table) BOOST_CHECK_EQUAL(v3.cast().at("foo").cast(), 2.71); BOOST_CHECK_EQUAL(v3.cast().at("bar").cast(), 54); BOOST_CHECK_EQUAL(v3.cast().at("baz").cast().str, "quux"); - BOOST_CHECK_EQUAL(v3.as_table().at("foo").as_float(), 2.71); + BOOST_CHECK_EQUAL(v3.as_table().at("foo").as_floating(), 2.71); BOOST_CHECK_EQUAL(v3.as_table().at("bar").as_integer(), 54); BOOST_CHECK_EQUAL(v3.as_table().at("baz").as_string().str, "quux"); From 46047c48bf326dd2ac4f67c408b5b5396699c7a6 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 7 Jun 2019 13:40:21 +0900 Subject: [PATCH 6/8] doc: add note about is|as_float to README --- README.md | 68 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index ee982db..d96c15a 100644 --- a/README.md +++ b/README.md @@ -516,20 +516,27 @@ if(v.is_integer()) The complete list of the functions is below. ```cpp -const toml::value v(/*...*/); -v.is_boolean(); -v.is_integer(); -v.is_float(); -v.is_string(); -v.is_offset_datetime(); -v.is_local_datetime(); -v.is_local_date(); -v.is_local_time(); -v.is_array(); -v.is_table(); -v.is_uninitialized(); +namespace toml { +class value { + // ... + bool is_boolean() const noexcept; + bool is_integer() const noexcept; + bool is_floating() const noexcept; + bool is_string() const noexcept; + bool is_offset_datetime() const noexcept; + bool is_local_datetime() const noexcept; + bool is_local_date() const noexcept; + bool is_local_time() const noexcept; + bool is_array() const noexcept; + bool is_table() const noexcept; + bool is_uninitialized() const noexcept; + // ... +}; +} // toml ``` +__NOTE__: `is_float` is marked as deprecated since v2.4.0 to make the function names consistent with snake case typenames. Please use `is_floating` instead. + Also, you can get `enum class` value from `toml::value`. ```cpp @@ -569,20 +576,33 @@ if(v.is_integer() && v.as_integer() == 42) The complete list of the functions is below. ```cpp -const toml::value v(/*...*/); -v.as_boolean(); -v.as_integer(); -v.as_float(); -v.as_string(); -v.as_offset_datetime(); -v.as_local_datetime(); -v.as_local_date(); -v.as_local_time(); -v.as_array(); -v.as_table(); -v.as_uninitialized(); +namespace toml { +class value { + // ... + const boolean& as_boolean() const& noexcept; + const integer& as_integer() const& noexcept; + const floating& as_floating() const& noexcept; + const string& as_string() const& noexcept; + const offset_datetime& as_offset_datetime() const& noexcept; + const local_datetime& as_local_datetime() const& noexcept; + const local_date& as_local_date() const& noexcept; + const local_time& as_local_time() const& noexcept; + const array& as_array() const& noexcept; + const table& as_table() const& noexcept; + // -------------------------------------------------------- + // non-const version + boolean& as_boolean() & noexcept; + // ditto... + // -------------------------------------------------------- + // rvalue version + boolean&& as_boolean() && noexcept; + // ditto... +}; +} // toml ``` +__NOTE__: `as_float` is marked as deprecated since v2.4.0 to make the function names consistent with snake case typenames. Please use `as_floating` instead. + ## Visiting a toml::value toml11 provides `toml::visit` to apply a function to `toml::value` in the From 2afa0ff0c32e4367a54caca429ab54e0151778d0 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 7 Jun 2019 19:01:46 +0900 Subject: [PATCH 7/8] doc: add find(value, key1, key2, ...) to README --- README.md | 90 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index ee982db..5f55a15 100644 --- a/README.md +++ b/README.md @@ -451,36 +451,58 @@ const auto value = toml::expect(data.at("number")) ## Finding a value from a table -toml11 provides utility function to find a value from `toml::table`. -Of course, you can do this in your own way with `toml::get` because -it just searches an `unordered_map` and returns a value if it exists. +toml11 provides utility function to find a value from `toml::value` and `toml::table`. ```cpp const auto data = toml::parse("example.toml"); -const auto num = toml::find(data, "num", /*for err msg*/"example.toml"); +// find a value named "num" from `data`. +const auto num = toml::find(data, "num"); ``` If the value does not exist, it throws `std::out_of_range` with an error message. +But, since `toml::table` is just an alias of `std::unordered_map`, +you need to pass a name to the function to show the name in the exception. + +```cpp +const auto num = toml::find(data, "num", "example.toml"); +``` ```console terminate called after throwing an instance of 'std::out_of_range' what(): [error] key "num" not found in example.toml +# ^^^^^^^^^^^^ this part ``` -You can use this with a `toml::value` that is expected to be a `toml::table`. -It automatically casts the value to table. +Of course, you can do this in your own way with `toml::get` because +it just searches an `unordered_map` and returns a value if it exists. ```cpp -const auto data = toml::parse("example.toml"); -const auto num = toml::find(data.at("table"), "num"); -// expecting the following example.toml -// [table] -// num = 42 +const toml::table data = toml::parse("example.toml"); +if(data.count("num") == 1) +{ + const auto num = toml::get(data.at("num")); + // more stuff ... +} ``` -In this case, because the value `data.at("table")` knows the locatoin of itself, -you don't need to pass where you find the value. -`toml::find` will show you an error message including table location. +---- + +You can also use this with a `toml::value` that is expected to be a `toml::table`. +It automatically casts the `toml::value` to a `toml::table`. If it failed to cast, +it would throw a `toml::type_error`. + +```cpp +// # expecting the following example.toml +// [table] +// num = 42 +const toml::table data = toml::parse("example.toml"); +const toml::value table = data.at("table"); +const auto num = toml::find(table, "num"); +``` + +In this case, because the `toml::value table` knows the locatoin of itself, +you don't need to pass the name to show it in an error message. +`toml::find` will automatically format an error message with the location of the table. ```console terminate called after throwing an instance of 'std::out_of_range' @@ -490,7 +512,45 @@ terminate called after throwing an instance of 'std::out_of_range' | ~~~~~~~ in this table ``` -If it's not a `toml::table`, the same error as "invalid type" would be thrown. +The default return value of the `toml::find` is a `toml::value`. + +```cpp +const toml::value& subtable = toml::find(table, "subtable"); +``` + +There are several ways to find a value buried in a deep recursion of tables. + +First, you can call `toml::find` as many as you need. + +```cpp +// # expecting the following example.toml +// answer.to.the.ultimate.question = 42 +// # is equivalent to {"answer": {"to":{"the":{"ultimate:{"question":42}}}}} + +const toml::table data = toml::parse("example.toml"); +const int a = toml::find(toml::find(toml::find(toml::find(toml::find( + data, "answer"), "to"), "the"), "ultimate"), "question"); +``` + +But it is a bother. + +After toml11 v2.4.0, you can pass a `toml::value` and as many number of keys as you want. + +```cpp +const toml::table data = toml::parse("example.toml"); +const int a = toml::find(data.at("answer"), "to", "the", "ultimate", "question"); +``` + +__NOTE__: +Currently, this function does not support `toml::table` because of some +technical reason. Please make sure that the type of the first argument is +`toml::value`. The main reason is that the `toml::table` may take an additional string +as the third argumnet to show its location in an error message. And the +most confusing part is that `toml::parse` returns `toml::table`, not a +`toml::value`. This confusing API will hopefully be resolved in the next +major update, v3 (it will contain some unavoidable breaking changes). + +---- There is another utility function, `toml::find_or`. It is almost same as `toml::find`, but returns a default value if the value is From 2d43119ac7ac455630b5a4ef678c240ede513f2b Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 7 Jun 2019 21:05:33 +0900 Subject: [PATCH 8/8] doc: change README a bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c3f4bc..ddb93eb 100644 --- a/README.md +++ b/README.md @@ -487,7 +487,7 @@ if(data.count("num") == 1) ---- -You can also use this with a `toml::value` that is expected to be a `toml::table`. +You can also use this with a `toml::value` that is expected to contain a `toml::table`. It automatically casts the `toml::value` to a `toml::table`. If it failed to cast, it would throw a `toml::type_error`.