Compare commits

...

11 Commits

Author SHA1 Message Date
ToruNiina
74fc70cfee return copied object from except
having reference makes some technical difficulties.
2018-12-17 10:57:40 +09:00
Toru Niina
91ac2debce Merge pull request #12 from ToruNiina/hotfix
enable to get toml::value as toml::value
2018-12-17 10:50:05 +09:00
Toru Niina
0de89a9f19 Merge pull request #13 from ToruNiina/error-format
enable to show user-defined error message with (a) toml::value(s)
2018-12-17 10:49:47 +09:00
ToruNiina
130609bf5f update README 2018-12-16 23:51:38 +09:00
ToruNiina
ab41e7acb9 enable to pass 2 value and change interface for clarity 2018-12-16 21:50:18 +09:00
ToruNiina
c15bc8df4a add format_error(toml::value, msg, comment) 2018-12-16 21:46:32 +09:00
ToruNiina
19524dbc4b fix silly typo 2018-12-16 21:13:21 +09:00
ToruNiina
c2e733a65d enable to get toml::value as toml::value 2018-12-16 20:50:40 +09:00
ToruNiina
0c08b9e940 fix typo 2018-12-15 22:02:46 +09:00
ToruNiina
06197605ba add link to toml-v0.5.0 official 2018-12-13 23:58:37 +09:00
ToruNiina
5c24cfd325 add example of multi-line error message 2018-12-13 23:47:32 +09:00
5 changed files with 122 additions and 92 deletions

View File

@@ -8,7 +8,7 @@ toml11
c++11 header-only toml parser depending only on c++ standard library. c++11 header-only toml parser depending only on c++ standard library.
compatible to the latest version of TOML v0.5.0 after version 2.0.0. compatible to the latest version of [TOML v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md) after version 2.0.0.
Are you looking for pre-C++11 compatible toml parser? Try [Boost.toml](https://github.com/ToruNiina/Boost.toml)! It has almost the same functionality as this library and works with C++98 & Boost. Are you looking for pre-C++11 compatible toml parser? Try [Boost.toml](https://github.com/ToruNiina/Boost.toml)! It has almost the same functionality as this library and works with C++98 & Boost.
@@ -64,6 +64,19 @@ terminate called after throwing an instance of 'toml::syntax_error'
| ^------ expected newline, but got '='. # error reason | ^------ expected newline, but got '='. # error reason
``` ```
If you (mistakenly) duplicate tables and got an error, you may want to see where the other is. toml11 shows both at the same time.
```console
terminate called after throwing an instance of 'toml::syntax_error'
what(): [error] toml::insert_value: table ("table") already exists.
--> duplicate-table.toml
1 | [table]
| ~~~~~~~ table already exists here
...
3 | [table]
| ~~~~~~~ table defined twice
```
Since the error message generation is generally a difficult task, the current status is not ideal. toml11 needs your help. If you encounter a weird error message, please let us know and contribute to improve the quality! Since the error message generation is generally a difficult task, the current status is not ideal. toml11 needs your help. If you encounter a weird error message, please let us know and contribute to improve the quality!
### Getting a toml value ### Getting a toml value
@@ -389,6 +402,59 @@ terminate called after throwing an instance of 'std::range_error'
| ~~~~~~~~~ should be in [0x00..0x10FFFF] | ~~~~~~~~~ should be in [0x00..0x10FFFF]
``` ```
### Formatting your error
When you encounter an error after you read the toml value, you may want to
show the error with the value.
toml11 provides you a function that formats user-defined error message with
related values. With a code like the following,
```cpp
const auto value = toml::find<int>(data, "num");
if(value < 0)
{
std::cerr << toml::format_error("[error] value should be positive",
data.at("num"), "positive number required")
<< std::endl;
}
```
you will get an error message like this.
```console
[error] value should be positive
--> example.toml
3 | num = -42
| ~~~ positive number required
```
When you pass two values to `toml::format_error`,
```cpp
const auto min = toml::find<int>(range, "min");
const auto max = toml::find<int>(range, "max");
if(max < min)
{
std::cerr << toml::format_error("[error] max should be larger than min",
data.at("min"), "minimum number here",
data.at("max"), "maximum number here");
<< std::endl;
}
```
you will get an error message like this.
```console
[error] value should be positive
--> example.toml
3 | min = 54
| ~~ minimum number here
...
4 | max = 42
| ~~ maximum number here
```
## Underlying types ## Underlying types
The toml types (can be used as `toml::*` in this library) and corresponding `enum` names are listed in the table below. The toml types (can be used as `toml::*` in this library) and corresponding `enum` names are listed in the table below.

View File

@@ -116,6 +116,14 @@ BOOST_AUTO_TEST_CASE(test_get_exact)
tab["key3"] = toml::value(123); tab["key3"] = toml::value(123);
BOOST_CHECK(tab == toml::get<toml::table>(v)); BOOST_CHECK(tab == toml::get<toml::table>(v));
} }
{
toml::value v1(42);
BOOST_CHECK(v1 == toml::get<toml::value>(v1));
toml::value v2(54);
toml::get<toml::value>(v1) = v2;
BOOST_CHECK(v2 == toml::get<toml::value>(v1));
}
} }
BOOST_AUTO_TEST_CASE(test_get_integer_type) BOOST_AUTO_TEST_CASE(test_get_integer_type)

View File

@@ -33,6 +33,30 @@ inline T&& get(value&& v)
return std::move(v.cast<detail::toml_value_t<T>::value>()); return std::move(v.cast<detail::toml_value_t<T>::value>());
} }
// ============================================================================
// T == toml::value; identity transformation.
template<typename T, typename std::enable_if<
std::is_same<T, ::toml::value>::value, std::nullptr_t>::type = nullptr>
inline T& get(value& v)
{
return v;
}
template<typename T, typename std::enable_if<
std::is_same<T, ::toml::value>::value, std::nullptr_t>::type = nullptr>
inline T const& get(const value& v)
{
return v;
}
template<typename T, typename std::enable_if<
std::is_same<T, ::toml::value>::value, std::nullptr_t>::type = nullptr>
inline T&& get(value&& v)
{
return std::move(v);
}
// ============================================================================ // ============================================================================
// integer convertible from toml::Integer // integer convertible from toml::Integer
@@ -456,52 +480,23 @@ auto get_or(toml::value&& v, const toml::key& ky, T&& opt)
// expect // expect
template<typename T> template<typename T>
auto expect(const toml::value& v) result<T, std::string> expect(const toml::value& v) noexcept
-> result<decltype(::toml::get<T>(v)), std::string>
{ {
try try
{ {
return ok(get<T>(v)); return ok(get<T>(v));
} }
catch(const type_error& te) catch(const std::exception& e)
{ {
return err(te.what()); return err(e.what());
} }
} }
template<typename T> template<typename T>
auto expect(toml::value& v) result<T, std::string> expect(const toml::value& v, const toml::key& k) noexcept
-> result<decltype(::toml::get<T>(v)), std::string>
{ {
try try
{ {
return ok(get<T>(v)); return ok(find<T>(v, k));
}
catch(const type_error& te)
{
return err(te.what());
}
}
template<typename T>
auto expect(toml::value&& v)
-> result<decltype(::toml::get<T>(std::move(v))), std::string>
{
try
{
return ok(get<T>(std::move(v)));
}
catch(const type_error& te)
{
return err(te.what());
}
}
template<typename T>
auto expect(const toml::value& v, const toml::key& k)
-> result<decltype(::toml::get<T>(v, k)), std::string>
{
try
{
return ok(get<T>(v, k));
} }
catch(const std::exception& e) catch(const std::exception& e)
{ {
@@ -509,65 +504,12 @@ auto expect(const toml::value& v, const toml::key& k)
} }
} }
template<typename T> template<typename T>
auto expect(toml::value& v, const toml::key& k) result<T, std::string> expect(const toml::table& t, const toml::key& k,
-> result<decltype(::toml::get<T>(v, k)), std::string> std::string tablename = "unknown table") noexcept
{ {
try try
{ {
return ok(get<T>(v, k)); return ok(find<T>(t, k, std::move(tablename)));
}
catch(const std::exception& e)
{
return err(e.what());
}
}
template<typename T>
auto expect(toml::value&& v, const toml::key& k)
-> result<decltype(::toml::get<T>(std::move(v), k)), std::string>
{
try
{
return ok(get<T>(std::move(v), k));
}
catch(const std::exception& e)
{
return err(e.what());
}
}
template<typename T>
auto expect(const toml::table& t, const toml::key& k, std::string tn)
-> result<decltype(::toml::get<T>(t, k, std::move(tn))), std::string>
{
try
{
return ok(get<T>(t, k, std::move(tn)));
}
catch(const std::exception& e)
{
return err(e.what());
}
}
template<typename T>
auto expect(toml::table& t, const toml::key& k, std::string tn)
-> result<decltype(::toml::get<T>(t, k, std::move(tn))), std::string>
{
try
{
return ok(get<T>(t, k, std::move(tn)));
}
catch(const std::exception& e)
{
return err(e.what());
}
}
template<typename T>
auto expect(toml::table&& t, const toml::key& k, std::string tn)
-> result<decltype(::toml::get<T>(std::move(t), k, std::move(tn))), std::string>
{
try
{
return ok(get<T>(std::move(t), k, std::move(tn)));
} }
catch(const std::exception& e) catch(const std::exception& e)
{ {

View File

@@ -881,7 +881,7 @@ parse_array(location<Container>& loc)
throw syntax_error(format_underline( throw syntax_error(format_underline(
"[error] toml::parse_array: type of elements should be the " "[error] toml::parse_array: type of elements should be the "
"same each other.", region<Container>(loc, first, loc.iter()), "same each other.", region<Container>(loc, first, loc.iter()),
"inhomogenous types")); "inhomogeneous types"));
} }
retval.push_back(std::move(val.unwrap())); retval.push_back(std::move(val.unwrap()));
} }

View File

@@ -800,5 +800,19 @@ inline bool operator>=(const toml::value& lhs, const toml::value& rhs)
return !(lhs < rhs); return !(lhs < rhs);
} }
inline std::string format_error(const std::string& err_msg,
const toml::value& v, const std::string& comment)
{
return detail::format_underline(err_msg, detail::get_region(v), comment);
}
inline std::string format_error(const std::string& err_msg,
const toml::value& v1, const std::string& comment1,
const toml::value& v2, const std::string& comment2)
{
return detail::format_underline(err_msg, detail::get_region(v1), comment1,
detail::get_region(v2), comment2);
}
}// toml }// toml
#endif// TOML11_VALUE #endif// TOML11_VALUE