mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1ec6d87bd | ||
|
|
8dded288b4 | ||
|
|
0f491c7f3a | ||
|
|
5edf43a1d2 | ||
|
|
cffc605505 | ||
|
|
fb91936a1d | ||
|
|
8833292858 | ||
|
|
3fe04aff77 | ||
|
|
138f030b5d |
@@ -5,9 +5,9 @@ project(toml11)
|
|||||||
|
|
||||||
set(toml11_VERSION_MAYOR 3)
|
set(toml11_VERSION_MAYOR 3)
|
||||||
set(toml11_VERSION_MINOR 0)
|
set(toml11_VERSION_MINOR 0)
|
||||||
set(toml11_VERSION_PATCH 0)
|
set(toml11_VERSION_PATCH 1)
|
||||||
set(toml11_VERSION
|
set(toml11_VERSION
|
||||||
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}-beta"
|
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
|
||||||
)
|
)
|
||||||
|
|
||||||
option(toml11_BUILD_TEST "Build toml tests" ON)
|
option(toml11_BUILD_TEST "Build toml tests" ON)
|
||||||
|
|||||||
112
README.md
112
README.md
@@ -47,8 +47,9 @@ int main()
|
|||||||
- [Decoding a toml file](#decoding-a-toml-file)
|
- [Decoding a toml file](#decoding-a-toml-file)
|
||||||
- [In the case of syntax error](#in-the-case-of-syntax-error)
|
- [In the case of syntax error](#in-the-case-of-syntax-error)
|
||||||
- [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints)
|
- [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints)
|
||||||
- [Finding a toml value](#finding-a-toml-value-from-a-table)
|
- [Finding a toml value](#finding-a-toml-value)
|
||||||
- [In the case of type error](#in-the-case-of-type-error)
|
- [Finding a value in a table](#finding-a-value-in-a-table)
|
||||||
|
- [In case of error](#in-case-of-error)
|
||||||
- [Dotted keys](#dotted-keys)
|
- [Dotted keys](#dotted-keys)
|
||||||
- [Casting a toml value](#casting-a-toml-value)
|
- [Casting a toml value](#casting-a-toml-value)
|
||||||
- [Checking value type](#checking-value-type)
|
- [Checking value type](#checking-value-type)
|
||||||
@@ -101,7 +102,7 @@ to pass a filename to the `toml::parse` function.
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const std::string fname("sample.toml");
|
const std::string fname("sample.toml");
|
||||||
const toml::table data = toml::parse(fname);
|
const toml::value data = toml::parse(fname);
|
||||||
```
|
```
|
||||||
|
|
||||||
If it encounters an error while opening a file, it will throw `std::runtime_error`.
|
If it encounters an error while opening a file, it will throw `std::runtime_error`.
|
||||||
@@ -185,7 +186,7 @@ representing unicode character is not a valid UTF-8 codepoint.
|
|||||||
| ^--------- should be in [0x00..0x10FFFF]
|
| ^--------- should be in [0x00..0x10FFFF]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Finding a toml value from a table
|
## Finding a toml value
|
||||||
|
|
||||||
After parsing successfully, you can obtain the values from the result of
|
After parsing successfully, you can obtain the values from the result of
|
||||||
`toml::parse` using `toml::find` function.
|
`toml::parse` using `toml::find` function.
|
||||||
@@ -196,8 +197,6 @@ answer = 42
|
|||||||
pi = 3.14
|
pi = 3.14
|
||||||
numbers = [1,2,3]
|
numbers = [1,2,3]
|
||||||
time = 1979-05-27T07:32:00Z
|
time = 1979-05-27T07:32:00Z
|
||||||
[tab]
|
|
||||||
key = "value"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
``` cpp
|
``` cpp
|
||||||
@@ -206,23 +205,16 @@ const auto answer = toml::find<std::int64_t >(data, "answer");
|
|||||||
const auto pi = toml::find<double >(data, "pi");
|
const auto pi = toml::find<double >(data, "pi");
|
||||||
const auto numbers = toml::find<std::vector<int>>(data, "numbers");
|
const auto numbers = toml::find<std::vector<int>>(data, "numbers");
|
||||||
const auto timepoint = toml::find<std::chrono::system_clock::time_point>(data, "time");
|
const auto timepoint = toml::find<std::chrono::system_clock::time_point>(data, "time");
|
||||||
const auto tab = toml::find<toml::table>(data, "tab");
|
|
||||||
const auto key = toml::find<std::string>(tab, "key");
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If the value does not exist, `toml::find` throws an error with the location of
|
By default, `toml::find` returns a `toml::value`.
|
||||||
the table.
|
|
||||||
|
|
||||||
```console
|
```cpp
|
||||||
terminate called after throwing an instance of 'std::out_of_range'
|
const toml::value& answer = toml::find(data, "answer");
|
||||||
what(): [error] key "answer" not found
|
|
||||||
--> example.toml
|
|
||||||
6 | [tab]
|
|
||||||
| ~~~~~ in this table
|
|
||||||
```
|
```
|
||||||
|
|
||||||
When you pass an exact TOML type that does not require type conversion,
|
When you pass an exact TOML type that does not require type conversion,
|
||||||
`toml::get` returns a reference without copying the value.
|
`toml::find` returns a reference without copying the value.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto data = toml::parse("sample.toml");
|
const auto data = toml::parse("sample.toml");
|
||||||
@@ -232,12 +224,6 @@ const auto& answer = toml::find<toml::integer>(data, "answer");
|
|||||||
If the specified type requires conversion, you can't take a reference to the value.
|
If the specified type requires conversion, you can't take a reference to the value.
|
||||||
See also [underlying types](#underlying-types).
|
See also [underlying types](#underlying-types).
|
||||||
|
|
||||||
By default, `toml::find` returns a `toml::value`.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
const toml::value& answer = toml::find(data, "answer");
|
|
||||||
```
|
|
||||||
|
|
||||||
**NOTE**: For some technical reason, automatic conversion between `integer` and
|
**NOTE**: For some technical reason, automatic conversion between `integer` and
|
||||||
`floating` is not supported. If you want to get a floating value even if a value
|
`floating` is not supported. If you want to get a floating value even if a value
|
||||||
has integer value, you need to convert it manually after obtaining a value,
|
has integer value, you need to convert it manually after obtaining a value,
|
||||||
@@ -250,23 +236,59 @@ double x = vx.is_floating() ? vx.as_floating(std::nothrow) :
|
|||||||
// floating nor integer.
|
// floating nor integer.
|
||||||
```
|
```
|
||||||
|
|
||||||
----
|
### Finding a value in a table
|
||||||
|
|
||||||
`toml::find` accepts arbitrary number of keys to find a value buried in a
|
There are several way to get a value defined in a table.
|
||||||
deep recursion of tables.
|
First, you can get a table as a normal value and find a value from the table.
|
||||||
|
|
||||||
```cpp
|
```toml
|
||||||
// # expecting the following example.toml
|
[fruit]
|
||||||
// answer.to.the.ultimate.question = 42
|
name = "apple"
|
||||||
// # is equivalent to {"answer": {"to":{"the":{"ultimate:{"question":42}}}}}
|
[fruit.physical]
|
||||||
|
color = "red"
|
||||||
const toml::table data = toml::parse("example.toml");
|
shape = "round"
|
||||||
const int a = toml::find<int>(data, "answer", "to", "the", "ultimate", "question");
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Of course, alternatively, you can call `toml::find` as many as you need.
|
``` cpp
|
||||||
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
const auto& fruit = toml::find(data, "fruit");
|
||||||
|
const auto name = toml::find<std::string>(fruit, "apple");
|
||||||
|
|
||||||
### In the case of type error
|
const auto& physical = toml::find(fruit, "physical");
|
||||||
|
const auto color = toml::find<std::string>(fruit, "color");
|
||||||
|
const auto shape = toml::find<std::string>(fruit, "shape");
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, variable `fruit` is a `toml::value` and can be used as the first argument
|
||||||
|
of `toml::find`.
|
||||||
|
|
||||||
|
Second, you can pass as many arguments as the number of subtables to `toml::find`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
const auto color = toml::find<std::string>(data, "fruit", "physical", "color");
|
||||||
|
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
||||||
|
```
|
||||||
|
|
||||||
|
### In case of error
|
||||||
|
|
||||||
|
If the value does not exist, `toml::find` throws an error with the location of
|
||||||
|
the table.
|
||||||
|
|
||||||
|
```console
|
||||||
|
terminate called after throwing an instance of 'std::out_of_range'
|
||||||
|
what(): [error] key "answer" not found
|
||||||
|
--> example.toml
|
||||||
|
6 | [tab]
|
||||||
|
| ~~~~~ 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
|
||||||
`toml::type_error` that inherits `std::exception`.
|
`toml::type_error` that inherits `std::exception`.
|
||||||
@@ -309,14 +331,15 @@ shape = "round"
|
|||||||
You can get both of the above tables with the same c++ code.
|
You can get both of the above tables with the same c++ code.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto physical = toml::find<toml::table>(data, "physical");
|
const auto physical = toml::find(data, "physical");
|
||||||
const auto color = toml::find<std::string>(physical, "color");
|
const auto color = toml::find<std::string>(physical, "color");
|
||||||
```
|
```
|
||||||
|
|
||||||
The following code does not work for the above toml file.
|
The following code does not work for the above toml file.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto color = toml::find<std::string>(data, "physical.color"); // does not work
|
// XXX this does not work!
|
||||||
|
const auto color = toml::find<std::string>(data, "physical.color");
|
||||||
```
|
```
|
||||||
|
|
||||||
The above code works with the following toml file.
|
The above code works with the following toml file.
|
||||||
@@ -348,18 +371,22 @@ contain one of the following types.
|
|||||||
- It depends. See [customizing containers](#customizing-containers) for detail.
|
- It depends. See [customizing containers](#customizing-containers) for detail.
|
||||||
|
|
||||||
To get a value inside, you can use `toml::get<T>()`. The usage is the same as
|
To get a value inside, you can use `toml::get<T>()`. The usage is the same as
|
||||||
`toml::find<T>` (actually, `toml::find` internally uses `toml::get`).
|
`toml::find<T>` (actually, `toml::find` internally uses `toml::get` after casting
|
||||||
|
a value to `toml::table`).
|
||||||
|
|
||||||
``` cpp
|
``` cpp
|
||||||
const toml::value data = toml::parse("sample.toml");
|
const toml::value data = toml::parse("sample.toml");
|
||||||
const toml::value answer_ = toml::get<toml::table >(data).at("answer")
|
const toml::value answer_ = toml::get<toml::table >(data).at("answer");
|
||||||
const std::int64_t answer = toml::get<std::int64_t>(answer_);
|
const std::int64_t answer = toml::get<std::int64_t>(answer_);
|
||||||
```
|
```
|
||||||
|
|
||||||
When you pass an exact TOML type that does not require type conversion,
|
When you pass an exact TOML type that does not require type conversion,
|
||||||
`toml::get` returns a reference through which you can modify the content.
|
`toml::get` returns a reference through which you can modify the content
|
||||||
|
(if the `toml::value` is `const`, it returns `const` reference).
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
toml::value data = toml::parse("sample.toml");
|
||||||
|
toml::value answer_ = toml::get<toml::table >(data).at("answer");
|
||||||
toml::integer& answer = toml::get<toml::integer>(answer_);
|
toml::integer& answer = toml::get<toml::integer>(answer_);
|
||||||
answer = 6 * 9; // write to data.answer. now `answer_` contains 54.
|
answer = 6 * 9; // write to data.answer. now `answer_` contains 54.
|
||||||
```
|
```
|
||||||
@@ -426,8 +453,6 @@ class value {
|
|||||||
} // toml
|
} // toml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Checking value type
|
## Checking value type
|
||||||
|
|
||||||
You can check the type of a value by `is_xxx` function.
|
You can check the type of a value by `is_xxx` function.
|
||||||
@@ -1392,8 +1417,9 @@ Between v2 and v3, those interfaces are rearranged.
|
|||||||
- See [Casting a toml::value](#casting-a-tomlvalue) and [Checking value type](#checking-value-type) for detail.
|
- See [Casting a toml::value](#casting-a-tomlvalue) and [Checking value type](#checking-value-type) for detail.
|
||||||
- An overload of `toml::find` for `toml::table` has been dropped. Use `toml::value` version instead.
|
- An overload of `toml::find` for `toml::table` has been dropped. Use `toml::value` version instead.
|
||||||
- Because type conversion between a table and a value causes ambiguity while overload resolution
|
- Because type conversion between a table and a value causes ambiguity while overload resolution
|
||||||
|
- Since `toml::parse` now returns a `toml::value`, this feature becomes less important.
|
||||||
- Also because `toml::table` is a normal STL container, implementing utility function is easy.
|
- Also because `toml::table` is a normal STL container, implementing utility function is easy.
|
||||||
- See [Finding a toml::value](#finding-a-tomlvalue) for detail.
|
- See [Finding a toml::value](#finding-a-toml-value) for detail.
|
||||||
- An overload of `operator<<` and `toml::format` for `toml::table`s are dropped.
|
- An overload of `operator<<` and `toml::format` for `toml::table`s are dropped.
|
||||||
- Use `toml::value` instead.
|
- Use `toml::value` instead.
|
||||||
- See [Serializing TOML data](#serializing-toml-data) for detail.
|
- See [Serializing TOML data](#serializing-toml-data) for detail.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <boost/test/included/unit_test.hpp>
|
#include <boost/test/included/unit_test.hpp>
|
||||||
#endif
|
#endif
|
||||||
#include <toml.hpp>
|
#include <toml.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
// to check it successfully compiles. it does not check the formatted string.
|
// to check it successfully compiles. it does not check the formatted string.
|
||||||
|
|
||||||
|
|||||||
56
toml/get.hpp
56
toml/get.hpp
@@ -575,6 +575,28 @@ find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// get_or(value, fallback)
|
// get_or(value, fallback)
|
||||||
|
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> const&
|
||||||
|
get_or(const basic_value<C, M, V>& v, const basic_value<C, M, V>&)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>&
|
||||||
|
get_or(basic_value<C, M, V>& v, basic_value<C, M, V>&)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>
|
||||||
|
get_or(basic_value<C, M, V>&& v, basic_value<C, M, V>&&)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// specialization for the exact toml types (return type becomes lvalue ref)
|
// specialization for the exact toml types (return type becomes lvalue ref)
|
||||||
|
|
||||||
@@ -726,6 +748,40 @@ get_or(const basic_value<C, M, V>& v, T&& opt)
|
|||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// find_or(value, key, fallback)
|
// find_or(value, key, fallback)
|
||||||
|
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> const&
|
||||||
|
find_or(const basic_value<C, M, V>& v, const key& ky,
|
||||||
|
const basic_value<C, M, V>& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
const auto& tab = v.as_table();
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return tab.at(ky);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>&
|
||||||
|
find_or(basic_value<C, M, V>& v, const toml::key& ky, basic_value<C, M, V>& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
auto& tab = v.as_table();
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return tab[ky];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>
|
||||||
|
find_or(basic_value<C, M, V>&& v, const toml::key& ky, basic_value<C, M, V>&& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
auto tab = std::move(v).as_table();
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return std::move(tab[ky]);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// exact types (return type can be a reference)
|
// exact types (return type can be a reference)
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
#include "lexer.hpp"
|
#include "lexer.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include "value.hpp"
|
#include "value.hpp"
|
||||||
#include <iostream>
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
|
|||||||
Reference in New Issue
Block a user