Merge branch 'add-value-member-methods'

This commit is contained in:
ToruNiina
2020-01-17 20:30:26 +09:00
3 changed files with 173 additions and 3 deletions

View File

@@ -295,6 +295,19 @@ const auto data = toml::parse("fruit.toml");
const auto bar = toml::find<std::string>(data, "values", 1);
```
Before calling `toml::find`, you can check if a value corresponding to a key
exists. You can use both `bool toml::value::contains(const key&) const` and
`std::size_t toml::value::count(const key&) const`. Those behaves like the
`std::map::contains` and `std::map::count`.
```cpp
const auto data = toml::parse("fruit.toml");
if(data.contains("fruit") && data.at("fruit").count("physical") != 0)
{
// ...
}
```
### In case of error
If the value does not exist, `toml::find` throws `std::out_of_range` with the
@@ -885,14 +898,25 @@ toml::value v(toml::local_time(std::chrono::hours(10)));
```
You can construct an array object not only from `initializer_list`, but also
from STL containers.
from STL containers. In that case, the element type must be convertible to
`toml::value`.
```cpp
std::vector<int> vec{1,2,3,4,5};
toml::value v = vec;
toml::value v(vec);
```
All the elements of `initializer_list` should be convertible into `toml::value`.
When you construct an array value, all the elements of `initializer_list`
must be convertible into `toml::value`.
If a `toml::value` has an array, you can `push_back` an element in it.
```cpp
toml::value v{1,2,3,4,5};
v.push_back(6);
```
`emplace_back` also works.
## Preserving comments

View File

@@ -966,3 +966,54 @@ BOOST_AUTO_TEST_CASE(test_value_bracket)
BOOST_CHECK_THROW(v1["foo"], toml::type_error);
}
}
BOOST_AUTO_TEST_CASE(test_value_map_methods)
{
{
toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}};
BOOST_TEST(v1.count("foo") == 1u);
BOOST_TEST(v1.count("bar") == 1u);
BOOST_TEST(v1.count("baz") == 1u);
BOOST_TEST(v1.count("qux") == 0u);
BOOST_TEST( v1.contains("foo"));
BOOST_TEST( v1.contains("bar"));
BOOST_TEST( v1.contains("baz"));
BOOST_TEST(!v1.contains("qux"));
BOOST_TEST(v1.size() == 3);
v1["qux"] = 54;
BOOST_TEST(v1.count("qux") == 1u);
BOOST_TEST(v1.contains("qux"));
BOOST_TEST(v1.size() == 4);
}
{
toml::value v1(42);
BOOST_CHECK_THROW(v1.size() , toml::type_error);
BOOST_CHECK_THROW(v1.count("k") , toml::type_error);
BOOST_CHECK_THROW(v1.contains("k"), toml::type_error);
}
}
BOOST_AUTO_TEST_CASE(test_value_vector_methods)
{
{
toml::value v1{1, 2, 3, 4, 5};
BOOST_TEST(v1.size() == 5);
v1.push_back(6);
BOOST_TEST(v1.size() == 6);
v1.emplace_back(6);
BOOST_TEST(v1.size() == 7);
}
{
toml::value v1(42);
BOOST_CHECK_THROW(v1.size(), toml::type_error);
BOOST_CHECK_THROW(v1.push_back(1), toml::type_error);
BOOST_CHECK_THROW(v1.emplace_back(1), toml::type_error);
}
}

View File

@@ -1606,6 +1606,101 @@ class basic_value
return this->as_array(std::nothrow)[idx];
}
void push_back(const value_type& x)
{
if(this->type_ != value_t::array)
{
throw type_error(detail::format_underline(
"toml::value::push_back(value): bad_cast to array type", {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}), this->location());
}
this->as_array(std::nothrow).push_back(x);
return;
}
void push_back(value_type&& x)
{
if(this->type_ != value_t::array)
{
throw type_error(detail::format_underline(
"toml::value::push_back(value): bad_cast to array type", {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}), this->location());
}
this->as_array(std::nothrow).push_back(std::move(x));
return;
}
template<typename ... Ts>
value_type& emplace_back(Ts&& ... args)
{
if(this->type_ != value_t::array)
{
throw type_error(detail::format_underline(
"toml::value::emplace_back(value): bad_cast to array type", {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}), this->location());
}
this->as_array(std::nothrow).emplace_back(std::forward<Ts>(args) ...);
return this->as_array(std::nothrow).back();
}
std::size_t size() const
{
switch(this->type_)
{
case value_t::array:
{
return this->as_array().size();
}
case value_t::table:
{
return this->as_table().size();
}
case value_t::string:
{
return this->as_string().str.size();
}
default:
{
throw type_error(detail::format_underline(
"toml::value::size(): bad_cast to container types", {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}), this->location());
}
}
}
std::size_t count(const key_type& k) const
{
if(this->type_ != value_t::table)
{
throw type_error(detail::format_underline(
"toml::value::count(key): bad_cast to table type", {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}), this->location());
}
return this->as_table().count(k);
}
bool contains(const key_type& k) const
{
if(this->type_ != value_t::table)
{
throw type_error(detail::format_underline(
"toml::value::contains(key): bad_cast to table type", {
{this->region_info_.get(),
concat_to_string("the actual type is ", this->type_)}
}), this->location());
}
return (this->as_table().count(k) != 0);
}
source_location location() const
{
return source_location(this->region_info_.get());