mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
35 Commits
find-fuzzy
...
v3.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e12fd4d944 | ||
|
|
36af02cb3a | ||
|
|
488015df49 | ||
|
|
1f951e49b1 | ||
|
|
6a7dbb7875 | ||
|
|
ad7eb56634 | ||
|
|
b01c5534ed | ||
|
|
22dac3c9f2 | ||
|
|
d5adfe8c7d | ||
|
|
4bb8045c84 | ||
|
|
babb6ab3fe | ||
|
|
d73bc6076c | ||
|
|
8d1da6e8b5 | ||
|
|
8276e12f06 | ||
|
|
f3d3f63ff9 | ||
|
|
d9689c878d | ||
|
|
df097cb09a | ||
|
|
a425e3b7c6 | ||
|
|
e4b4503b81 | ||
|
|
b44fbad925 | ||
|
|
826c9444ac | ||
|
|
a1095f3e4c | ||
|
|
483a39beb4 | ||
|
|
1409114c96 | ||
|
|
ecfc9d0c5a | ||
|
|
94f76137a3 | ||
|
|
c2e1aa9a3c | ||
|
|
5b5ece6c32 | ||
|
|
b696e327d7 | ||
|
|
757e5d60be | ||
|
|
c02093de7f | ||
|
|
4f8b62a7e9 | ||
|
|
d9b8582c47 | ||
|
|
64e7bdb835 | ||
|
|
1acf87679e |
78
.travis.yml
78
.travis.yml
@@ -5,7 +5,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env: COMPILER="g++-5" CXX_STANDARD=11
|
||||
env: COMPILER="g++-5" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -17,7 +17,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env: COMPILER="g++-6" CXX_STANDARD=11
|
||||
env: COMPILER="g++-6" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -29,7 +29,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env: COMPILER="g++-7" CXX_STANDARD=11
|
||||
env: COMPILER="g++-7" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -41,7 +41,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env: COMPILER="g++-8" CXX_STANDARD=11
|
||||
env: COMPILER="g++-8" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -53,7 +53,31 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env: COMPILER="g++-8" CXX_STANDARD=17
|
||||
env: COMPILER="g++-8" CXX_STANDARD=11 TOML_HEAD=ON
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:mhier/libboost-latest'
|
||||
packages:
|
||||
- g++-8
|
||||
- boost1.70
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:mhier/libboost-latest'
|
||||
packages:
|
||||
- g++-8
|
||||
- boost1.70
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=ON
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -65,7 +89,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-3.7" CXX_STANDARD=11
|
||||
env: COMPILER="clang++-3.7" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -79,7 +103,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-4.0" CXX_STANDARD=11
|
||||
env: COMPILER="clang++-4.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -93,7 +117,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-5.0" CXX_STANDARD=11
|
||||
env: COMPILER="clang++-5.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -107,7 +131,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-6.0" CXX_STANDARD=11
|
||||
env: COMPILER="clang++-6.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -121,7 +145,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-7" CXX_STANDARD=11
|
||||
env: COMPILER="clang++-7" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -135,7 +159,7 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-8" CXX_STANDARD=11
|
||||
env: COMPILER="clang++-8" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -149,7 +173,35 @@ matrix:
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-8" CXX_STANDARD=17
|
||||
env: COMPILER="clang++-8" CXX_STANDARD=11 TOML_HEAD=ON
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-8
|
||||
- sourceline: 'ppa:mhier/libboost-latest'
|
||||
packages:
|
||||
- g++-8
|
||||
- clang-8
|
||||
- boost1.70
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=OFF
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-8
|
||||
- sourceline: 'ppa:mhier/libboost-latest'
|
||||
packages:
|
||||
- clang-8
|
||||
- g++-8
|
||||
- boost1.70
|
||||
- os: linux
|
||||
language: cpp
|
||||
compiler: clang
|
||||
env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=ON
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
@@ -179,6 +231,6 @@ script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- git clone https://github.com/toml-lang/toml.git
|
||||
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD ..
|
||||
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD -DTOML11_USE_UNRELEASED_TOML_FEATURES=${TOML_HEAD} ..
|
||||
- make
|
||||
- ctest --output-on-failure
|
||||
|
||||
156
README.md
156
README.md
@@ -70,6 +70,7 @@ int main()
|
||||
- [Formatting user-defined error messages](#formatting-user-defined-error-messages)
|
||||
- [Serializing TOML data](#serializing-toml-data)
|
||||
- [Underlying types](#underlying-types)
|
||||
- [Unreleased TOML features](#unreleased-toml-features)
|
||||
- [Breaking Changes from v2](#breaking-changes-from-v2)
|
||||
- [Running Tests](#running-tests)
|
||||
- [Contributors](#contributors)
|
||||
@@ -270,46 +271,6 @@ const auto color = toml::find<std::string>(data, "fruit", "physical", "color");
|
||||
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
||||
```
|
||||
|
||||
### Dotted keys
|
||||
|
||||
TOML v0.5.0 has a new feature named "dotted keys".
|
||||
You can chain keys to represent the structure of the data.
|
||||
|
||||
```toml
|
||||
physical.color = "orange"
|
||||
physical.shape = "round"
|
||||
```
|
||||
|
||||
This is equivalent to the following.
|
||||
|
||||
```toml
|
||||
[physical]
|
||||
color = "orange"
|
||||
shape = "round"
|
||||
```
|
||||
|
||||
You can get both of the above tables with the same c++ code.
|
||||
|
||||
```cpp
|
||||
const auto physical = toml::find(data, "physical");
|
||||
const auto color = toml::find<std::string>(physical, "color");
|
||||
```
|
||||
|
||||
The following code does not work for the above toml file.
|
||||
|
||||
```cpp
|
||||
// XXX this does not work!
|
||||
const auto color = toml::find<std::string>(data, "physical.color");
|
||||
```
|
||||
|
||||
The above code works with the following toml file.
|
||||
|
||||
```toml
|
||||
"physical.color" = "orange"
|
||||
# equivalent to {"physical.color": "orange"},
|
||||
# NOT {"physical": {"color": "orange"}}.
|
||||
```
|
||||
|
||||
### In case of error
|
||||
|
||||
If the value does not exist, `toml::find` throws an error with the location of
|
||||
@@ -350,77 +311,46 @@ shared by `toml::value`s and remains on the heap memory. It is recommended to
|
||||
destruct all the `toml::value` classes after configuring your application
|
||||
if you have a large TOML file compared to the memory resource.
|
||||
|
||||
### Fuzzy Search
|
||||
### Dotted keys
|
||||
|
||||
To find a value, you can use `find_fuzzy` instead of `find`.
|
||||
TOML v0.5.0 has a new feature named "dotted keys".
|
||||
You can chain keys to represent the structure of the data.
|
||||
|
||||
```toml
|
||||
[foobar]
|
||||
# typo!
|
||||
anseer = 42
|
||||
physical.color = "orange"
|
||||
physical.shape = "round"
|
||||
```
|
||||
|
||||
This is equivalent to the following.
|
||||
|
||||
```toml
|
||||
[physical]
|
||||
color = "orange"
|
||||
shape = "round"
|
||||
```
|
||||
|
||||
You can get both of the above tables with the same c++ code.
|
||||
|
||||
```cpp
|
||||
const auto data = toml::parse("sample.toml");
|
||||
const auto foobar = toml::find(data, "foobar");
|
||||
const auto answer = toml::find_fuzzy<int>(data, "answer"); // it finds "anseer".
|
||||
const auto physical = toml::find(data, "physical");
|
||||
const auto color = toml::find<std::string>(physical, "color");
|
||||
```
|
||||
|
||||
When the specified key is not found, `toml::find_fuzzy` calculates
|
||||
[levenstein distance](https://en.wikipedia.org/wiki/Levenshtein_distance)
|
||||
between the specified key and other keys.
|
||||
If it finds a key that is 1 away from the specified key by the Levenstein
|
||||
distance, it returns the corresponding value.
|
||||
|
||||
To allow a more distant string, you can explicitly pass `toml::levenstein_matcher`
|
||||
to `find_fuzzy`.
|
||||
The following code does not work for the above toml file.
|
||||
|
||||
```cpp
|
||||
toml::levenstein_matcher lev(2); // allow distance <= 2
|
||||
const auto answer = toml::find_fuzzy<int>(data, "answer", lev);
|
||||
// XXX this does not work!
|
||||
const auto color = toml::find<std::string>(data, "physical.color");
|
||||
```
|
||||
|
||||
You can also use your own distance metric. Implement your `fuzzy_matcher` that
|
||||
has `operator()` that takes two strings and returns true if two strings resemble
|
||||
each other.
|
||||
The above code works with the following toml file.
|
||||
|
||||
```cpp
|
||||
struct fuzzy_matcher
|
||||
{
|
||||
bool operator()(const std::string& lhs, const std::string& rhs) const
|
||||
{
|
||||
// return true if lhs matches with rhs.
|
||||
}
|
||||
};
|
||||
```toml
|
||||
"physical.color" = "orange"
|
||||
# equivalent to {"physical.color": "orange"},
|
||||
# NOT {"physical": {"color": "orange"}}.
|
||||
```
|
||||
|
||||
If there are multiple keys that meets the condition, it throws `runtime_error`.
|
||||
|
||||
However, in many cases, rather than just allowing typographical errors,
|
||||
you will want to suggest it and encouledge users to correct it.
|
||||
|
||||
If you pass a `fuzzy_matcher` to `toml::find`, a suggestion will be displayed
|
||||
in the error message.
|
||||
|
||||
```cpp
|
||||
toml::levenstein_matcher lev(1); // finds keys within distance <= 1
|
||||
const auto answer = toml::find<int>(data, "answer", lev); // it throws!
|
||||
```
|
||||
|
||||
```console
|
||||
terminate called after throwing an instance of 'std::out_of_range'
|
||||
what(): [error] key "answer" not found.
|
||||
--> hoge.toml
|
||||
1 | [foobar]
|
||||
| ~~~~~~~~ in this table
|
||||
...
|
||||
2 | anseer = 42
|
||||
| ~~ did you mean this here?
|
||||
```
|
||||
|
||||
Note: Currently, `find_fuzzy` and `find(value, key, matcher)` take only one key.
|
||||
The codes like `find_fuzzy(value, key1, key2, key3)` do not work.
|
||||
|
||||
## Casting a toml value
|
||||
|
||||
### `toml::get`
|
||||
@@ -524,6 +454,22 @@ class value {
|
||||
} // toml
|
||||
```
|
||||
|
||||
### `at()`
|
||||
|
||||
You can access to the element of a table and an array by `toml::basic_value::at`.
|
||||
|
||||
```cpp
|
||||
const toml::value v{1,2,3,4,5};
|
||||
std::cout << v.at(2).as_integer() << std::endl; // 3
|
||||
|
||||
const toml::value v{{"foo", 42}, {"bar", 3.14}};
|
||||
std::cout << v.at("foo").as_integer() << std::endl; // 42
|
||||
```
|
||||
|
||||
If an invalid key (integer for a table, string for an array), it throws
|
||||
`toml::type_error` for the conversion. If the provided key is out-of-range,
|
||||
it throws `std::out_of_range`.
|
||||
|
||||
## Checking value type
|
||||
|
||||
You can check the type of a value by `is_xxx` function.
|
||||
@@ -1145,7 +1091,7 @@ namespace toml
|
||||
template<>
|
||||
struct from<ext::foo>
|
||||
{
|
||||
ext::foo from_toml(const value& v)
|
||||
static ext::foo from_toml(const value& v)
|
||||
{
|
||||
ext::foo f;
|
||||
f.a = find<int >(v, "a");
|
||||
@@ -1185,7 +1131,7 @@ template<>
|
||||
struct from<ext::foo>
|
||||
{
|
||||
template<typename C, template<typename ...> class M, template<typename ...> class A>
|
||||
ext::foo from_toml(const basic_value<C, M, A>& v)
|
||||
static ext::foo from_toml(const basic_value<C, M, A>& v)
|
||||
{
|
||||
ext::foo f;
|
||||
f.a = find<int >(v, "a");
|
||||
@@ -1241,7 +1187,7 @@ namespace toml
|
||||
template<>
|
||||
struct into<ext::foo>
|
||||
{
|
||||
toml::table into_toml(const ext::foo& f)
|
||||
static toml::table into_toml(const ext::foo& f)
|
||||
{
|
||||
return toml::table{{"a", f.a}, {"b", f.b}, {"c", f.c}};
|
||||
}
|
||||
@@ -1467,6 +1413,16 @@ not capable of representing a Local Time independent from a specific day.
|
||||
|
||||
It is recommended to get `datetime`s as `std::chrono` classes through `toml::get`.
|
||||
|
||||
## Unreleased TOML features
|
||||
|
||||
There are some unreleased features in toml-lang/toml:master.
|
||||
Currently, the following features are available after defining
|
||||
`TOML11_USE_UNRELEASED_TOML_FEATURES` macro flag.
|
||||
|
||||
- Leading zeroes in exponent parts of floats are permitted.
|
||||
- e.g. `1.0e+01`, `5e+05`
|
||||
- Allow raw tab characters in basic strings and multi-line basic strings.
|
||||
|
||||
## Breaking Changes from v2
|
||||
|
||||
Although toml11 is relatively new library (it's three years old now), it had
|
||||
@@ -1536,6 +1492,8 @@ I appreciate the help of the contributors who introduced the great feature to th
|
||||
- Fixed warnings while type conversion
|
||||
- @KerstinKeller
|
||||
- Added installation script to CMake
|
||||
- J.C. Moyer (@jcmoyer)
|
||||
- Fixed an example code in the documentation
|
||||
|
||||
## Licensing terms
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ set(TEST_NAMES
|
||||
test_get_or
|
||||
test_find
|
||||
test_find_or
|
||||
test_find_fuzzy
|
||||
test_expect
|
||||
test_parse_file
|
||||
test_serialize_file
|
||||
@@ -51,6 +50,14 @@ if(COMPILER_SUPPORTS_WPEDANTIC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||
endif()
|
||||
|
||||
option(TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
"use features in toml-lang/toml master while testing" OFF)
|
||||
|
||||
if(TOML11_USE_UNRELEASED_TOML_FEATURES)
|
||||
message(STATUS "adding TOML11_USE_UNRELEASED_TOML_FEATURES flag")
|
||||
add_definitions("-DTOML11_USE_UNRELEASED_TOML_FEATURES")
|
||||
endif()
|
||||
|
||||
# Disable some MSVC warnings
|
||||
if(MSVC)
|
||||
# conversion from 'double' to 'unsigned int', possible loss of data
|
||||
|
||||
@@ -33,6 +33,17 @@ struct bar
|
||||
return toml::table{{"a", this->a}, {"b", this->b}};
|
||||
}
|
||||
};
|
||||
|
||||
struct baz
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
struct qux
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
} // extlib
|
||||
|
||||
namespace toml
|
||||
@@ -54,6 +65,24 @@ struct into<extlib::foo>
|
||||
return toml::table{{"a", f.a}, {"b", f.b}};
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct from<extlib::baz>
|
||||
{
|
||||
static extlib::baz from_toml(const toml::value& v)
|
||||
{
|
||||
return extlib::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct into<extlib::qux>
|
||||
{
|
||||
static toml::table into_toml(const extlib::qux& f)
|
||||
{
|
||||
return toml::table{{"a", f.a}, {"b", f.b}};
|
||||
}
|
||||
};
|
||||
} // toml
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -83,6 +112,16 @@ struct bar
|
||||
return toml::table{{"a", this->a}, {"b", this->b}};
|
||||
}
|
||||
};
|
||||
struct baz
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
struct qux
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
} // extlib2
|
||||
|
||||
namespace toml
|
||||
@@ -105,6 +144,28 @@ struct into<extlib2::foo>
|
||||
return toml::table{{"a", f.a}, {"b", f.b}};
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct from<extlib2::baz>
|
||||
{
|
||||
template<typename C, template<typename ...> class M, template<typename ...> class A>
|
||||
static extlib2::baz from_toml(const toml::basic_value<C, M, A>& v)
|
||||
{
|
||||
return extlib2::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct into<extlib2::qux>
|
||||
{
|
||||
static toml::basic_value<toml::preserve_comments, std::map>
|
||||
into_toml(const extlib2::qux& f)
|
||||
{
|
||||
return toml::basic_value<toml::preserve_comments, std::map>{
|
||||
{"a", f.a}, {"b", f.b}
|
||||
};
|
||||
}
|
||||
};
|
||||
} // toml
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -188,6 +249,41 @@ BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_conversion_one_way)
|
||||
{
|
||||
{
|
||||
const toml::value v{{"a", 42}, {"b", "baz"}};
|
||||
|
||||
const auto baz = toml::get<extlib::baz>(v);
|
||||
BOOST_TEST(baz.a == 42);
|
||||
BOOST_TEST(baz.b == "baz");
|
||||
}
|
||||
{
|
||||
const extlib::qux q{42, "qux"};
|
||||
const toml::value v(q);
|
||||
|
||||
BOOST_TEST(toml::find<int>(v, "a") == 42);
|
||||
BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
|
||||
}
|
||||
|
||||
{
|
||||
const toml::basic_value<toml::discard_comments, std::map> v{
|
||||
{"a", 42}, {"b", "baz"}
|
||||
};
|
||||
|
||||
const auto baz = toml::get<extlib2::baz>(v);
|
||||
BOOST_TEST(baz.a == 42);
|
||||
BOOST_TEST(baz.b == "baz");
|
||||
}
|
||||
{
|
||||
const extlib::qux q{42, "qux"};
|
||||
const toml::basic_value<toml::preserve_comments, std::map> v(q);
|
||||
|
||||
BOOST_TEST(toml::find<int>(v, "a") == 42);
|
||||
BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
||||
{
|
||||
{
|
||||
|
||||
@@ -27,6 +27,32 @@ using test_value_types = std::tuple<
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_throws)
|
||||
{
|
||||
// -----------------------------------------------------------------------
|
||||
// const-reference version
|
||||
{
|
||||
// value is not a table
|
||||
const toml::value v(true);
|
||||
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not the expected type
|
||||
const toml::value v{{"key", 42}};
|
||||
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not found
|
||||
const toml::value v{{"key", 42}};
|
||||
BOOST_CHECK_THROW(toml::find<toml::integer>(v, "different_key"),
|
||||
std::out_of_range);
|
||||
}
|
||||
{
|
||||
// the positive control.
|
||||
const toml::value v{{"key", 42}};
|
||||
BOOST_TEST(42 == toml::find<int>(v, "key"));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// reference version
|
||||
{
|
||||
// value is not a table
|
||||
toml::value v(true);
|
||||
@@ -48,6 +74,31 @@ BOOST_AUTO_TEST_CASE(test_find_throws)
|
||||
toml::value v{{"key", 42}};
|
||||
BOOST_TEST(42 == toml::find<int>(v, "key"));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// move version
|
||||
|
||||
{
|
||||
// value is not a table
|
||||
toml::value v(true);
|
||||
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), "key"), toml::type_error);
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not the expected type
|
||||
toml::value v{{"key", 42}};
|
||||
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), "key"), toml::type_error);
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not found
|
||||
toml::value v{{"key", 42}};
|
||||
BOOST_CHECK_THROW(toml::find<toml::integer>(std::move(v), "different_key"),
|
||||
std::out_of_range);
|
||||
}
|
||||
{
|
||||
// the positive control.
|
||||
toml::value v{{"key", 42}};
|
||||
BOOST_TEST(42 == toml::find<int>(std::move(v), "key"));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
||||
@@ -74,6 +125,9 @@ BOOST_AUTO_TEST_CASE(test_find_recursive)
|
||||
auto& num2 = toml::find<toml::integer>(v, a, b, c, d);
|
||||
num2 = 42;
|
||||
BOOST_TEST(42 == toml::find<int>(v, a, b, c, d));
|
||||
|
||||
auto num3 = toml::find<toml::integer>(std::move(v), a, b, c, d);
|
||||
BOOST_TEST(42 == num3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +139,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
|
||||
toml::find<toml::boolean>(v, "key") = false;
|
||||
BOOST_TEST(false == toml::find<toml::boolean>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::boolean>(std::move(v), "key");
|
||||
BOOST_TEST(false == moved);
|
||||
}
|
||||
{
|
||||
value_type v{{"key", 42}};
|
||||
@@ -92,6 +149,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
|
||||
toml::find<toml::integer>(v, "key") = 54;
|
||||
BOOST_TEST(toml::integer(54) == toml::find<toml::integer>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::integer>(std::move(v), "key");
|
||||
BOOST_TEST(toml::integer(54) == moved);
|
||||
}
|
||||
{
|
||||
value_type v{{"key", 3.14}};
|
||||
@@ -99,6 +159,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
|
||||
toml::find<toml::floating>(v, "key") = 2.71;
|
||||
BOOST_TEST(toml::floating(2.71) == toml::find<toml::floating>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::floating>(std::move(v), "key");
|
||||
BOOST_TEST(toml::floating(2.71) == moved);
|
||||
}
|
||||
{
|
||||
value_type v{{"key", "foo"}};
|
||||
@@ -108,6 +171,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
toml::find<toml::string>(v, "key").str += "bar";
|
||||
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
|
||||
toml::find<toml::string>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::string>(std::move(v), "key");
|
||||
BOOST_TEST(toml::string("foobar", toml::string_t::basic) == moved);
|
||||
}
|
||||
{
|
||||
value_type v{{"key", value_type("foo", toml::string_t::literal)}};
|
||||
@@ -117,6 +183,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
toml::find<toml::string>(v, "key").str += "bar";
|
||||
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
|
||||
toml::find<toml::string>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::string>(std::move(v), "key");
|
||||
BOOST_TEST(toml::string("foobar", toml::string_t::literal) == moved);
|
||||
}
|
||||
{
|
||||
toml::local_date d(2018, toml::month_t::Apr, 22);
|
||||
@@ -126,6 +195,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
toml::find<toml::local_date>(v, "key").year = 2017;
|
||||
d.year = 2017;
|
||||
BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::local_date>(std::move(v), "key");
|
||||
BOOST_CHECK(d == moved);
|
||||
}
|
||||
{
|
||||
toml::local_time t(12, 30, 45);
|
||||
@@ -135,6 +207,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
toml::find<toml::local_time>(v, "key").hour = 9;
|
||||
t.hour = 9;
|
||||
BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::local_time>(std::move(v), "key");
|
||||
BOOST_CHECK(t == moved);
|
||||
}
|
||||
{
|
||||
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
||||
@@ -145,6 +220,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
toml::find<toml::local_datetime>(v, "key").date.year = 2017;
|
||||
dt.date.year = 2017;
|
||||
BOOST_CHECK(dt == toml::find<toml::local_datetime>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::local_datetime>(std::move(v), "key");
|
||||
BOOST_CHECK(dt == moved);
|
||||
}
|
||||
{
|
||||
toml::offset_datetime dt(toml::local_datetime(
|
||||
@@ -156,6 +234,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
toml::find<toml::offset_datetime>(v, "key").date.year = 2017;
|
||||
dt.date.year = 2017;
|
||||
BOOST_CHECK(dt == toml::find<toml::offset_datetime>(v, "key"));
|
||||
|
||||
const auto moved = toml::find<toml::offset_datetime>(std::move(v), "key");
|
||||
BOOST_CHECK(dt == moved);
|
||||
}
|
||||
{
|
||||
typename value_type::array_type vec;
|
||||
@@ -171,6 +252,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
|
||||
const bool result2 = (vec == toml::find<typename value_type::array_type>(v, "key"));
|
||||
BOOST_CHECK(result2);
|
||||
|
||||
const auto moved = toml::find<typename value_type::array_type>(std::move(v), "key");
|
||||
const bool result3 = (vec == moved);
|
||||
BOOST_CHECK(result3);
|
||||
}
|
||||
{
|
||||
typename value_type::table_type tab;
|
||||
@@ -184,6 +269,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
tab["key3"] = value_type(123);
|
||||
const bool result2 = (tab == toml::find<typename value_type::table_type>(v, "key"));
|
||||
BOOST_CHECK(result2);
|
||||
|
||||
const auto moved = toml::find<typename value_type::table_type>(std::move(v), "key");
|
||||
const bool result3 = (tab == moved);
|
||||
BOOST_CHECK(result3);
|
||||
}
|
||||
{
|
||||
value_type v1(42);
|
||||
@@ -193,6 +282,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
||||
value_type v2(54);
|
||||
toml::find(v, "key") = v2;
|
||||
BOOST_CHECK(v2 == toml::find(v, "key"));
|
||||
|
||||
const auto moved = toml::find(std::move(v), "key");
|
||||
BOOST_CHECK(v2 == moved);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,15 +292,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_integer_type, value_type, test_value_typ
|
||||
{
|
||||
{
|
||||
value_type v{{"key", 42}};
|
||||
BOOST_TEST(int(42) == toml::find<int >(v, "key"));
|
||||
BOOST_TEST(short(42) == toml::find<short >(v, "key"));
|
||||
BOOST_TEST(char(42) == toml::find<char >(v, "key"));
|
||||
BOOST_TEST(unsigned(42) == toml::find<unsigned >(v, "key"));
|
||||
BOOST_TEST(long(42) == toml::find<long >(v, "key"));
|
||||
BOOST_TEST(std::int64_t(42) == toml::find<std::int64_t >(v, "key"));
|
||||
BOOST_TEST(int(42) == toml::find<int >(v, "key"));
|
||||
BOOST_TEST(short(42) == toml::find<short >(v, "key"));
|
||||
BOOST_TEST(char(42) == toml::find<char >(v, "key"));
|
||||
BOOST_TEST(unsigned(42) == toml::find<unsigned >(v, "key"));
|
||||
BOOST_TEST(long(42) == toml::find<long >(v, "key"));
|
||||
BOOST_TEST(std::int64_t(42) == toml::find<std::int64_t >(v, "key"));
|
||||
BOOST_TEST(std::uint64_t(42) == toml::find<std::uint64_t>(v, "key"));
|
||||
BOOST_TEST(std::int16_t(42) == toml::find<std::int16_t >(v, "key"));
|
||||
BOOST_TEST(std::int16_t(42) == toml::find<std::int16_t >(v, "key"));
|
||||
BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(v, "key"));
|
||||
BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(std::move(v), "key"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +312,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_ty
|
||||
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(v, "key"));
|
||||
BOOST_TEST(static_cast<double >(3.14) == toml::find<double >(v, "key"));
|
||||
BOOST_TEST(static_cast<long double>(3.14) == toml::find<long double>(v, "key"));
|
||||
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(std::move(v), "key"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,6 +330,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_string_type, value_type, test_value_type
|
||||
toml::find<std::string>(v, "key") += "bar";
|
||||
BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
|
||||
}
|
||||
{
|
||||
value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
|
||||
const auto moved = toml::find<std::string>(std::move(v), "key");
|
||||
BOOST_TEST("foo" == moved);
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
{
|
||||
@@ -292,6 +391,53 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array, value_type, test_value_types
|
||||
BOOST_TEST(2.71 == pr.second);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array, value_type, test_value_types)
|
||||
{
|
||||
value_type v1{{"key", {42, 54, 69, 72}}};
|
||||
value_type v2{{"key", {42, 54, 69, 72}}};
|
||||
value_type v3{{"key", {42, 54, 69, 72}}};
|
||||
value_type v4{{"key", {42, 54, 69, 72}}};
|
||||
value_type v5{{"key", {42, 54, 69, 72}}};
|
||||
|
||||
const std::vector<int> vec = toml::find<std::vector<int>>(std::move(v1), "key");
|
||||
const std::list<short> lst = toml::find<std::list<short>>(std::move(v2), "key");
|
||||
const std::deque<std::int64_t> deq = toml::find<std::deque<std::int64_t>>(std::move(v3), "key");
|
||||
|
||||
BOOST_TEST(42 == vec.at(0));
|
||||
BOOST_TEST(54 == vec.at(1));
|
||||
BOOST_TEST(69 == vec.at(2));
|
||||
BOOST_TEST(72 == vec.at(3));
|
||||
|
||||
std::list<short>::const_iterator iter = lst.begin();
|
||||
BOOST_TEST(static_cast<short>(42) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(54) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(69) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(72) == *(iter++));
|
||||
|
||||
BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
|
||||
BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
|
||||
BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
|
||||
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
||||
|
||||
std::array<int, 4> ary = toml::find<std::array<int, 4>>(std::move(v4), "key");
|
||||
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
||||
|
||||
std::tuple<int, short, unsigned, long> tpl =
|
||||
toml::find<std::tuple<int, short, unsigned, long>>(std::move(v5), "key");
|
||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
||||
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||
|
||||
value_type p{{"key", {3.14, 2.71}}};
|
||||
std::pair<double, double> pr = toml::find<std::pair<double, double> >(std::move(p), "key");
|
||||
BOOST_TEST(3.14 == pr.first);
|
||||
BOOST_TEST(2.71 == pr.second);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_value_types)
|
||||
{
|
||||
value_type v1{42, 54, 69, 72};
|
||||
@@ -323,62 +469,153 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_va
|
||||
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array_of_array, value_type, test_value_types)
|
||||
{
|
||||
value_type a1{42, 54, 69, 72};
|
||||
value_type a2{"foo", "bar", "baz"};
|
||||
value_type v1{{"key", {a1, a2}}};
|
||||
value_type v2{{"key", {a1, a2}}};
|
||||
|
||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||
toml::find<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v1), "key");
|
||||
|
||||
BOOST_TEST(p.first.at(0) == 42);
|
||||
BOOST_TEST(p.first.at(1) == 54);
|
||||
BOOST_TEST(p.first.at(2) == 69);
|
||||
BOOST_TEST(p.first.at(3) == 72);
|
||||
|
||||
BOOST_TEST(p.second.at(0) == "foo");
|
||||
BOOST_TEST(p.second.at(1) == "bar");
|
||||
BOOST_TEST(p.second.at(2) == "baz");
|
||||
|
||||
std::tuple<std::vector<int>, std::vector<std::string>> t =
|
||||
toml::find<std::tuple<std::vector<int>, std::vector<std::string>>>(std::move(v2), "key");
|
||||
|
||||
BOOST_TEST(std::get<0>(t).at(0) == 42);
|
||||
BOOST_TEST(std::get<0>(t).at(1) == 54);
|
||||
BOOST_TEST(std::get<0>(t).at(2) == 69);
|
||||
BOOST_TEST(std::get<0>(t).at(3) == 72);
|
||||
|
||||
BOOST_TEST(std::get<1>(t).at(0) == "foo");
|
||||
BOOST_TEST(std::get<1>(t).at(1) == "bar");
|
||||
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_table, value_type, test_value_types)
|
||||
{
|
||||
value_type v1{{"key", {
|
||||
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
|
||||
}}};
|
||||
const auto v = toml::find<std::map<std::string, int>>(v1, "key");
|
||||
BOOST_TEST(v.at("key1") == 1);
|
||||
BOOST_TEST(v.at("key2") == 2);
|
||||
BOOST_TEST(v.at("key3") == 3);
|
||||
BOOST_TEST(v.at("key4") == 4);
|
||||
{
|
||||
value_type v1{{"key", {
|
||||
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
|
||||
}}};
|
||||
const auto v = toml::find<std::map<std::string, int>>(v1, "key");
|
||||
BOOST_TEST(v.at("key1") == 1);
|
||||
BOOST_TEST(v.at("key2") == 2);
|
||||
BOOST_TEST(v.at("key3") == 3);
|
||||
BOOST_TEST(v.at("key4") == 4);
|
||||
}
|
||||
{
|
||||
value_type v1{{"key", {
|
||||
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
|
||||
}}};
|
||||
const auto v = toml::find<std::map<std::string, int>>(std::move(v1), "key");
|
||||
BOOST_TEST(v.at("key1") == 1);
|
||||
BOOST_TEST(v.at("key2") == 2);
|
||||
BOOST_TEST(v.at("key3") == 3);
|
||||
BOOST_TEST(v.at("key4") == 4);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_date, value_type, test_value_types)
|
||||
{
|
||||
value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::find<std::chrono::system_clock::time_point>(v1, "key"));
|
||||
{
|
||||
value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::find<std::chrono::system_clock::time_point>(v1, "key"));
|
||||
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 0;
|
||||
t.tm_min = 0;
|
||||
t.tm_sec = 0;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
BOOST_TEST(c == date);
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 0;
|
||||
t.tm_min = 0;
|
||||
t.tm_sec = 0;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
BOOST_TEST(c == date);
|
||||
}
|
||||
{
|
||||
value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key"));
|
||||
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 0;
|
||||
t.tm_min = 0;
|
||||
t.tm_sec = 0;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
BOOST_TEST(c == date);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_time, value_type, test_value_types)
|
||||
{
|
||||
value_type v1{{"key", toml::local_time{12, 30, 45}}};
|
||||
const auto time = toml::find<std::chrono::seconds>(v1, "key");
|
||||
BOOST_CHECK(time == std::chrono::hours(12) +
|
||||
std::chrono::minutes(30) + std::chrono::seconds(45));
|
||||
{
|
||||
value_type v1{{"key", toml::local_time{12, 30, 45}}};
|
||||
const auto time = toml::find<std::chrono::seconds>(v1, "key");
|
||||
BOOST_CHECK(time == std::chrono::hours(12) +
|
||||
std::chrono::minutes(30) + std::chrono::seconds(45));
|
||||
}
|
||||
{
|
||||
value_type v1{{"key", toml::local_time{12, 30, 45}}};
|
||||
const auto time = toml::find<std::chrono::seconds>(std::move(v1), "key");
|
||||
BOOST_CHECK(time == std::chrono::hours(12) +
|
||||
std::chrono::minutes(30) + std::chrono::seconds(45));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_datetime, value_type, test_value_types)
|
||||
{
|
||||
value_type v1{{"key", toml::local_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 45})}};
|
||||
{
|
||||
value_type v1{{"key", toml::local_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 45})}};
|
||||
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::find<std::chrono::system_clock::time_point>(v1, "key"));
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 12;
|
||||
t.tm_min = 30;
|
||||
t.tm_sec = 45;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
BOOST_TEST(c == date);
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::find<std::chrono::system_clock::time_point>(v1, "key"));
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 12;
|
||||
t.tm_min = 30;
|
||||
t.tm_sec = 45;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
BOOST_TEST(c == date);
|
||||
}
|
||||
{
|
||||
value_type v1{{"key", toml::local_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 45})}};
|
||||
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key"));
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 12;
|
||||
t.tm_min = 30;
|
||||
t.tm_sec = 45;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
BOOST_TEST(c == date);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types)
|
||||
@@ -428,5 +665,28 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_va
|
||||
BOOST_TEST(tm.tm_min == 30);
|
||||
BOOST_TEST(tm.tm_sec == 0);
|
||||
}
|
||||
|
||||
{
|
||||
value_type v1{{"key", toml::offset_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 0},
|
||||
toml::time_offset{-8, 0})}};
|
||||
// 2018-04-01T12:30:00-08:00
|
||||
// == 2018-04-01T20:30:00Z
|
||||
|
||||
const auto date = toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key");
|
||||
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||
|
||||
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
|
||||
BOOST_CHECK(tmp);
|
||||
const auto tm = *tmp;
|
||||
BOOST_TEST(tm.tm_year + 1900 == 2018);
|
||||
BOOST_TEST(tm.tm_mon + 1 == 4);
|
||||
BOOST_TEST(tm.tm_mday == 1);
|
||||
BOOST_TEST(tm.tm_hour == 20);
|
||||
BOOST_TEST(tm.tm_min == 30);
|
||||
BOOST_TEST(tm.tm_sec == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,350 +0,0 @@
|
||||
#define BOOST_TEST_MODULE "test_find_fuzzy"
|
||||
|
||||
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#else
|
||||
#define BOOST_TEST_NO_LIB
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
#endif
|
||||
|
||||
#include <toml.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_levenstein_distance)
|
||||
{
|
||||
const toml::levenstein_matcher lev(1);
|
||||
|
||||
// distance == 0
|
||||
{
|
||||
const std::string s1("foobar");
|
||||
const std::string s2 = s1;
|
||||
|
||||
BOOST_TEST(lev.distance(s1, s2) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
const std::string s1("foobar");
|
||||
const std::string s2("foobaz");
|
||||
|
||||
BOOST_TEST(lev.distance(s1, s2) == 1);
|
||||
}
|
||||
{
|
||||
const std::string s1("foobar"); // insertion (+x)
|
||||
const std::string s2("fooxbar");
|
||||
|
||||
BOOST_TEST(lev.distance(s1, s2) == 1);
|
||||
}
|
||||
{
|
||||
const std::string s1("foobar");
|
||||
const std::string s2("fooar"); // insertion(+b)
|
||||
|
||||
BOOST_TEST(lev.distance(s1, s2) == 1);
|
||||
}
|
||||
|
||||
// distance > 1
|
||||
{
|
||||
const std::string s1("foobar");
|
||||
const std::string s2("fooquux");
|
||||
|
||||
BOOST_TEST(lev.distance(s1, s2) == 4);
|
||||
}
|
||||
{
|
||||
const std::string s1("foobar");
|
||||
const std::string s2("fooqu");
|
||||
|
||||
BOOST_TEST(s1 != s2);
|
||||
BOOST_TEST(lev.distance(s1, s2) == 3);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_fuzzy)
|
||||
{
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", "value"} // typo! key -> keu
|
||||
};
|
||||
|
||||
BOOST_TEST(toml::find_fuzzy(v, "key") == toml::value("value"));
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy(v, "kiwi"), std::out_of_range);
|
||||
|
||||
static_assert(std::is_same<
|
||||
toml::value&, decltype(toml::find_fuzzy(v, "key"))>::value, "");
|
||||
|
||||
toml::find_fuzzy(v, "key") = "foobar";
|
||||
BOOST_TEST(toml::find(v, "keu") == toml::value("foobar"));
|
||||
}
|
||||
{
|
||||
const toml::value v{
|
||||
{"keu", "value"} // typo! key -> keu
|
||||
};
|
||||
|
||||
BOOST_TEST(toml::find_fuzzy(v, "key") == toml::value("value"));
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy(v, "kiwi"), std::out_of_range);
|
||||
|
||||
static_assert(std::is_same<
|
||||
toml::value const&, decltype(toml::find_fuzzy(v, "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", "value"} // typo! key -> keu
|
||||
};
|
||||
|
||||
BOOST_TEST(toml::find_fuzzy(std::move(v), "key") == toml::value("value"));
|
||||
|
||||
static_assert(std::is_same<
|
||||
toml::value&&, decltype(toml::find_fuzzy(std::move(v), "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", "value"} // typo! key -> keu
|
||||
};
|
||||
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy(std::move(v), "kiwi"), std::out_of_range);
|
||||
|
||||
static_assert(std::is_same<
|
||||
toml::value&&, decltype(toml::find_fuzzy(std::move(v), "key"))>::value, "");
|
||||
}
|
||||
|
||||
// find with conversion
|
||||
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", 42} // typo! key -> keu
|
||||
};
|
||||
|
||||
BOOST_TEST(toml::find_fuzzy<int>(v, "key") == 42);
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy<int>(v, "kiwi"), std::out_of_range);
|
||||
|
||||
static_assert(std::is_same<int,
|
||||
decltype(toml::find_fuzzy<int>(v, "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
const toml::value v{
|
||||
{"keu", 42} // typo! key -> keu
|
||||
};
|
||||
|
||||
BOOST_TEST(toml::find_fuzzy<int>(v, "key") == 42);
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy<int>(v, "kiwi"), std::out_of_range);
|
||||
|
||||
static_assert(std::is_same<int,
|
||||
decltype(toml::find_fuzzy<int>(v, "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", 42} // typo! key -> keu
|
||||
};
|
||||
|
||||
BOOST_TEST(toml::find_fuzzy<int>(std::move(v), "key") == 42);
|
||||
|
||||
static_assert(std::is_same<int,
|
||||
decltype(toml::find_fuzzy<int>(std::move(v), "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", 42} // typo! key -> keu
|
||||
};
|
||||
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy<int>(std::move(v), "kiwi"), std::out_of_range);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_fuzzy_throw)
|
||||
{
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", "value"}, // typo! key -> keu
|
||||
{"ky", "value"} // typo! key -> ky
|
||||
};
|
||||
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy(v, "key"), std::out_of_range);
|
||||
}
|
||||
{
|
||||
const toml::value v{
|
||||
{"keu", "value"}, // typo! key -> keu
|
||||
{"ky", "value"} // typo! key -> ky
|
||||
};
|
||||
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy(v, "key"), std::out_of_range);
|
||||
}
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", "value"}, // typo! key -> keu
|
||||
{"ky", "value"} // typo! key -> ky
|
||||
};
|
||||
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy(std::move(v), "key"), std::out_of_range);
|
||||
}
|
||||
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", 42}, // typo! key -> keu
|
||||
{"ky", 42} // typo! key -> ky
|
||||
};
|
||||
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy<int>(v, "key"), std::out_of_range);
|
||||
}
|
||||
{
|
||||
const toml::value v{
|
||||
{"keu", 42}, // typo! key -> keu
|
||||
{"ky", 42} // typo! key -> ky
|
||||
};
|
||||
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy<int>(v, "key"), std::out_of_range);
|
||||
}
|
||||
{
|
||||
toml::value v{
|
||||
{"keu", 42}, // typo! key -> keu
|
||||
{"ky", 42} // typo! key -> ky
|
||||
};
|
||||
|
||||
BOOST_CHECK_THROW(toml::find_fuzzy<int>(std::move(v), "key"), std::out_of_range);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_throw_typo_aware_exception)
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
const toml::levenstein_matcher lev(1);
|
||||
{
|
||||
toml::value v = u8R"(
|
||||
keu = "value"
|
||||
)"_toml;
|
||||
|
||||
BOOST_CHECK_THROW(toml::find(v, "key", lev), std::out_of_range);
|
||||
try
|
||||
{
|
||||
const auto& ret = toml::find(v, "key", lev);
|
||||
(void)ret; // suppress unused variable
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
// exception.what() should include the typo-ed key name
|
||||
const std::string what(oor.what());
|
||||
BOOST_TEST(what.find("keu") != std::string::npos);
|
||||
|
||||
// std::cout << what << std::endl;
|
||||
}
|
||||
static_assert(std::is_same<
|
||||
toml::value&, decltype(toml::find(v, "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
const toml::value v = u8R"(
|
||||
keu = "value"
|
||||
)"_toml;
|
||||
|
||||
BOOST_CHECK_THROW(toml::find(v, "key", lev), std::out_of_range);
|
||||
try
|
||||
{
|
||||
const auto& ret = toml::find(v, "key", lev);
|
||||
(void)ret;
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
// exception.what() should include the typo-ed key name
|
||||
const std::string what(oor.what());
|
||||
BOOST_TEST(what.find("keu") != std::string::npos);
|
||||
|
||||
// std::cout << what << std::endl;
|
||||
}
|
||||
static_assert(std::is_same<
|
||||
toml::value const&, decltype(toml::find(v, "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
toml::value v = u8R"(
|
||||
keu = "value"
|
||||
)"_toml;
|
||||
|
||||
bool thrown = false; // since it moves, we need to check both once
|
||||
try
|
||||
{
|
||||
const auto& ret = toml::find(std::move(v), "key", lev);
|
||||
(void)ret;
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
// exception.what() should include the typo-ed key name
|
||||
const std::string what(oor.what());
|
||||
BOOST_TEST(what.find("keu") != std::string::npos);
|
||||
thrown = true;
|
||||
|
||||
// std::cout << what << std::endl;
|
||||
}
|
||||
BOOST_TEST(thrown);
|
||||
static_assert(std::is_same<
|
||||
toml::value&, decltype(toml::find(v, "key"))>::value, "");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_throw_conversion_typo_aware_exception)
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
const toml::levenstein_matcher lev(1);
|
||||
{
|
||||
toml::value v = u8R"(
|
||||
keu = 42
|
||||
)"_toml;
|
||||
|
||||
BOOST_CHECK_THROW(toml::find<int>(v, "key", lev), std::out_of_range);
|
||||
try
|
||||
{
|
||||
const auto& ret = toml::find<int>(v, "key", lev);
|
||||
(void)ret; // suppress unused variable
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
// exception.what() should include the typo-ed key name
|
||||
const std::string what(oor.what());
|
||||
BOOST_TEST(what.find("keu") != std::string::npos);
|
||||
|
||||
// std::cout << what << std::endl;
|
||||
}
|
||||
static_assert(std::is_same<int,
|
||||
decltype(toml::find<int>(v, "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
const toml::value v = u8R"(
|
||||
keu = 42
|
||||
)"_toml;
|
||||
|
||||
BOOST_CHECK_THROW(toml::find<int>(v, "key", lev), std::out_of_range);
|
||||
try
|
||||
{
|
||||
const auto& ret = toml::find<int>(v, "key", lev);
|
||||
(void)ret;
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
// exception.what() should include the typo-ed key name
|
||||
const std::string what(oor.what());
|
||||
BOOST_TEST(what.find("keu") != std::string::npos);
|
||||
|
||||
// std::cout << what << std::endl;
|
||||
}
|
||||
static_assert(std::is_same<int,
|
||||
decltype(toml::find<int>(v, "key"))>::value, "");
|
||||
}
|
||||
{
|
||||
toml::value v = u8R"(
|
||||
keu = 42
|
||||
)"_toml;
|
||||
|
||||
bool thrown = false; // since it moves, we need to check both once
|
||||
try
|
||||
{
|
||||
const auto& ret = toml::find<int>(std::move(v), "key", lev);
|
||||
(void)ret;
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
// exception.what() should include the typo-ed key name
|
||||
const std::string what(oor.what());
|
||||
BOOST_TEST(what.find("keu") != std::string::npos);
|
||||
thrown = true;
|
||||
|
||||
// std::cout << what << std::endl;
|
||||
}
|
||||
BOOST_TEST(thrown);
|
||||
static_assert(std::is_same<int,
|
||||
decltype(toml::find<int>(v, "key"))>::value, "");
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,55 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types)
|
||||
}
|
||||
#undef TOML11_TEST_FIND_OR_EXACT
|
||||
|
||||
#define TOML11_TEST_FIND_OR_MOVE(toml_type, init_expr, opt_expr) \
|
||||
{ \
|
||||
using namespace test; \
|
||||
const toml::toml_type init init_expr ; \
|
||||
toml::toml_type opt opt_expr ; \
|
||||
value_type v{{"key", init}}; \
|
||||
BOOST_TEST(init != opt); \
|
||||
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));\
|
||||
BOOST_TEST(init == moved); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move, value_type, test_value_types)
|
||||
{
|
||||
TOML11_TEST_FIND_OR_MOVE(boolean, ( true), (false))
|
||||
TOML11_TEST_FIND_OR_MOVE(integer, ( 42), ( 54))
|
||||
TOML11_TEST_FIND_OR_MOVE(floating, ( 3.14), ( 2.71))
|
||||
TOML11_TEST_FIND_OR_MOVE(string, ("foo"), ("bar"))
|
||||
TOML11_TEST_FIND_OR_MOVE(local_time, (12, 30, 45), (6, 0, 30))
|
||||
TOML11_TEST_FIND_OR_MOVE(local_date, (2019, toml::month_t::Apr, 1),
|
||||
(1999, toml::month_t::Jan, 2))
|
||||
TOML11_TEST_FIND_OR_MOVE(local_datetime,
|
||||
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
|
||||
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
|
||||
)
|
||||
TOML11_TEST_FIND_OR_MOVE(offset_datetime,
|
||||
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
|
||||
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
|
||||
)
|
||||
{
|
||||
typename value_type::array_type init{1,2,3,4,5};
|
||||
typename value_type::array_type opt {6,7,8,9,10};
|
||||
value_type v{{"key", init}};
|
||||
BOOST_TEST(init != opt);
|
||||
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
|
||||
BOOST_TEST(init == moved);
|
||||
}
|
||||
{
|
||||
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
|
||||
typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
|
||||
value_type v{{"key", init}};
|
||||
BOOST_TEST(init != opt);
|
||||
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
|
||||
BOOST_TEST(init == moved);
|
||||
}
|
||||
}
|
||||
#undef TOML11_TEST_FIND_OR_MOVE
|
||||
|
||||
|
||||
#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\
|
||||
{ \
|
||||
using namespace test; \
|
||||
@@ -304,10 +353,20 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_type
|
||||
BOOST_AUTO_TEST_CASE(test_find_or_integer)
|
||||
{
|
||||
{
|
||||
toml::value v = toml::table{{"num", 42}};
|
||||
toml::value v{{"num", 42}};
|
||||
BOOST_TEST(42u == toml::find_or(v, "num", 0u));
|
||||
BOOST_TEST(0u == toml::find_or(v, "foo", 0u));
|
||||
}
|
||||
{
|
||||
toml::value v{{"num", 42}};
|
||||
const auto moved = toml::find_or(std::move(v), "num", 0u);
|
||||
BOOST_TEST(42u == moved);
|
||||
}
|
||||
{
|
||||
toml::value v{{"num", 42}};
|
||||
const auto moved = toml::find_or(std::move(v), "foo", 0u);
|
||||
BOOST_TEST(0u == moved);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_or_floating)
|
||||
@@ -318,6 +377,14 @@ BOOST_AUTO_TEST_CASE(test_find_or_floating)
|
||||
BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f));
|
||||
BOOST_TEST(static_cast<float>(double(3.14)) == toml::find_or(v2, "key", 2.71f));
|
||||
}
|
||||
{
|
||||
toml::value v1{{"key", 42}};
|
||||
toml::value v2{{"key", 3.14}};
|
||||
const auto moved1 = toml::find_or(std::move(v1), "key", 2.71f);
|
||||
const auto moved2 = toml::find_or(std::move(v2), "key", 2.71f);
|
||||
BOOST_TEST(2.71f == moved1);
|
||||
BOOST_TEST(static_cast<float>(double(3.14)) == moved2);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_or_string)
|
||||
@@ -345,6 +412,32 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
|
||||
s1 = "bazqux"; // restoring moved value
|
||||
BOOST_TEST("bazqux" == toml::find_or(std::move(v2), "key", std::move(s1)));
|
||||
}
|
||||
{
|
||||
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||
toml::value v2 = toml::table{{"key", 42}};
|
||||
|
||||
std::string s1("bazqux");
|
||||
|
||||
const auto moved1 = toml::find_or(std::move(v1), "key", s1);
|
||||
const auto moved2 = toml::find_or(std::move(v2), "key", s1);
|
||||
|
||||
BOOST_TEST("foobar" == moved1);
|
||||
BOOST_TEST("bazqux" == moved2);
|
||||
}
|
||||
{
|
||||
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||
toml::value v2 = toml::table{{"key", 42}};
|
||||
|
||||
std::string s1("bazqux");
|
||||
std::string s2("bazqux");
|
||||
|
||||
const auto moved1 = toml::find_or(std::move(v1), "key", std::move(s1));
|
||||
const auto moved2 = toml::find_or(std::move(v2), "key", std::move(s2));
|
||||
|
||||
BOOST_TEST("foobar" == moved1);
|
||||
BOOST_TEST("bazqux" == moved2);
|
||||
}
|
||||
|
||||
// string literal
|
||||
{
|
||||
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||
@@ -357,6 +450,28 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
|
||||
BOOST_TEST("foobar" == toml::find_or(v1, "key", lit));
|
||||
BOOST_TEST("bazqux" == toml::find_or(v2, "key", lit));
|
||||
}
|
||||
{
|
||||
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||
toml::value v2 = toml::table{{"key",42}};
|
||||
|
||||
const auto moved1 = toml::find_or(std::move(v1), "key", "bazqux");
|
||||
const auto moved2 = toml::find_or(std::move(v2), "key", "bazqux");
|
||||
|
||||
BOOST_TEST("foobar" == moved1);
|
||||
BOOST_TEST("bazqux" == moved2);
|
||||
}
|
||||
{
|
||||
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||
toml::value v2 = toml::table{{"key",42}};
|
||||
|
||||
const char* lit = "bazqux";
|
||||
const auto moved1 = toml::find_or(std::move(v1), "key", lit);
|
||||
const auto moved2 = toml::find_or(std::move(v2), "key", lit);
|
||||
|
||||
BOOST_TEST("foobar" == moved1);
|
||||
BOOST_TEST("bazqux" == moved2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_find_or_map)
|
||||
@@ -377,7 +492,7 @@ BOOST_AUTO_TEST_CASE(test_find_or_map)
|
||||
BOOST_TEST(key.at("key") == "value");
|
||||
}
|
||||
{
|
||||
const toml::value v1{
|
||||
toml::value v1{
|
||||
{"key", {{"key", "value"}}}
|
||||
};
|
||||
|
||||
@@ -390,4 +505,35 @@ BOOST_AUTO_TEST_CASE(test_find_or_map)
|
||||
BOOST_TEST(key.size() == 1u);
|
||||
BOOST_TEST(key.at("key") == "value");
|
||||
}
|
||||
|
||||
{
|
||||
toml::value v1{
|
||||
{"key", {{"key", "value"}}}
|
||||
};
|
||||
toml::value v2(v1);
|
||||
|
||||
const auto key = toml::find_or(std::move(v1), "key", map_type{});
|
||||
const auto key2 = toml::find_or(std::move(v2), "key2", map_type{});
|
||||
|
||||
BOOST_TEST(!key.empty());
|
||||
BOOST_TEST(key2.empty());
|
||||
|
||||
BOOST_TEST(key.size() == 1u);
|
||||
BOOST_TEST(key.at("key") == "value");
|
||||
}
|
||||
{
|
||||
toml::value v1{
|
||||
{"key", {{"key", "value"}}}
|
||||
};
|
||||
toml::value v2(v1);
|
||||
|
||||
const auto key = toml::find_or<map_type>(std::move(v1), "key", map_type{});
|
||||
const auto key2 = toml::find_or<map_type>(std::move(v2), "key2", map_type{});
|
||||
|
||||
BOOST_TEST(!key.empty());
|
||||
BOOST_TEST(key2.empty());
|
||||
|
||||
BOOST_TEST(key.size() == 1u);
|
||||
BOOST_TEST(key.at("key") == "value");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
|
||||
toml::get<toml::boolean>(v) = false;
|
||||
BOOST_TEST(false == toml::get<toml::boolean>(v));
|
||||
|
||||
toml::boolean x = toml::get<toml::boolean>(std::move(v));
|
||||
BOOST_TEST(false == x);
|
||||
}
|
||||
{
|
||||
value_type v(42);
|
||||
@@ -38,6 +41,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
|
||||
toml::get<toml::integer>(v) = 54;
|
||||
BOOST_TEST(toml::integer(54) == toml::get<toml::integer>(v));
|
||||
|
||||
toml::integer x = toml::get<toml::integer>(std::move(v));
|
||||
BOOST_TEST(toml::integer(54) == x);
|
||||
}
|
||||
{
|
||||
value_type v(3.14);
|
||||
@@ -45,6 +51,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
|
||||
toml::get<toml::floating>(v) = 2.71;
|
||||
BOOST_TEST(toml::floating(2.71) == toml::get<toml::floating>(v));
|
||||
|
||||
toml::floating x = toml::get<toml::floating>(std::move(v));
|
||||
BOOST_TEST(toml::floating(2.71) == x);
|
||||
}
|
||||
{
|
||||
value_type v("foo");
|
||||
@@ -54,6 +63,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
toml::get<toml::string>(v).str += "bar";
|
||||
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
|
||||
toml::get<toml::string>(v));
|
||||
|
||||
toml::string x = toml::get<toml::string>(std::move(v));
|
||||
BOOST_TEST(toml::string("foobar") == x);
|
||||
}
|
||||
{
|
||||
value_type v("foo", toml::string_t::literal);
|
||||
@@ -63,6 +75,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
toml::get<toml::string>(v).str += "bar";
|
||||
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
|
||||
toml::get<toml::string>(v));
|
||||
|
||||
toml::string x = toml::get<toml::string>(std::move(v));
|
||||
BOOST_TEST(toml::string("foobar", toml::string_t::literal) == x);
|
||||
}
|
||||
{
|
||||
toml::local_date d(2018, toml::month_t::Apr, 22);
|
||||
@@ -72,6 +87,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
toml::get<toml::local_date>(v).year = 2017;
|
||||
d.year = 2017;
|
||||
BOOST_TEST(d == toml::get<toml::local_date>(v));
|
||||
|
||||
toml::local_date x = toml::get<toml::local_date>(std::move(v));
|
||||
BOOST_TEST(d == x);
|
||||
}
|
||||
{
|
||||
toml::local_time t(12, 30, 45);
|
||||
@@ -81,6 +99,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
toml::get<toml::local_time>(v).hour = 9;
|
||||
t.hour = 9;
|
||||
BOOST_TEST(t == toml::get<toml::local_time>(v));
|
||||
|
||||
toml::local_time x = toml::get<toml::local_time>(std::move(v));
|
||||
BOOST_TEST(t == x);
|
||||
}
|
||||
{
|
||||
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
||||
@@ -91,6 +112,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
toml::get<toml::local_datetime>(v).date.year = 2017;
|
||||
dt.date.year = 2017;
|
||||
BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
|
||||
|
||||
toml::local_datetime x = toml::get<toml::local_datetime>(std::move(v));
|
||||
BOOST_TEST(dt == x);
|
||||
}
|
||||
{
|
||||
toml::offset_datetime dt(toml::local_datetime(
|
||||
@@ -102,6 +126,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
toml::get<toml::offset_datetime>(v).date.year = 2017;
|
||||
dt.date.year = 2017;
|
||||
BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
|
||||
|
||||
toml::offset_datetime x = toml::get<toml::offset_datetime>(std::move(v));
|
||||
BOOST_TEST(dt == x);
|
||||
}
|
||||
{
|
||||
using array_type = typename value_type::array_type;
|
||||
@@ -114,6 +141,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
toml::get<array_type>(v).push_back(value_type(123));
|
||||
vec.push_back(value_type(123));
|
||||
BOOST_TEST(vec == toml::get<array_type>(v));
|
||||
|
||||
array_type x = toml::get<array_type>(std::move(v));
|
||||
BOOST_TEST(vec == x);
|
||||
}
|
||||
{
|
||||
using table_type = typename value_type::table_type;
|
||||
@@ -126,6 +156,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
toml::get<table_type>(v)["key3"] = value_type(123);
|
||||
tab["key3"] = value_type(123);
|
||||
BOOST_TEST(tab == toml::get<table_type>(v));
|
||||
|
||||
table_type x = toml::get<table_type>(std::move(v));
|
||||
BOOST_TEST(tab == x);
|
||||
}
|
||||
{
|
||||
value_type v1(42);
|
||||
@@ -134,6 +167,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
||||
value_type v2(54);
|
||||
toml::get<value_type>(v1) = v2;
|
||||
BOOST_TEST(v2 == toml::get<value_type>(v1));
|
||||
|
||||
value_type x = toml::get<value_type>(std::move(v1));
|
||||
BOOST_TEST(v2 == x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +186,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_integer_type, value_type, test_value_type
|
||||
BOOST_TEST(std::uint64_t(42) == toml::get<std::uint64_t>(v));
|
||||
BOOST_TEST(std::int16_t(42) == toml::get<std::int16_t >(v));
|
||||
BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(v));
|
||||
|
||||
BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(std::move(v)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,6 +198,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_typ
|
||||
BOOST_TEST(static_cast<float >(3.14) == toml::get<float >(v));
|
||||
BOOST_TEST(static_cast<double >(3.14) == toml::get<double >(v));
|
||||
BOOST_TEST(static_cast<long double>(3.14) == toml::get<long double>(v));
|
||||
|
||||
BOOST_TEST(3.14f == toml::get<float>(std::move(v)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,12 +210,18 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types
|
||||
BOOST_TEST("foo" == toml::get<std::string>(v));
|
||||
toml::get<std::string>(v) += "bar";
|
||||
BOOST_TEST("foobar" == toml::get<std::string>(v));
|
||||
|
||||
const auto x = toml::get<std::string>(std::move(v));
|
||||
BOOST_TEST("foobar" == x);
|
||||
}
|
||||
{
|
||||
value_type v("foo", toml::string_t::literal);
|
||||
BOOST_TEST("foo" == toml::get<std::string>(v));
|
||||
toml::get<std::string>(v) += "bar";
|
||||
BOOST_TEST("foobar" == toml::get<std::string>(v));
|
||||
|
||||
const auto x = toml::get<std::string>(std::move(v));
|
||||
BOOST_TEST("foobar" == x);
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
@@ -192,92 +238,176 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
|
||||
{
|
||||
const value_type v{42, 54, 69, 72};
|
||||
{
|
||||
const value_type v{42, 54, 69, 72};
|
||||
|
||||
const std::vector<int> vec = toml::get<std::vector<int>>(v);
|
||||
const std::list<short> lst = toml::get<std::list<short>>(v);
|
||||
const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v);
|
||||
const std::vector<int> vec = toml::get<std::vector<int>>(v);
|
||||
const std::list<short> lst = toml::get<std::list<short>>(v);
|
||||
const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v);
|
||||
|
||||
BOOST_TEST(42 == vec.at(0));
|
||||
BOOST_TEST(54 == vec.at(1));
|
||||
BOOST_TEST(69 == vec.at(2));
|
||||
BOOST_TEST(72 == vec.at(3));
|
||||
BOOST_TEST(42 == vec.at(0));
|
||||
BOOST_TEST(54 == vec.at(1));
|
||||
BOOST_TEST(69 == vec.at(2));
|
||||
BOOST_TEST(72 == vec.at(3));
|
||||
|
||||
std::list<short>::const_iterator iter = lst.begin();
|
||||
BOOST_TEST(static_cast<short>(42) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(54) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(69) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(72) == *(iter++));
|
||||
std::list<short>::const_iterator iter = lst.begin();
|
||||
BOOST_TEST(static_cast<short>(42) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(54) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(69) == *(iter++));
|
||||
BOOST_TEST(static_cast<short>(72) == *(iter++));
|
||||
|
||||
BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
|
||||
BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
|
||||
BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
|
||||
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
||||
BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
|
||||
BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
|
||||
BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
|
||||
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
||||
|
||||
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
|
||||
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
||||
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
|
||||
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
||||
|
||||
std::tuple<int, short, unsigned, long> tpl =
|
||||
toml::get<std::tuple<int, short, unsigned, long>>(v);
|
||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
||||
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||
std::tuple<int, short, unsigned, long> tpl =
|
||||
toml::get<std::tuple<int, short, unsigned, long>>(v);
|
||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
||||
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||
|
||||
const value_type p{3.14, 2.71};
|
||||
std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
|
||||
BOOST_TEST(3.14 == pr.first);
|
||||
BOOST_TEST(2.71 == pr.second);
|
||||
const value_type p{3.14, 2.71};
|
||||
std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
|
||||
BOOST_TEST(3.14 == pr.first);
|
||||
BOOST_TEST(2.71 == pr.second);
|
||||
}
|
||||
|
||||
{
|
||||
value_type v{42, 54, 69, 72};
|
||||
const std::vector<int> vec = toml::get<std::vector<int>>(std::move(v));
|
||||
BOOST_TEST(42 == vec.at(0));
|
||||
BOOST_TEST(54 == vec.at(1));
|
||||
BOOST_TEST(69 == vec.at(2));
|
||||
BOOST_TEST(72 == vec.at(3));
|
||||
}
|
||||
{
|
||||
value_type v{42, 54, 69, 72};
|
||||
const std::deque<int> deq = toml::get<std::deque<int>>(std::move(v));
|
||||
BOOST_TEST(42 == deq.at(0));
|
||||
BOOST_TEST(54 == deq.at(1));
|
||||
BOOST_TEST(69 == deq.at(2));
|
||||
BOOST_TEST(72 == deq.at(3));
|
||||
}
|
||||
{
|
||||
value_type v{42, 54, 69, 72};
|
||||
const std::list<int> lst = toml::get<std::list<int>>(std::move(v));
|
||||
std::list<int>::const_iterator iter = lst.begin();
|
||||
BOOST_TEST(42 == *(iter++));
|
||||
BOOST_TEST(54 == *(iter++));
|
||||
BOOST_TEST(69 == *(iter++));
|
||||
BOOST_TEST(72 == *(iter++));
|
||||
}
|
||||
{
|
||||
value_type v{42, 54, 69, 72};
|
||||
std::array<int, 4> ary = toml::get<std::array<int, 4>>(std::move(v));
|
||||
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
||||
}
|
||||
{
|
||||
value_type v{42, 54, 69, 72};
|
||||
std::tuple<int, short, unsigned, long> tpl =
|
||||
toml::get<std::tuple<int, short, unsigned, long>>(std::move(v));
|
||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
||||
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_value_types)
|
||||
{
|
||||
const value_type v1{42, 54, 69, 72};
|
||||
const value_type v2{"foo", "bar", "baz"};
|
||||
const value_type v{v1, v2};
|
||||
{
|
||||
const value_type v1{42, 54, 69, 72};
|
||||
const value_type v2{"foo", "bar", "baz"};
|
||||
const value_type v{v1, v2};
|
||||
|
||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
|
||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
|
||||
|
||||
BOOST_TEST(p.first.at(0) == 42);
|
||||
BOOST_TEST(p.first.at(1) == 54);
|
||||
BOOST_TEST(p.first.at(2) == 69);
|
||||
BOOST_TEST(p.first.at(3) == 72);
|
||||
BOOST_TEST(p.first.size() == 4u);
|
||||
BOOST_TEST(p.first.at(0) == 42);
|
||||
BOOST_TEST(p.first.at(1) == 54);
|
||||
BOOST_TEST(p.first.at(2) == 69);
|
||||
BOOST_TEST(p.first.at(3) == 72);
|
||||
|
||||
BOOST_TEST(p.second.at(0) == "foo");
|
||||
BOOST_TEST(p.second.at(1) == "bar");
|
||||
BOOST_TEST(p.second.at(2) == "baz");
|
||||
BOOST_TEST(p.second.size() == 3u);
|
||||
BOOST_TEST(p.second.at(0) == "foo");
|
||||
BOOST_TEST(p.second.at(1) == "bar");
|
||||
BOOST_TEST(p.second.at(2) == "baz");
|
||||
|
||||
std::tuple<std::vector<int>, std::vector<std::string>> t =
|
||||
toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v);
|
||||
std::tuple<std::vector<int>, std::vector<std::string>> t =
|
||||
toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v);
|
||||
|
||||
BOOST_TEST(std::get<0>(t).at(0) == 42);
|
||||
BOOST_TEST(std::get<0>(t).at(1) == 54);
|
||||
BOOST_TEST(std::get<0>(t).at(2) == 69);
|
||||
BOOST_TEST(std::get<0>(t).at(3) == 72);
|
||||
BOOST_TEST(std::get<0>(t).at(0) == 42);
|
||||
BOOST_TEST(std::get<0>(t).at(1) == 54);
|
||||
BOOST_TEST(std::get<0>(t).at(2) == 69);
|
||||
BOOST_TEST(std::get<0>(t).at(3) == 72);
|
||||
|
||||
BOOST_TEST(std::get<1>(t).at(0) == "foo");
|
||||
BOOST_TEST(std::get<1>(t).at(1) == "bar");
|
||||
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
||||
BOOST_TEST(std::get<1>(t).at(0) == "foo");
|
||||
BOOST_TEST(std::get<1>(t).at(1) == "bar");
|
||||
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
||||
}
|
||||
{
|
||||
const value_type v1{42, 54, 69, 72};
|
||||
const value_type v2{"foo", "bar", "baz"};
|
||||
value_type v{v1, v2};
|
||||
|
||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v));
|
||||
|
||||
BOOST_TEST(p.first.size() == 4u);
|
||||
BOOST_TEST(p.first.at(0) == 42);
|
||||
BOOST_TEST(p.first.at(1) == 54);
|
||||
BOOST_TEST(p.first.at(2) == 69);
|
||||
BOOST_TEST(p.first.at(3) == 72);
|
||||
|
||||
BOOST_TEST(p.second.size() == 3u);
|
||||
BOOST_TEST(p.second.at(0) == "foo");
|
||||
BOOST_TEST(p.second.at(1) == "bar");
|
||||
BOOST_TEST(p.second.at(2) == "baz");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types)
|
||||
{
|
||||
const value_type v1{
|
||||
{"key1", 1},
|
||||
{"key2", 2},
|
||||
{"key3", 3},
|
||||
{"key4", 4}
|
||||
};
|
||||
{
|
||||
const value_type v1{
|
||||
{"key1", 1},
|
||||
{"key2", 2},
|
||||
{"key3", 3},
|
||||
{"key4", 4}
|
||||
};
|
||||
|
||||
const auto v = toml::get<std::map<std::string, int>>(v1);
|
||||
BOOST_TEST(v.at("key1") == 1);
|
||||
BOOST_TEST(v.at("key2") == 2);
|
||||
BOOST_TEST(v.at("key3") == 3);
|
||||
BOOST_TEST(v.at("key4") == 4);
|
||||
}
|
||||
{
|
||||
value_type v1{
|
||||
{"key1", 1},
|
||||
{"key2", 2},
|
||||
{"key3", 3},
|
||||
{"key4", 4}
|
||||
};
|
||||
const auto v = toml::get<std::map<std::string, int>>(std::move(v1));
|
||||
BOOST_TEST(v.at("key1") == 1);
|
||||
BOOST_TEST(v.at("key2") == 2);
|
||||
BOOST_TEST(v.at("key3") == 3);
|
||||
BOOST_TEST(v.at("key4") == 4);
|
||||
}
|
||||
|
||||
const auto v = toml::get<std::map<std::string, int>>(v1);
|
||||
BOOST_TEST(v.at("key1") == 1);
|
||||
BOOST_TEST(v.at("key2") == 2);
|
||||
BOOST_TEST(v.at("key3") == 3);
|
||||
BOOST_TEST(v.at("key4") == 4);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types)
|
||||
|
||||
@@ -25,6 +25,11 @@ using test_value_types = std::tuple<
|
||||
|
||||
namespace test
|
||||
{
|
||||
// to compare result values in BOOST_TEST().
|
||||
//
|
||||
// BOOST_TEST outputs the expected and actual values. Thus it includes the
|
||||
// output stream operator inside. To compile it, we need operator<<s for
|
||||
// containers to compare.
|
||||
template<typename charT, typename traits, typename T, typename Alloc>
|
||||
std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
|
||||
@@ -121,6 +126,55 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_exact, value_type, test_value_types)
|
||||
}
|
||||
#undef TOML11_TEST_GET_OR_EXACT
|
||||
|
||||
#define TOML11_TEST_GET_OR_MOVE_EXACT(toml_type, init_expr, opt_expr)\
|
||||
{ \
|
||||
using namespace test; \
|
||||
const toml::toml_type init init_expr ; \
|
||||
toml::toml_type opt opt_expr ; \
|
||||
value_type v(init); \
|
||||
BOOST_TEST(init != opt); \
|
||||
const auto opt_ = toml::get_or(std::move(v), std::move(opt));\
|
||||
BOOST_TEST(init == opt_); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_move, value_type, test_value_types)
|
||||
{
|
||||
TOML11_TEST_GET_OR_MOVE_EXACT(boolean, ( true), (false))
|
||||
TOML11_TEST_GET_OR_MOVE_EXACT(integer, ( 42), ( 54))
|
||||
TOML11_TEST_GET_OR_MOVE_EXACT(floating, ( 3.14), ( 2.71))
|
||||
TOML11_TEST_GET_OR_MOVE_EXACT(string, ("foo"), ("bar"))
|
||||
TOML11_TEST_GET_OR_MOVE_EXACT(local_time, (12, 30, 45), (6, 0, 30))
|
||||
TOML11_TEST_GET_OR_MOVE_EXACT(local_date, (2019, toml::month_t::Apr, 1),
|
||||
(1999, toml::month_t::Jan, 2))
|
||||
TOML11_TEST_GET_OR_MOVE_EXACT(local_datetime,
|
||||
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
|
||||
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
|
||||
)
|
||||
TOML11_TEST_GET_OR_MOVE_EXACT(offset_datetime,
|
||||
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
|
||||
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
|
||||
)
|
||||
{
|
||||
const typename value_type::array_type init{1,2,3,4,5};
|
||||
typename value_type::array_type opt {6,7,8,9,10};
|
||||
value_type v(init);
|
||||
BOOST_TEST(init != opt);
|
||||
const auto opt_ = toml::get_or(std::move(v), std::move(opt));
|
||||
BOOST_TEST(init == opt_);
|
||||
}
|
||||
{
|
||||
const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
|
||||
typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
|
||||
value_type v(init);
|
||||
BOOST_TEST(init != opt);
|
||||
const auto opt_ = toml::get_or(std::move(v), std::move(opt));
|
||||
BOOST_TEST(init == opt_);
|
||||
}
|
||||
}
|
||||
#undef TOML11_TEST_GET_OR_MOVE_EXACT
|
||||
|
||||
|
||||
#define TOML11_TEST_GET_OR_MODIFY(toml_type, init_expr, opt_expr)\
|
||||
{ \
|
||||
using namespace test; \
|
||||
@@ -309,6 +363,13 @@ BOOST_AUTO_TEST_CASE(test_get_or_integer)
|
||||
BOOST_TEST(42u == toml::get_or(v1, 0u));
|
||||
BOOST_TEST(0u == toml::get_or(v2, 0u));
|
||||
}
|
||||
{
|
||||
toml::value v1(42);
|
||||
toml::value v2(3.14);
|
||||
BOOST_TEST(42u == toml::get_or(std::move(v1), 0u));
|
||||
BOOST_TEST(0u == toml::get_or(std::move(v2), 0u));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_get_or_floating)
|
||||
@@ -319,6 +380,12 @@ BOOST_AUTO_TEST_CASE(test_get_or_floating)
|
||||
BOOST_TEST(2.71f == toml::get_or(v1, 2.71f));
|
||||
BOOST_TEST(static_cast<float>(v2.as_floating()) == toml::get_or(v2, 2.71f));
|
||||
}
|
||||
{
|
||||
toml::value v1(42);
|
||||
toml::value v2(3.14);
|
||||
BOOST_TEST(2.71f == toml::get_or(std::move(v1), 2.71f));
|
||||
BOOST_TEST(static_cast<float>(3.14) == toml::get_or(std::move(v2), 2.71f));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_get_or_string)
|
||||
@@ -345,7 +412,16 @@ BOOST_AUTO_TEST_CASE(test_get_or_string)
|
||||
BOOST_TEST("foobar" == toml::get_or(v1, std::move(s1)));
|
||||
BOOST_TEST("bazqux" == toml::get_or(v2, std::move(s1)));
|
||||
}
|
||||
{
|
||||
toml::value v1("foobar");
|
||||
toml::value v2(42);
|
||||
|
||||
std::string s1("bazqux");
|
||||
const std::string s2("bazqux");
|
||||
|
||||
BOOST_TEST("foobar" == toml::get_or(std::move(v1), s1));
|
||||
BOOST_TEST("bazqux" == toml::get_or(std::move(v2), s1));
|
||||
}
|
||||
{
|
||||
toml::value v1("foobar");
|
||||
toml::value v2(42);
|
||||
@@ -357,4 +433,20 @@ BOOST_AUTO_TEST_CASE(test_get_or_string)
|
||||
BOOST_TEST("foobar" == toml::get_or(v1, lit));
|
||||
BOOST_TEST("bazqux" == toml::get_or(v2, lit));
|
||||
}
|
||||
{
|
||||
toml::value v1("foobar");
|
||||
toml::value v2(42);
|
||||
|
||||
BOOST_TEST("foobar" == toml::get_or(std::move(v1), "bazqux"));
|
||||
BOOST_TEST("bazqux" == toml::get_or(std::move(v2), "bazqux"));
|
||||
}
|
||||
{
|
||||
toml::value v1("foobar");
|
||||
toml::value v2(42);
|
||||
|
||||
const char* lit = "bazqux";
|
||||
BOOST_TEST("foobar" == toml::get_or(v1, lit));
|
||||
BOOST_TEST("bazqux" == toml::get_or(v2, lit));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,27 +35,35 @@ BOOST_AUTO_TEST_CASE(test_fractional_invalid)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_exponential_valid)
|
||||
{
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e10", "1e10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e+10", "1e+10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e-10", "1e-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e10", "+1e10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e+10", "+1e+10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e-10", "+1e-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e10", "-1e10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e+10", "-1e+10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e-10", "-1e-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "123e-10", "123e-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1E10", "1E10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1E+10", "1E+10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1E-10", "1E-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "123E-10", "123E-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-10", "1_2_3E-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e10", "1e10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e+10", "1e+10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e-10", "1e-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e10", "+1e10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e+10", "+1e+10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e-10", "+1e-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e10", "-1e10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e+10", "-1e+10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e-10", "-1e-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "123e-10", "123e-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1E10", "1E10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1E+10", "1E+10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1E-10", "1E-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "123E-10", "123E-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-10", "1_2_3E-10");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-1_0", "1_2_3E-1_0");
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-01", "1_2_3E-01");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-0_1", "1_2_3E-0_1");
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_exponential_invalid)
|
||||
{
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1E0", "1e1");
|
||||
// accept partially
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1E0", "1e1");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1E1e0", "1E1");
|
||||
}
|
||||
|
||||
@@ -64,12 +72,26 @@ BOOST_AUTO_TEST_CASE(test_both_valid)
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e23", "6.02e23");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e+23", "6.02e+23");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1.112_650_06e-17", "1.112_650_06e-17");
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e-07", "1.0e-07");
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_both_invalid)
|
||||
{
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1.0", "1e1");
|
||||
TOML11_TEST_LEX_REJECT(lex_float, "01e1.0");
|
||||
// accept partially
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1.0", "1e1");
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e_01", "1.0");
|
||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e0__1", "1.0e0");
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_special_floating_point)
|
||||
|
||||
@@ -68,6 +68,13 @@ BOOST_AUTO_TEST_CASE(test_exponential)
|
||||
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-1_0", 123e-10);
|
||||
TOML11_TEST_PARSE_EQUAL(parse_floating, "+0e0", 0.0);
|
||||
TOML11_TEST_PARSE_EQUAL(parse_floating, "-0e0", -0.0);
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-01", 123e-1);
|
||||
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-0_1", 123e-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_exponential_value)
|
||||
@@ -90,6 +97,13 @@ BOOST_AUTO_TEST_CASE(test_exponential_value)
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-1_0", value(123e-10));
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+0e0", value( 0.0));
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0e0", value(-0.0));
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-01", value(123e-1));
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-0_1", value(123e-1));
|
||||
#endif
|
||||
}
|
||||
BOOST_AUTO_TEST_CASE(test_fe)
|
||||
{
|
||||
@@ -102,6 +116,12 @@ BOOST_AUTO_TEST_CASE(test_fe_vaule)
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e23", value(6.02e23));
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e+23", value(6.02e23));
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.112_650_06e-17", value(1.11265006e-17));
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "3.141_5e-01", value(3.1415e-1));
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_inf)
|
||||
|
||||
@@ -905,3 +905,32 @@ BOOST_AUTO_TEST_CASE(test_value_empty)
|
||||
BOOST_CHECK_THROW(v1.as_array(), toml::type_error);
|
||||
BOOST_CHECK_THROW(v1.as_table(), toml::type_error);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_value_at)
|
||||
{
|
||||
{
|
||||
toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}};
|
||||
|
||||
BOOST_TEST(v1.at("foo").as_integer() == 42);
|
||||
BOOST_TEST(v1.at("bar").as_floating() == 3.14);
|
||||
BOOST_TEST(v1.at("baz").as_string() == "qux");
|
||||
|
||||
BOOST_CHECK_THROW(v1.at(0), toml::type_error);
|
||||
BOOST_CHECK_THROW(v1.at("quux"), std::out_of_range);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
toml::value v1{1,2,3,4,5};
|
||||
|
||||
BOOST_TEST(v1.at(0).as_integer() == 1);
|
||||
BOOST_TEST(v1.at(1).as_integer() == 2);
|
||||
BOOST_TEST(v1.at(2).as_integer() == 3);
|
||||
BOOST_TEST(v1.at(3).as_integer() == 4);
|
||||
BOOST_TEST(v1.at(4).as_integer() == 5);
|
||||
|
||||
BOOST_CHECK_THROW(v1.at("foo"), toml::type_error);
|
||||
BOOST_CHECK_THROW(v1.at(5), std::out_of_range);
|
||||
}
|
||||
}
|
||||
|
||||
1
toml.hpp
1
toml.hpp
@@ -37,6 +37,5 @@
|
||||
#include "toml/literal.hpp"
|
||||
#include "toml/serializer.hpp"
|
||||
#include "toml/get.hpp"
|
||||
#include "toml/find.hpp"
|
||||
|
||||
#endif// TOML_FOR_MODERN_CPP
|
||||
|
||||
786
toml/find.hpp
786
toml/find.hpp
@@ -1,786 +0,0 @@
|
||||
// Copyright Toru Niina 2019.
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_FIND_HPP
|
||||
#define TOML11_FIND_HPP
|
||||
#include "get.hpp"
|
||||
#include <numeric>
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// these overloads do not require to set T. and returns value itself.
|
||||
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 key& ky)
|
||||
{
|
||||
const auto& tab = v.template cast<value_t::table>();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return tab.at(ky);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
basic_value<C, M, V>& find(basic_value<C, M, V>& v, const key& ky)
|
||||
{
|
||||
auto& tab = v.template cast<value_t::table>();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return tab.at(ky);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
basic_value<C, M, V>&& find(basic_value<C, M, V>&& v, const key& ky)
|
||||
{
|
||||
auto tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return std::move(tab.at(ky));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// find<T>(value, key);
|
||||
|
||||
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 key& ky)
|
||||
{
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(tab.at(ky));
|
||||
}
|
||||
|
||||
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 key& ky)
|
||||
{
|
||||
auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(tab.at(ky));
|
||||
}
|
||||
|
||||
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 key& ky)
|
||||
{
|
||||
auto tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(std::move(tab.at(ky)));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
||||
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
detail::enable_if_t<detail::conjunction<std::is_convertible<Ts, std::string>...
|
||||
>::value, const basic_value<C, M, V>&>
|
||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
detail::enable_if_t<detail::conjunction<std::is_convertible<Ts, std::string>...
|
||||
>::value, basic_value<C, M, V>&>
|
||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
detail::enable_if_t<detail::conjunction<std::is_convertible<Ts, std::string>...
|
||||
>::value, basic_value<C, M, V>&&>
|
||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
detail::enable_if_t<detail::conjunction<std::is_convertible<Ts, std::string>...
|
||||
>::value, decltype(get<T>(std::declval<const basic_value<C, M, V>&>()))>
|
||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
detail::enable_if_t<detail::conjunction<std::is_convertible<Ts, std::string>...
|
||||
>::value, decltype(get<T>(std::declval<basic_value<C, M, V>&>()))>
|
||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
detail::enable_if_t<detail::conjunction<std::is_convertible<Ts, std::string>...
|
||||
>::value, decltype(get<T>(std::declval<basic_value<C, M, V>&&>()))>
|
||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find<T>(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// 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 std::move(opt);}
|
||||
auto tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0) {return std::move(opt);}
|
||||
return std::move(tab[ky]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// exact types (return type can be a reference)
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const&
|
||||
find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt)
|
||||
{
|
||||
if(!v.is_table()) {return opt;}
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return get_or(tab.at(ky), opt);
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&
|
||||
find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
|
||||
{
|
||||
if(!v.is_table()) {return opt;}
|
||||
auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return get_or(tab[ky], opt);
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&&
|
||||
find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
|
||||
{
|
||||
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||
auto tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// std::string (return type can be a reference)
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
|
||||
find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt)
|
||||
{
|
||||
if(!v.is_table()) {return opt;}
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return get_or(tab.at(ky), opt);
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
|
||||
find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
|
||||
{
|
||||
if(!v.is_table()) {return opt;}
|
||||
auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return get_or(tab.at(ky), opt);
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<std::is_same<T, std::string>::value, std::string>
|
||||
find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
|
||||
{
|
||||
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||
auto tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||
return get_or(std::move(tab.at(ky)), std::forward<T>(opt));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// string literal (deduced as std::string)
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_string_literal<typename std::remove_reference<T>::type>::value,
|
||||
std::string>
|
||||
find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
||||
{
|
||||
if(!v.is_table()) {return std::string(opt);}
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return std::string(opt);}
|
||||
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// others (require type conversion and return type cannot be lvalue reference)
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::conjunction<
|
||||
// T is not an exact toml type
|
||||
detail::negation<detail::is_exact_toml_type<
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
|
||||
basic_value<C, M, V>>>,
|
||||
// T is not std::string
|
||||
detail::negation<std::is_same<std::string,
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
||||
// T is not a string literal
|
||||
detail::negation<detail::is_string_literal<
|
||||
typename std::remove_reference<T>::type>>
|
||||
>::value, typename std::remove_cv<typename std::remove_reference<T>::type>::type>
|
||||
find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
||||
{
|
||||
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// expect
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
result<T, std::string> expect(const basic_value<C, M, V>& v) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return ok(get<T>(v));
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
return err(e.what());
|
||||
}
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
result<T, std::string>
|
||||
expect(const basic_value<C, M, V>& v, const toml::key& k) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return ok(find<T>(v, k));
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
return err(e.what());
|
||||
}
|
||||
}
|
||||
template<typename T, typename Table>
|
||||
detail::enable_if_t<detail::conjunction<
|
||||
detail::is_map<Table>, detail::is_basic_value<typename Table::mapped_type>
|
||||
>::value, result<T, std::string>>
|
||||
expect(const Table& t, const toml::key& k,
|
||||
std::string tablename = "unknown table") noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return ok(find<T>(t, k, std::move(tablename)));
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
return err(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// find_fuzzy
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// default fuzzy matcher; levenstein distance (all cost is 1)
|
||||
|
||||
struct levenstein_matcher
|
||||
{
|
||||
levenstein_matcher(): tolerance(1) {}
|
||||
levenstein_matcher(const std::uint32_t tol): tolerance(tol) {}
|
||||
~levenstein_matcher() = default;
|
||||
levenstein_matcher(levenstein_matcher const&) = default;
|
||||
levenstein_matcher(levenstein_matcher &&) = default;
|
||||
levenstein_matcher& operator=(levenstein_matcher const&) = default;
|
||||
levenstein_matcher& operator=(levenstein_matcher &&) = default;
|
||||
|
||||
template<typename charT, typename traitsT, typename Alloc1, typename Alloc2>
|
||||
bool operator()(const std::basic_string<charT, traitsT, Alloc1>& lhs,
|
||||
const std::basic_string<charT, traitsT, Alloc2>& rhs) const
|
||||
{
|
||||
return this->distance(lhs, rhs) <= this->tolerance;
|
||||
}
|
||||
|
||||
template<typename charT, typename traitsT, typename Alloc1, typename Alloc2>
|
||||
std::uint32_t distance(
|
||||
const std::basic_string<charT, traitsT, Alloc1>& lhs,
|
||||
const std::basic_string<charT, traitsT, Alloc2>& rhs) const
|
||||
{
|
||||
// force `lhs.size() <= rhs.size()`
|
||||
if(lhs.size() > rhs.size()) {return this->distance(rhs, lhs);}
|
||||
|
||||
std::vector<std::uint32_t> matrix(lhs.size() + 1u);
|
||||
std::iota(matrix.begin(), matrix.end(), 0);
|
||||
|
||||
for(const charT r : rhs)
|
||||
{
|
||||
std::uint32_t prev_diag = matrix.front();
|
||||
matrix.front() += 1;
|
||||
|
||||
for(std::size_t i=0; i<lhs.size(); ++i)
|
||||
{
|
||||
const charT l = lhs[i];
|
||||
if(traitsT::eq(l, r))
|
||||
{
|
||||
std::swap(matrix[i+1], prev_diag);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto tmp = matrix[i+1];
|
||||
matrix[i+1] = std::min(prev_diag, std::min(matrix[i], matrix[i+1])) + 1;
|
||||
prev_diag = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return matrix.back();
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint32_t tolerance;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// toml::find_fuzzy<T>(v, "tablename", FuzzyMatcher);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename Iterator, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher>
|
||||
Iterator find_unique(
|
||||
Iterator iter, const Iterator end, const basic_value<C, M, V>& v,
|
||||
const toml::key& k, const FuzzyMatcher& match)
|
||||
{
|
||||
Iterator found = end;
|
||||
for(; iter != end; ++iter)
|
||||
{
|
||||
if(match(iter->first, k))
|
||||
{
|
||||
if(found != end)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(
|
||||
concat_to_string("[error] key \"", k, "\" not found."),
|
||||
{
|
||||
{std::addressof(detail::get_region(v)),"in this table"},
|
||||
{std::addressof(detail::get_region(found->second)),
|
||||
"did you mean this here?"},
|
||||
{std::addressof(detail::get_region(iter->second)),
|
||||
"or this?"}
|
||||
}));
|
||||
}
|
||||
found = iter;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
} // detail
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher = levenstein_matcher>
|
||||
auto find_fuzzy(const basic_value<C, M, V>& v, const key& ky,
|
||||
const FuzzyMatcher match = levenstein_matcher(1))
|
||||
-> decltype(find<T>(std::declval<const basic_value<C, M, V>&>(), ky))
|
||||
{
|
||||
try
|
||||
{
|
||||
return find<T>(v, ky);
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
const auto& t = v.as_table();
|
||||
const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
|
||||
if(found != t.end())
|
||||
{
|
||||
return get<T>(found->second);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher = levenstein_matcher>
|
||||
auto find_fuzzy(basic_value<C, M, V>& v, const key& ky,
|
||||
const FuzzyMatcher match = levenstein_matcher(1))
|
||||
-> decltype(find<T>(std::declval<basic_value<C, M, V>&>(), ky))
|
||||
{
|
||||
try
|
||||
{
|
||||
return find<T>(v, ky);
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
auto& t = v.as_table();
|
||||
const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
|
||||
if(found != t.end())
|
||||
{
|
||||
return get<T>(found->second);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher = levenstein_matcher>
|
||||
auto find_fuzzy(basic_value<C, M, V>&& v_, const key& ky,
|
||||
const FuzzyMatcher match = levenstein_matcher(1))
|
||||
-> decltype(find<T>(std::declval<basic_value<C, M, V>&&>(), ky))
|
||||
{
|
||||
basic_value<C, M, V> v = v_; // to re-use later, store it once
|
||||
try
|
||||
{
|
||||
return std::move(find<T>(v, ky)); // pass lref, move later
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
auto& t = v.as_table(); // because v is used here
|
||||
const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
|
||||
if(found != t.end())
|
||||
{
|
||||
return get<T>(std::move(found->second));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// no-template-argument case (by default, return toml::value).
|
||||
// toml::find_fuzzy(v, "tablename", FuzzyMatcher);
|
||||
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher = levenstein_matcher>
|
||||
basic_value<C, M, V> const&
|
||||
find_fuzzy(const basic_value<C, M, V>& v, const key& ky,
|
||||
const FuzzyMatcher match = levenstein_matcher(1))
|
||||
{
|
||||
try
|
||||
{
|
||||
return find(v, ky);
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
const auto& t = v.as_table();
|
||||
const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
|
||||
if(found != t.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher = levenstein_matcher>
|
||||
basic_value<C, M, V>&
|
||||
find_fuzzy(basic_value<C, M, V>& v, const key& ky,
|
||||
const FuzzyMatcher match = levenstein_matcher(1))
|
||||
{
|
||||
try
|
||||
{
|
||||
return find(v, ky);
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
auto& t = v.as_table();
|
||||
const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
|
||||
if(found != t.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher = levenstein_matcher>
|
||||
basic_value<C, M, V>&&
|
||||
find_fuzzy(basic_value<C, M, V>&& v_, const key& ky,
|
||||
const FuzzyMatcher match = levenstein_matcher(1))
|
||||
{
|
||||
basic_value<C, M, V> v = v_; // to re-use later, store it once
|
||||
try
|
||||
{
|
||||
return std::move(find(v, ky));
|
||||
}
|
||||
catch(const std::out_of_range& oor)
|
||||
{
|
||||
auto& t = v.as_table();
|
||||
const auto found = detail::find_unique(t.begin(), t.end(), v, ky, match);
|
||||
if(found != t.end())
|
||||
{
|
||||
return std::move(found->second);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// find(v, k, matcher)
|
||||
//
|
||||
// when matcher is passed, check a key that matches exists or not. if it exists,
|
||||
// suggest that in the error message
|
||||
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher>
|
||||
basic_value<C, M, V> const&
|
||||
find(const basic_value<C, M, V>& v, const key& ky, FuzzyMatcher match)
|
||||
{
|
||||
const auto& tab = v.template cast<value_t::table>();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
for(const auto& kv : tab)
|
||||
{
|
||||
if(match(kv.first, ky))
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found."), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"},
|
||||
{std::addressof(detail::get_region(kv.second)),
|
||||
"did you mean this?"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return tab.at(ky);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher>
|
||||
basic_value<C, M, V>&
|
||||
find(basic_value<C, M, V>& v, const key& ky, FuzzyMatcher match)
|
||||
{
|
||||
auto& tab = v.template cast<value_t::table>();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
for(const auto& kv : tab)
|
||||
{
|
||||
if(match(kv.first, ky))
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found."), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"},
|
||||
{std::addressof(detail::get_region(kv.second)),
|
||||
"did you mean this?"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return tab.at(ky);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher>
|
||||
basic_value<C, M, V>&&
|
||||
find(basic_value<C, M, V>&& v, const key& ky, FuzzyMatcher match)
|
||||
{
|
||||
auto tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
for(const auto& kv : tab)
|
||||
{
|
||||
if(match(kv.first, ky))
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found."), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"},
|
||||
{std::addressof(detail::get_region(kv.second)),
|
||||
"did you mean this?"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return std::move(tab.at(ky));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// find<T>(value, key, fuzzy_matcher);
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher>
|
||||
detail::enable_if_t<
|
||||
detail::negation<std::is_convertible<FuzzyMatcher, std::string>>::value,
|
||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))>
|
||||
find(const basic_value<C, M, V>& v, const key& ky, FuzzyMatcher match)
|
||||
{
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
for(const auto& kv : tab)
|
||||
{
|
||||
if(match(kv.first, ky))
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found."), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"},
|
||||
{std::addressof(detail::get_region(kv.second)),
|
||||
"did you mean this here?"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(tab.at(ky));
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher>
|
||||
detail::enable_if_t<
|
||||
detail::negation<std::is_convertible<FuzzyMatcher, std::string>>::value,
|
||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))>
|
||||
find(basic_value<C, M, V>& v, const key& ky, FuzzyMatcher match)
|
||||
{
|
||||
auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
for(const auto& kv : tab)
|
||||
{
|
||||
if(match(kv.first, ky))
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found."), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"},
|
||||
{std::addressof(detail::get_region(kv.second)),
|
||||
"did you mean this here?"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(tab.at(ky));
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename FuzzyMatcher>
|
||||
detail::enable_if_t<
|
||||
detail::negation<std::is_convertible<FuzzyMatcher, std::string>>::value,
|
||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))>
|
||||
find(basic_value<C, M, V>&& v, const key& ky, FuzzyMatcher match)
|
||||
{
|
||||
auto tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
for(const auto& kv : tab)
|
||||
{
|
||||
if(match(kv.first, ky))
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found."), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"},
|
||||
{std::addressof(detail::get_region(kv.second)),
|
||||
"did you mean this here?"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(std::move(tab.at(ky)));
|
||||
}
|
||||
|
||||
} // toml
|
||||
#endif// TOML11_FIND_HPP
|
||||
427
toml/get.hpp
427
toml/get.hpp
@@ -31,10 +31,10 @@ get(const basic_value<C, M, V>& v)
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> &&
|
||||
detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>
|
||||
get(basic_value<C, M, V>&& v)
|
||||
{
|
||||
return std::move(v).template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>();
|
||||
return T(std::move(v).template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -58,10 +58,10 @@ get(const basic_value<C, M, V>& v)
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T> &&
|
||||
inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T>
|
||||
get(basic_value<C, M, V>&& v)
|
||||
{
|
||||
return std::move(v);
|
||||
return basic_value<C, M, V>(std::move(v));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -90,7 +90,7 @@ inline detail::enable_if_t<detail::conjunction<
|
||||
>::value, T>
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
return static_cast<T>(v.template cast<value_t::integer>());
|
||||
return static_cast<T>(v.as_integer());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -105,7 +105,7 @@ inline detail::enable_if_t<detail::conjunction<
|
||||
>::value, T>
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
return static_cast<T>(v.template cast<value_t::floating>());
|
||||
return static_cast<T>(v.as_floating());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -117,7 +117,7 @@ template<typename T, typename C,
|
||||
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
|
||||
get(basic_value<C, M, V>& v)
|
||||
{
|
||||
return v.template cast<value_t::string>().str;
|
||||
return v.as_string().str;
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
@@ -125,15 +125,15 @@ template<typename T, typename C,
|
||||
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
return v.template cast<value_t::string>().str;
|
||||
return v.as_string().str;
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
|
||||
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>
|
||||
get(basic_value<C, M, V>&& v)
|
||||
{
|
||||
return std::move(v.template cast<value_t::string>().str);
|
||||
return std::string(std::move(v.as_string().str));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -145,7 +145,7 @@ template<typename T, typename C,
|
||||
inline detail::enable_if_t<std::is_same<T, std::string_view>::value, std::string_view>
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
return std::string_view(v.template cast<value_t::string>().str);
|
||||
return std::string_view(v.as_string().str);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -158,7 +158,7 @@ inline detail::enable_if_t<detail::is_chrono_duration<T>::value, T>
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
return std::chrono::duration_cast<T>(
|
||||
std::chrono::nanoseconds(v.template cast<value_t::local_time>()));
|
||||
std::chrono::nanoseconds(v.as_local_time()));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -174,18 +174,15 @@ get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
case value_t::local_date:
|
||||
{
|
||||
return std::chrono::system_clock::time_point(
|
||||
v.template cast<value_t::local_date>());
|
||||
return std::chrono::system_clock::time_point(v.as_local_date());
|
||||
}
|
||||
case value_t::local_datetime:
|
||||
{
|
||||
return std::chrono::system_clock::time_point(
|
||||
v.template cast<value_t::local_datetime>());
|
||||
return std::chrono::system_clock::time_point(v.as_local_datetime());
|
||||
}
|
||||
case value_t::offset_datetime:
|
||||
{
|
||||
return std::chrono::system_clock::time_point(
|
||||
v.template cast<value_t::offset_datetime>());
|
||||
return std::chrono::system_clock::time_point(v.as_offset_datetime());
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -259,7 +256,7 @@ get(const basic_value<C, M, V>&);
|
||||
// toml::from<T>::from_toml(v)
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
std::size_t S = sizeof(::toml::into<T>)>
|
||||
std::size_t S = sizeof(::toml::from<T>)>
|
||||
T get(const basic_value<C, M, V>&);
|
||||
|
||||
// ============================================================================
|
||||
@@ -276,7 +273,7 @@ detail::enable_if_t<detail::conjunction<
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
const auto& ar = v.template cast<value_t::array>();
|
||||
const auto& ar = v.as_array();
|
||||
T container;
|
||||
container.resize(ar.size());
|
||||
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
||||
@@ -298,7 +295,7 @@ detail::enable_if_t<detail::conjunction<
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
const auto& ar = v.template cast<value_t::array>();
|
||||
const auto& ar = v.as_array();
|
||||
|
||||
T container;
|
||||
if(ar.size() != container.size())
|
||||
@@ -325,7 +322,7 @@ get(const basic_value<C, M, V>& v)
|
||||
using first_type = typename T::first_type;
|
||||
using second_type = typename T::second_type;
|
||||
|
||||
const auto& ar = v.template cast<value_t::array>();
|
||||
const auto& ar = v.as_array();
|
||||
if(ar.size() != 2)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
@@ -356,7 +353,7 @@ template<typename T, typename C,
|
||||
detail::enable_if_t<detail::is_std_tuple<T>::value, T>
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
const auto& ar = v.template cast<value_t::array>();
|
||||
const auto& ar = v.as_array();
|
||||
if(ar.size() != std::tuple_size<T>::value)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
@@ -388,7 +385,7 @@ get(const basic_value<C, M, V>& v)
|
||||
"toml::get only supports map type of which key_type is "
|
||||
"convertible from std::string.");
|
||||
T map;
|
||||
for(const auto& kv : v.template cast<value_t::table>())
|
||||
for(const auto& kv : v.as_table())
|
||||
{
|
||||
map[key_type(kv.first)] = ::toml::get<mapped_type>(kv.second);
|
||||
}
|
||||
@@ -420,6 +417,158 @@ T get(const basic_value<C, M, V>& v)
|
||||
return ::toml::from<T>::from_toml(v);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// find
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// these overloads do not require to set T. and returns value itself.
|
||||
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 key& ky)
|
||||
{
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return tab.at(ky);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
basic_value<C, M, V>& find(basic_value<C, M, V>& v, const key& ky)
|
||||
{
|
||||
auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return tab.at(ky);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
basic_value<C, M, V> find(basic_value<C, M, V>&& v, const key& ky)
|
||||
{
|
||||
typename basic_value<C, M, V>::table_type tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// find<T>(value, key);
|
||||
|
||||
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 key& ky)
|
||||
{
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(tab.at(ky));
|
||||
}
|
||||
|
||||
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 key& ky)
|
||||
{
|
||||
auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(tab.at(ky));
|
||||
}
|
||||
|
||||
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 key& ky)
|
||||
{
|
||||
typename basic_value<C, M, V>::table_type tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(std::move(tab.at(ky)));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
||||
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
const basic_value<C, M, V>&
|
||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
basic_value<C, M, V>&
|
||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
template<typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
basic_value<C, M, V>
|
||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
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)
|
||||
{
|
||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V,
|
||||
typename ... Ts>
|
||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
||||
{
|
||||
return ::toml::find<T>(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// get_or(value, fallback)
|
||||
|
||||
@@ -456,8 +605,7 @@ get_or(const basic_value<C, M, V>& v, const T& opt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return get<typename std::remove_cv<
|
||||
typename std::remove_reference<T>::type>::type>(v);
|
||||
return get<detail::remove_cvref_t<T>>(v);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -472,8 +620,7 @@ get_or(basic_value<C, M, V>& v, T& opt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return get<typename std::remove_cv<
|
||||
typename std::remove_reference<T>::type>::type>(v);
|
||||
return get<detail::remove_cvref_t<T>>(v);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -482,18 +629,17 @@ get_or(basic_value<C, M, V>& v, T& opt)
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&&
|
||||
detail::enable_if_t<detail::is_exact_toml_type<detail::remove_cvref_t<T>,
|
||||
basic_value<C, M, V>>::value, detail::remove_cvref_t<T>>
|
||||
get_or(basic_value<C, M, V>&& v, T&& opt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return get<typename std::remove_cv<
|
||||
typename std::remove_reference<T>::type>::type>(v);
|
||||
return get<detail::remove_cvref_t<T>>(std::move(v));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return opt;
|
||||
return detail::remove_cvref_t<T>(std::forward<T>(opt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,14 +648,13 @@ get_or(basic_value<C, M, V>&& v, T&& opt)
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<std::is_same<
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
|
||||
std::string>::value, std::string> const&
|
||||
get_or(const basic_value<C, M, V>& v, T&& opt)
|
||||
detail::enable_if_t<std::is_same<detail::remove_cvref_t<T>, std::string>::value,
|
||||
std::string> const&
|
||||
get_or(const basic_value<C, M, V>& v, const T& opt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return v.template cast<value_t::string>().str;
|
||||
return v.as_string().str;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -523,7 +668,7 @@ get_or(basic_value<C, M, V>& v, T& opt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return v.template cast<value_t::string>().str;
|
||||
return v.as_string().str;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -532,18 +677,17 @@ get_or(basic_value<C, M, V>& v, T& opt)
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<std::is_same<
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
|
||||
std::string>::value, std::string>
|
||||
detail::enable_if_t<
|
||||
std::is_same<detail::remove_cvref_t<T>, std::string>::value, std::string>
|
||||
get_or(basic_value<C, M, V>&& v, T&& opt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return std::move(v.template cast<value_t::string>().str);
|
||||
return std::move(v.as_string().str);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return std::forward<T>(opt);
|
||||
return std::string(std::forward<T>(opt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -558,11 +702,11 @@ get_or(const basic_value<C, M, V>& v, T&& opt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return std::move(v.template cast<value_t::string>().str);
|
||||
return std::move(v.as_string().str);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return std::string(opt);
|
||||
return std::string(std::forward<T>(opt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,24 +716,199 @@ get_or(const basic_value<C, M, V>& v, T&& opt)
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
|
||||
detail::negation<detail::is_exact_toml_type<detail::remove_cvref_t<T>,
|
||||
basic_value<C, M, V>>>,
|
||||
detail::negation<std::is_same<std::string,
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
||||
detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>,
|
||||
detail::negation<detail::is_string_literal<
|
||||
typename std::remove_reference<T>::type>>
|
||||
>::value, typename std::remove_reference<T>::type>
|
||||
>::value, detail::remove_cvref_t<T>>
|
||||
get_or(const basic_value<C, M, V>& v, T&& opt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return get<typename std::remove_cv<
|
||||
typename std::remove_reference<T>::type>::type>(v);
|
||||
return get<detail::remove_cvref_t<T>>(v);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return std::forward<T>(opt);
|
||||
return detail::remove_cvref_t<T>(std::forward<T>(opt));
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// 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.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 = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// exact types (return type can be a reference)
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const&
|
||||
find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt)
|
||||
{
|
||||
if(!v.is_table()) {return opt;}
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return get_or(tab.at(ky), opt);
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&
|
||||
find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
|
||||
{
|
||||
if(!v.is_table()) {return opt;}
|
||||
auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return get_or(tab.at(ky), opt);
|
||||
}
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value,
|
||||
detail::remove_cvref_t<T>>
|
||||
find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
|
||||
{
|
||||
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||
auto tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||
return get_or(std::move(tab.at(ky)), std::forward<T>(opt));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// std::string (return type can be a reference)
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
|
||||
find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt)
|
||||
{
|
||||
if(!v.is_table()) {return opt;}
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return get_or(tab.at(ky), opt);
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
|
||||
find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
|
||||
{
|
||||
if(!v.is_table()) {return opt;}
|
||||
auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return opt;}
|
||||
return get_or(tab.at(ky), opt);
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<std::is_same<T, std::string>::value, std::string>
|
||||
find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
|
||||
{
|
||||
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||
auto tab = std::move(v).as_table();
|
||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||
return get_or(std::move(tab.at(ky)), std::forward<T>(opt));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// string literal (deduced as std::string)
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<
|
||||
detail::is_string_literal<typename std::remove_reference<T>::type>::value,
|
||||
std::string>
|
||||
find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
||||
{
|
||||
if(!v.is_table()) {return std::string(opt);}
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return std::string(opt);}
|
||||
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// others (require type conversion and return type cannot be lvalue reference)
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::conjunction<
|
||||
// T is not an exact toml type
|
||||
detail::negation<detail::is_exact_toml_type<
|
||||
detail::remove_cvref_t<T>, basic_value<C, M, V>>>,
|
||||
// T is not std::string
|
||||
detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>,
|
||||
// T is not a string literal
|
||||
detail::negation<detail::is_string_literal<
|
||||
typename std::remove_reference<T>::type>>
|
||||
>::value, detail::remove_cvref_t<T>>
|
||||
find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
||||
{
|
||||
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||
const auto& tab = v.as_table();
|
||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// expect
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
result<T, std::string> expect(const basic_value<C, M, V>& v) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return ok(get<T>(v));
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
return err(e.what());
|
||||
}
|
||||
}
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
result<T, std::string>
|
||||
expect(const basic_value<C, M, V>& v, const toml::key& k) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return ok(find<T>(v, k));
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
return err(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,12 +63,22 @@ using lex_integer = either<lex_bin_int, lex_oct_int, lex_hex_int, lex_dec_int>;
|
||||
using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
|
||||
using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
|
||||
using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
|
||||
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>, lex_dec_int>;
|
||||
|
||||
using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
|
||||
sequence<lex_underscore, lex_digit>>, unlimited>>;
|
||||
sequence<lex_underscore, lex_digit>>, unlimited>>;
|
||||
|
||||
using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
// use toml-lang/toml HEAD
|
||||
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>,
|
||||
maybe<lex_sign>, lex_zero_prefixable_int>;
|
||||
#else
|
||||
// strictly TOML v0.5.0
|
||||
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>,
|
||||
lex_dec_int>;
|
||||
#endif
|
||||
|
||||
using lex_float = either<lex_special_float,
|
||||
sequence<lex_dec_int, either<lex_exponent_part,
|
||||
sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;
|
||||
@@ -115,10 +125,17 @@ using lex_local_time = lex_partial_time;
|
||||
// ===========================================================================
|
||||
|
||||
using lex_quotation_mark = character<'"'>;
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09 (tab)
|
||||
in_range<0x0a, 0x1F>, // is allowed
|
||||
character<0x22>, character<0x5C>,
|
||||
character<0x7F>>>;
|
||||
#else
|
||||
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
|
||||
character<0x22>, character<0x5C>,
|
||||
character<0x7F>>>;
|
||||
|
||||
#endif
|
||||
using lex_escape = character<'\\'>;
|
||||
using lex_escape_unicode_short = sequence<character<'u'>,
|
||||
repeat<lex_hex_dig, exactly<4>>>;
|
||||
@@ -138,11 +155,18 @@ using lex_basic_string = sequence<lex_quotation_mark,
|
||||
lex_quotation_mark>;
|
||||
|
||||
using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
using lex_ml_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09
|
||||
in_range<0x0a, 0x1F>, // is tab
|
||||
character<0x5C>,
|
||||
character<0x7F>,
|
||||
lex_ml_basic_string_delim>>;
|
||||
#else // TOML v0.5.0
|
||||
using lex_ml_basic_unescaped = exclude<either<in_range<0x00,0x1F>,
|
||||
character<0x5C>,
|
||||
character<0x7F>,
|
||||
lex_ml_basic_string_delim>>;
|
||||
#endif
|
||||
|
||||
using lex_ml_basic_escaped_newline = sequence<
|
||||
lex_escape, maybe<lex_ws>, lex_newline,
|
||||
|
||||
@@ -240,6 +240,19 @@ disjunction<
|
||||
>
|
||||
>{};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C++20 remove_cvref_t
|
||||
|
||||
template<typename T>
|
||||
struct remove_cvref
|
||||
{
|
||||
using type = typename std::remove_cv<
|
||||
typename std::remove_reference<T>::type>::type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using remove_cvref_t = typename remove_cvref<T>::type;
|
||||
|
||||
}// detail
|
||||
}//toml
|
||||
#endif // TOML_TRAITS
|
||||
|
||||
@@ -1567,6 +1567,28 @@ class basic_value
|
||||
return std::move(this->table_.value());
|
||||
}
|
||||
|
||||
// accessors =============================================================
|
||||
//
|
||||
// may throw type_error or out_of_range
|
||||
//
|
||||
value_type& at(const key& k)
|
||||
{
|
||||
return this->as_table().at(k);
|
||||
}
|
||||
value_type const& at(const key& k) const
|
||||
{
|
||||
return this->as_table().at(k);
|
||||
}
|
||||
|
||||
value_type& at(const std::size_t idx)
|
||||
{
|
||||
return this->as_array().at(idx);
|
||||
}
|
||||
value_type const& at(const std::size_t idx) const
|
||||
{
|
||||
return this->as_array().at(idx);
|
||||
}
|
||||
|
||||
source_location location() const
|
||||
{
|
||||
return source_location(this->region_info_.get());
|
||||
|
||||
Reference in New Issue
Block a user