mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-09-17 09:08:08 +08:00
Merge branch 'master' of github.com:ToruNiina/toml11
This commit is contained in:
30
README.md
30
README.md
@@ -274,10 +274,31 @@ const auto color = toml::find<std::string>(data, "fruit", "physical", "color");
|
|||||||
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Finding a value in an array
|
||||||
|
|
||||||
|
You can find n-th value in an array by `toml::find`.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
values = ["foo", "bar", "baz"]
|
||||||
|
```
|
||||||
|
|
||||||
|
``` cpp
|
||||||
|
const auto data = toml::parse("sample.toml");
|
||||||
|
const auto values = toml::find(data, "values");
|
||||||
|
const auto bar = toml::find<std::string>(values, 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
`toml::find` can also search array recursively.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
const auto bar = toml::find<std::string>(data, "values", 1);
|
||||||
|
```
|
||||||
|
|
||||||
### In case of error
|
### In case of error
|
||||||
|
|
||||||
If the value does not exist, `toml::find` throws an error with the location of
|
If the value does not exist, `toml::find` throws `std::out_of_range` with the
|
||||||
the table.
|
location of the table.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
terminate called after throwing an instance of 'std::out_of_range'
|
terminate called after throwing an instance of 'std::out_of_range'
|
||||||
@@ -287,11 +308,6 @@ terminate called after throwing an instance of 'std::out_of_range'
|
|||||||
| ~~~~~ in this table
|
| ~~~~~ in this table
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: It is recommended to find a table as `toml::value` because it has much information
|
|
||||||
compared to `toml::table`, which is an alias of
|
|
||||||
`std::unordered_map<std::string, toml::value>`. Since `toml::table` does not have
|
|
||||||
any information about toml file, such as where the table was defined in the file.
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
If the specified type differs from the actual value contained, it throws
|
If the specified type differs from the actual value contained, it throws
|
||||||
|
@@ -101,6 +101,78 @@ BOOST_AUTO_TEST_CASE(test_find_throws)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_find_array_throws)
|
||||||
|
{
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// const-reference version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
const toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(v, 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// non-const reference version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(v, 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// move version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(std::move(v), 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(std::move(v), 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
||||||
{
|
{
|
||||||
// recursively search tables
|
// recursively search tables
|
||||||
@@ -129,6 +201,53 @@ BOOST_AUTO_TEST_CASE(test_find_recursive)
|
|||||||
auto num3 = toml::find<toml::integer>(std::move(v), a, b, c, d);
|
auto num3 = toml::find<toml::integer>(std::move(v), a, b, c, d);
|
||||||
BOOST_TEST(42 == num3);
|
BOOST_TEST(42 == num3);
|
||||||
}
|
}
|
||||||
|
// recursively search arrays
|
||||||
|
{
|
||||||
|
toml::value v{
|
||||||
|
toml::array{"array", "of", "string"},
|
||||||
|
toml::array{toml::array{1, 2, 3}, toml::array{3.14, 2.71}}
|
||||||
|
};
|
||||||
|
BOOST_TEST("array" == toml::find<std::string>(v, 0, 0));
|
||||||
|
BOOST_TEST("of" == toml::find<std::string>(v, 0, 1));
|
||||||
|
BOOST_TEST("string" == toml::find<std::string>(v, 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST(1 == toml::find<int>(v, 1, 0, 0));
|
||||||
|
BOOST_TEST(2 == toml::find<int>(v, 1, 0, 1));
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 1, 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, 1, 1, 0));
|
||||||
|
BOOST_TEST(2.71 == toml::find<double>(v, 1, 1, 1));
|
||||||
|
|
||||||
|
// reference that can be used to modify the content
|
||||||
|
auto& num = toml::find<toml::integer>(v, 1, 0, 2);
|
||||||
|
num = 42;
|
||||||
|
BOOST_TEST( 1 == toml::find<int>(v, 1, 0, 0));
|
||||||
|
BOOST_TEST( 2 == toml::find<int>(v, 1, 0, 1));
|
||||||
|
BOOST_TEST(42 == toml::find<int>(v, 1, 0, 2));
|
||||||
|
|
||||||
|
// move value
|
||||||
|
auto num2 = toml::find<toml::integer>(std::move(v), 1, 0, 2);
|
||||||
|
BOOST_TEST(42 == num2);
|
||||||
|
}
|
||||||
|
// recursively search mixtures
|
||||||
|
{
|
||||||
|
toml::value v = toml::table{{"array", toml::array{
|
||||||
|
toml::array{1, 2, 3},
|
||||||
|
toml::array{
|
||||||
|
toml::table{{"foo", "bar"}, {"baz", "qux"}},
|
||||||
|
toml::table{{"pi", 3.14}, {"e", 2.71}}
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
BOOST_TEST(1 == toml::find<int>(v, "array", 0, 0));
|
||||||
|
BOOST_TEST(2 == toml::find<int>(v, "array", 0, 1));
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, "array", 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST("bar" == toml::find<std::string>(v, "array", 1, 0, "foo"));
|
||||||
|
BOOST_TEST("qux" == toml::find<std::string>(v, "array", 1, 0, "baz"));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, "pi"));
|
||||||
|
BOOST_TEST(2.71 == toml::find<double>(v, "array", 1, 1, "e"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||||
|
136
toml/get.hpp
136
toml/get.hpp
@@ -485,6 +485,52 @@ basic_value<C, M, V> find(basic_value<C, M, V>&& v, const key& ky)
|
|||||||
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// find(value, idx)
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> const&
|
||||||
|
find(const basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
const auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ary.at(idx);
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>& find(basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ary.at(idx);
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> find(basic_value<C, M, V>&& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return basic_value<C, M, V>(std::move(ary.at(idx)));
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// find<T>(value, key);
|
// find<T>(value, key);
|
||||||
|
|
||||||
@@ -536,57 +582,111 @@ find(basic_value<C, M, V>&& v, const key& ky)
|
|||||||
return ::toml::get<T>(std::move(tab.at(ky)));
|
return ::toml::get<T>(std::move(tab.at(ky)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// find<T>(value, idx)
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))
|
||||||
|
find(const basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
const auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(ary.at(idx));
|
||||||
|
}
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
||||||
|
find(basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(ary.at(idx));
|
||||||
|
}
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
||||||
|
find(basic_value<C, M, V>&& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
typename basic_value<C, M, V>::array_type ary = std::move(v).as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(std::move(ary.at(idx)));
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
||||||
|
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
const basic_value<C, M, V>&
|
const basic_value<C, M, V>&
|
||||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(v, std::forward<Key1>(k1)),
|
||||||
|
std::forward<Key2>(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
basic_value<C, M, V>&
|
basic_value<C, M, V>&
|
||||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(v, std::forward<Key1>(k1)),
|
||||||
|
std::forward<Key2>(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
basic_value<C, M, V>
|
basic_value<C, M, V>
|
||||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(std::move(v), std::forward<Key1>(k1)),
|
||||||
|
std::forward<Key2>(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>()))
|
decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>()))
|
||||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(v, std::forward<Key1>(k1)),
|
||||||
|
std::forward<Key2>(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
||||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(v, std::forward<Key1>(k1)),
|
||||||
|
std::forward<Key2>(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
||||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(std::move(v), std::forward<Key1>(k1)),
|
||||||
|
std::forward<Key2>(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
Reference in New Issue
Block a user