mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfe5e50acf | ||
|
|
05077dee0c | ||
|
|
b9f1726e26 | ||
|
|
c583e38ebf | ||
|
|
388e9db32b | ||
|
|
aa8d574dfe | ||
|
|
49fdb61731 | ||
|
|
b2bb21a473 | ||
|
|
0c58549fc6 | ||
|
|
b7b5e847d3 | ||
|
|
22d630fec1 | ||
|
|
f7bf341452 | ||
|
|
0934d90f90 | ||
|
|
f2c8d0e279 | ||
|
|
8c7d83d985 | ||
|
|
5ce44adbdc | ||
|
|
5c5b1320d0 | ||
|
|
8b737dc21f | ||
|
|
ee654b6c3f | ||
|
|
c59782d180 | ||
|
|
9bef715ccd | ||
|
|
d2b1cf5123 | ||
|
|
9f92916d1d | ||
|
|
666e4cf9dc | ||
|
|
cafee29c64 | ||
|
|
a7a2272b29 | ||
|
|
dc0bca2bb6 | ||
|
|
490abe04fd | ||
|
|
81ed4c0e9d | ||
|
|
1b07baf184 | ||
|
|
9073d52159 | ||
|
|
55260654bf | ||
|
|
aa6271af75 | ||
|
|
c54a03f189 | ||
|
|
c153c0e8c3 | ||
|
|
1f90af8e67 | ||
|
|
a0c5192b74 | ||
|
|
7f020f3f44 | ||
|
|
827b433389 | ||
|
|
1148d01c70 | ||
|
|
17d78553ff | ||
|
|
4c12dad51f |
95
.travis.yml
95
.travis.yml
@@ -5,7 +5,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-5" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="g++-5" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -17,7 +17,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-6" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="g++-6" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -29,7 +29,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-7" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="g++-7" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -41,7 +41,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-8" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="g++-8" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -65,7 +65,19 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=OFF
|
env: COMPILER="g++-8" CXX_STANDARD=14
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa: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
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -89,7 +101,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-3.9" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="clang++-3.9" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -103,7 +115,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-4.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="clang++-4.0" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -117,7 +129,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-5.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="clang++-5.0" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -131,7 +143,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-6.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="clang++-6.0" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -145,7 +157,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-7" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="clang++-7" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -159,7 +171,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-8" CXX_STANDARD=11 TOML_HEAD=OFF
|
env: COMPILER="clang++-8" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -187,7 +199,21 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=OFF
|
env: COMPILER="clang++-8" CXX_STANDARD=14
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=17
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -212,6 +238,34 @@ matrix:
|
|||||||
- clang-8
|
- clang-8
|
||||||
- g++-8
|
- g++-8
|
||||||
- boost1.70
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=11 WITH_ASAN=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=11 WITH_UBSAN=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
- os: osx
|
- os: osx
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
@@ -234,11 +288,26 @@ script:
|
|||||||
tar xf cmake-3.14.5-Linux-x86_64.tar.gz -C cmake --strip-components=1
|
tar xf cmake-3.14.5-Linux-x86_64.tar.gz -C cmake --strip-components=1
|
||||||
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
|
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
|
||||||
fi
|
fi
|
||||||
|
- |
|
||||||
|
if [[ "${TOML_HEAD}" != "ON" ]]; then
|
||||||
|
export TOML_HEAD="OFF"
|
||||||
|
fi
|
||||||
|
- echo "TOML_HEAD = ${TOML_HEAD}"
|
||||||
|
- |
|
||||||
|
if [[ "${WITH_ASAN}" != "ON" ]]; then
|
||||||
|
export WITH_ASAN="OFF"
|
||||||
|
fi
|
||||||
|
- echo "WITH_ASAN = ${WITH_ASAN}"
|
||||||
|
- |
|
||||||
|
if [[ "${WITH_UBSAN}" != "ON" ]]; then
|
||||||
|
export WITH_UBSAN="OFF"
|
||||||
|
fi
|
||||||
|
- echo "WITH_UBSAN = ${WITH_UBSAN}"
|
||||||
- cmake --version
|
- cmake --version
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- git clone https://github.com/toml-lang/toml.git
|
- git clone https://github.com/toml-lang/toml.git
|
||||||
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD -DTOML11_USE_UNRELEASED_TOML_FEATURES=${TOML_HEAD} ..
|
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD -DTOML11_USE_UNRELEASED_TOML_FEATURES=${TOML_HEAD} -Dtoml11_TEST_WITH_ASAN=${WITH_ASAN} -Dtoml11_TEST_WITH_UBSAN=${WITH_UBSAN} ..
|
||||||
- make
|
- make
|
||||||
- ctest --output-on-failure
|
- ctest --output-on-failure
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ enable_testing()
|
|||||||
project(toml11)
|
project(toml11)
|
||||||
|
|
||||||
set(toml11_VERSION_MAYOR 3)
|
set(toml11_VERSION_MAYOR 3)
|
||||||
set(toml11_VERSION_MINOR 2)
|
set(toml11_VERSION_MINOR 3)
|
||||||
set(toml11_VERSION_PATCH 0)
|
set(toml11_VERSION_PATCH 0)
|
||||||
set(toml11_VERSION
|
set(toml11_VERSION
|
||||||
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
|
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
|
||||||
)
|
)
|
||||||
|
|
||||||
option(toml11_BUILD_TEST "Build toml tests" ON)
|
option(toml11_BUILD_TEST "Build toml tests" ON)
|
||||||
|
option(toml11_TEST_WITH_ASAN "use LLVM address sanitizer" OFF)
|
||||||
|
option(toml11_TEST_WITH_UBSAN "use LLVM undefined behavior sanitizer" OFF)
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
||||||
|
|||||||
90
README.md
90
README.md
@@ -274,10 +274,44 @@ const auto color = toml::find<std::string>(data, "fruit", "physical", "color");
|
|||||||
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Finding a value in an array
|
||||||
|
|
||||||
|
You can find n-th value in an array by `toml::find`.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
values = ["foo", "bar", "baz"]
|
||||||
|
```
|
||||||
|
|
||||||
|
``` cpp
|
||||||
|
const auto data = toml::parse("sample.toml");
|
||||||
|
const auto values = toml::find(data, "values");
|
||||||
|
const auto bar = toml::find<std::string>(values, 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
`toml::find` can also search array recursively.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
const auto bar = toml::find<std::string>(data, "values", 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
Before calling `toml::find`, you can check if a value corresponding to a key
|
||||||
|
exists. You can use both `bool toml::value::contains(const key&) const` and
|
||||||
|
`std::size_t toml::value::count(const key&) const`. Those behaves like the
|
||||||
|
`std::map::contains` and `std::map::count`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
if(data.contains("fruit") && data.at("fruit").count("physical") != 0)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### In case of error
|
### In case of error
|
||||||
|
|
||||||
If the value does not exist, `toml::find` throws an error with the location of
|
If the value does not exist, `toml::find` throws `std::out_of_range` with the
|
||||||
the table.
|
location of the table.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
terminate called after throwing an instance of 'std::out_of_range'
|
terminate called after throwing an instance of 'std::out_of_range'
|
||||||
@@ -287,11 +321,6 @@ terminate called after throwing an instance of 'std::out_of_range'
|
|||||||
| ~~~~~ in this table
|
| ~~~~~ in this table
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: It is recommended to find a table as `toml::value` because it has much information
|
|
||||||
compared to `toml::table`, which is an alias of
|
|
||||||
`std::unordered_map<std::string, toml::value>`. Since `toml::table` does not have
|
|
||||||
any information about toml file, such as where the table was defined in the file.
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
If the specified type differs from the actual value contained, it throws
|
If the specified type differs from the actual value contained, it throws
|
||||||
@@ -869,14 +898,25 @@ toml::value v(toml::local_time(std::chrono::hours(10)));
|
|||||||
```
|
```
|
||||||
|
|
||||||
You can construct an array object not only from `initializer_list`, but also
|
You can construct an array object not only from `initializer_list`, but also
|
||||||
from STL containers.
|
from STL containers. In that case, the element type must be convertible to
|
||||||
|
`toml::value`.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
std::vector<int> vec{1,2,3,4,5};
|
std::vector<int> vec{1,2,3,4,5};
|
||||||
toml::value v = vec;
|
toml::value v(vec);
|
||||||
```
|
```
|
||||||
|
|
||||||
All the elements of `initializer_list` should be convertible into `toml::value`.
|
When you construct an array value, all the elements of `initializer_list`
|
||||||
|
must be convertible into `toml::value`.
|
||||||
|
|
||||||
|
If a `toml::value` has an array, you can `push_back` an element in it.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
toml::value v{1,2,3,4,5};
|
||||||
|
v.push_back(6);
|
||||||
|
```
|
||||||
|
|
||||||
|
`emplace_back` also works.
|
||||||
|
|
||||||
## Preserving comments
|
## Preserving comments
|
||||||
|
|
||||||
@@ -1093,7 +1133,7 @@ const auto data = toml::parse("example.toml");
|
|||||||
const foo f = toml::find<ext::foo>(data, "foo");
|
const foo f = toml::find<ext::foo>(data, "foo");
|
||||||
```
|
```
|
||||||
|
|
||||||
There are 2 ways to use `toml::get` with the types that you defined.
|
There are 3 ways to use `toml::get` with the types that you defined.
|
||||||
|
|
||||||
The first one is to implement `from_toml(const toml::value&)` member function.
|
The first one is to implement `from_toml(const toml::value&)` member function.
|
||||||
|
|
||||||
@@ -1120,7 +1160,31 @@ struct foo
|
|||||||
In this way, because `toml::get` first constructs `foo` without arguments,
|
In this way, because `toml::get` first constructs `foo` without arguments,
|
||||||
the type should be default-constructible.
|
the type should be default-constructible.
|
||||||
|
|
||||||
The second is to implement specialization of `toml::from` for your type.
|
The second is to implement `constructor(const toml::value&)`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace ext
|
||||||
|
{
|
||||||
|
struct foo
|
||||||
|
{
|
||||||
|
explicit foo(const toml::value& v)
|
||||||
|
: a(toml::find<int>(v, "a")), b(toml::find<double>(v, "b")),
|
||||||
|
c(toml::find<std::string>(v, "c"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
int a;
|
||||||
|
double b;
|
||||||
|
std::string c;
|
||||||
|
};
|
||||||
|
} // ext
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that implicit default constructor declaration will be suppressed
|
||||||
|
when a constructor is defined. If you want to use the struct (here, `foo`)
|
||||||
|
in a container (e.g. `std::vector<foo>`), you may need to define default
|
||||||
|
constructor explicitly.
|
||||||
|
|
||||||
|
The third is to implement specialization of `toml::from` for your type.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
namespace ext
|
namespace ext
|
||||||
@@ -1724,6 +1788,6 @@ I appreciate the help of the contributors who introduced the great feature to th
|
|||||||
|
|
||||||
This product is licensed under the terms of the [MIT License](LICENSE).
|
This product is licensed under the terms of the [MIT License](LICENSE).
|
||||||
|
|
||||||
- Copyright (c) 2017-2019 Toru Niina
|
- Copyright (c) 2017-2020 Toru Niina
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|||||||
@@ -34,11 +34,21 @@ set(TEST_NAMES
|
|||||||
test_error_detection
|
test_error_detection
|
||||||
test_format_error
|
test_format_error
|
||||||
test_extended_conversions
|
test_extended_conversions
|
||||||
|
test_visit
|
||||||
)
|
)
|
||||||
|
|
||||||
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
|
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
|
||||||
CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA)
|
CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA)
|
||||||
CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
|
CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Werror" COMPILER_SUPPORTS_WERROR)
|
||||||
|
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wsign-conversion" COMPILER_SUPPORTS_WSIGN_CONVERSION)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wconversion" COMPILER_SUPPORTS_WCONVERSION)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wduplicated-cond" COMPILER_SUPPORTS_WDUPLICATED_COND)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wduplicated-branches" COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wlogical-op" COMPILER_SUPPORTS_WLOGICAL_OP)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wuseless-cast" COMPILER_SUPPORTS_WUSELESS_CAST)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wdouble-promotion" COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
|
||||||
|
|
||||||
if(COMPILER_SUPPORTS_WALL)
|
if(COMPILER_SUPPORTS_WALL)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||||
@@ -49,6 +59,30 @@ endif()
|
|||||||
if(COMPILER_SUPPORTS_WPEDANTIC)
|
if(COMPILER_SUPPORTS_WPEDANTIC)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||||
endif()
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WERROR)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WSIGN_CONVERSION)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WCONVERSION)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wconversion")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WDUPLICATED_COND)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-cond")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-branches")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WLOGICAL_OP)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wlogical-op")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WUSELESS_CAST)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuseless-cast")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdouble-promotion")
|
||||||
|
endif()
|
||||||
|
|
||||||
option(TOML11_USE_UNRELEASED_TOML_FEATURES
|
option(TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
"use features in toml-lang/toml master while testing" OFF)
|
"use features in toml-lang/toml master while testing" OFF)
|
||||||
@@ -104,6 +138,19 @@ foreach(TEST_NAME ${TEST_NAMES})
|
|||||||
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
||||||
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
|
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
|
||||||
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
if(toml11_TEST_WITH_ASAN)
|
||||||
|
set_target_properties(${TEST_NAME} PROPERTIES
|
||||||
|
COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer"
|
||||||
|
LINK_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
|
||||||
|
elseif(toml11_TEST_WITH_UBSAN)
|
||||||
|
set_target_properties(${TEST_NAME} PROPERTIES
|
||||||
|
COMPILE_FLAGS "-fsanitize=undefined"
|
||||||
|
LINK_FLAGS "-fsanitize=undefined")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
# Set the PATH to be able to find Boost DLL
|
# Set the PATH to be able to find Boost DLL
|
||||||
|
|||||||
@@ -44,6 +44,18 @@ struct qux
|
|||||||
int a;
|
int a;
|
||||||
std::string b;
|
std::string b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct foobar
|
||||||
|
{
|
||||||
|
foobar() = default; // later we use std::vector<foobar>, default ctor is required.
|
||||||
|
|
||||||
|
// via constructor
|
||||||
|
explicit foobar(const toml::value& v)
|
||||||
|
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
|
||||||
|
{}
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
} // extlib
|
} // extlib
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
@@ -122,6 +134,19 @@ struct qux
|
|||||||
int a;
|
int a;
|
||||||
std::string b;
|
std::string b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct foobar
|
||||||
|
{
|
||||||
|
foobar() = default; // later we use std::vector<foobar>, default ctor is required.
|
||||||
|
|
||||||
|
template<typename C, template<typename ...> class M, template<typename ...> class A>
|
||||||
|
explicit foobar(const toml::basic_value<C, M, A>& v)
|
||||||
|
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
|
||||||
|
{}
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
|
|
||||||
} // extlib2
|
} // extlib2
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
@@ -284,6 +309,27 @@ BOOST_AUTO_TEST_CASE(test_conversion_one_way)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_conversion_via_constructor)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::value v{{"a", 42}, {"b", "foobar"}};
|
||||||
|
|
||||||
|
const auto foobar = toml::get<extlib::foobar>(v);
|
||||||
|
BOOST_TEST(foobar.a == 42);
|
||||||
|
BOOST_TEST(foobar.b == "foobar");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::basic_value<toml::discard_comments, std::map> v{
|
||||||
|
{"a", 42}, {"b", "foobar"}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto foobar = toml::get<extlib2::foobar>(v);
|
||||||
|
BOOST_TEST(foobar.a == 42);
|
||||||
|
BOOST_TEST(foobar.b == "foobar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -384,5 +430,63 @@ BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
|||||||
BOOST_TEST(bars.at(2).b == "quux");
|
BOOST_TEST(bars.at(2).b == "quux");
|
||||||
BOOST_TEST(bars.at(3).b == "foobar");
|
BOOST_TEST(bars.at(3).b == "foobar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// via constructor
|
||||||
|
{
|
||||||
|
const toml::value v{
|
||||||
|
toml::table{{"a", 42}, {"b", "baz"}},
|
||||||
|
toml::table{{"a", 43}, {"b", "qux"}},
|
||||||
|
toml::table{{"a", 44}, {"b", "quux"}},
|
||||||
|
toml::table{{"a", 45}, {"b", "foobar"}}
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto foobars = toml::get<std::vector<extlib::foobar>>(v);
|
||||||
|
BOOST_TEST(foobars.size() == 4ul);
|
||||||
|
BOOST_TEST(foobars.at(0).a == 42);
|
||||||
|
BOOST_TEST(foobars.at(1).a == 43);
|
||||||
|
BOOST_TEST(foobars.at(2).a == 44);
|
||||||
|
BOOST_TEST(foobars.at(3).a == 45);
|
||||||
|
|
||||||
|
BOOST_TEST(foobars.at(0).b == "baz");
|
||||||
|
BOOST_TEST(foobars.at(1).b == "qux");
|
||||||
|
BOOST_TEST(foobars.at(2).b == "quux");
|
||||||
|
BOOST_TEST(foobars.at(3).b == "foobar");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
|
||||||
|
BOOST_TEST(foobars.size() == 4ul);
|
||||||
|
BOOST_TEST(foobars.at(0).a == 42);
|
||||||
|
BOOST_TEST(foobars.at(1).a == 43);
|
||||||
|
BOOST_TEST(foobars.at(2).a == 44);
|
||||||
|
BOOST_TEST(foobars.at(3).a == 45);
|
||||||
|
|
||||||
|
BOOST_TEST(foobars.at(0).b == "baz");
|
||||||
|
BOOST_TEST(foobars.at(1).b == "qux");
|
||||||
|
BOOST_TEST(foobars.at(2).b == "quux");
|
||||||
|
BOOST_TEST(foobars.at(3).b == "foobar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::basic_value<toml::discard_comments, std::map, std::deque>
|
||||||
|
v{
|
||||||
|
toml::table{{"a", 42}, {"b", "baz"}},
|
||||||
|
toml::table{{"a", 43}, {"b", "qux"}},
|
||||||
|
toml::table{{"a", 44}, {"b", "quux"}},
|
||||||
|
toml::table{{"a", 45}, {"b", "foobar"}}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
|
||||||
|
BOOST_TEST(foobars.size() == 4ul);
|
||||||
|
BOOST_TEST(foobars.at(0).a == 42);
|
||||||
|
BOOST_TEST(foobars.at(1).a == 43);
|
||||||
|
BOOST_TEST(foobars.at(2).a == 44);
|
||||||
|
BOOST_TEST(foobars.at(3).a == 45);
|
||||||
|
|
||||||
|
BOOST_TEST(foobars.at(0).b == "baz");
|
||||||
|
BOOST_TEST(foobars.at(1).b == "qux");
|
||||||
|
BOOST_TEST(foobars.at(2).b == "quux");
|
||||||
|
BOOST_TEST(foobars.at(3).b == "foobar");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,78 @@ BOOST_AUTO_TEST_CASE(test_find_throws)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_find_array_throws)
|
||||||
|
{
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// const-reference version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
const toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(v, 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// non-const reference version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(v, 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// move version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(std::move(v), 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(std::move(v), 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
||||||
{
|
{
|
||||||
// recursively search tables
|
// recursively search tables
|
||||||
@@ -126,8 +198,76 @@ BOOST_AUTO_TEST_CASE(test_find_recursive)
|
|||||||
num2 = 42;
|
num2 = 42;
|
||||||
BOOST_TEST(42 == toml::find<int>(v, a, b, c, d));
|
BOOST_TEST(42 == toml::find<int>(v, a, b, c, d));
|
||||||
|
|
||||||
auto num3 = toml::find<toml::integer>(std::move(v), a, b, c, d);
|
auto num3 = toml::find<toml::integer>(v, a, "b", c, "d");
|
||||||
BOOST_TEST(42 == num3);
|
BOOST_TEST(42 == num3);
|
||||||
|
|
||||||
|
auto num4 = toml::find<toml::integer>(std::move(v), a, b, c, d);
|
||||||
|
BOOST_TEST(42 == num4);
|
||||||
|
}
|
||||||
|
// recursively search arrays
|
||||||
|
{
|
||||||
|
toml::value v{
|
||||||
|
toml::array{"array", "of", "string"},
|
||||||
|
toml::array{toml::array{1, 2, 3}, toml::array{3.14, 2.71}}
|
||||||
|
};
|
||||||
|
BOOST_TEST("array" == toml::find<std::string>(v, 0, 0));
|
||||||
|
BOOST_TEST("of" == toml::find<std::string>(v, 0, 1));
|
||||||
|
BOOST_TEST("string" == toml::find<std::string>(v, 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST(1 == toml::find<int>(v, 1, 0, 0));
|
||||||
|
BOOST_TEST(2 == toml::find<int>(v, 1, 0, 1));
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 1, 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, 1, 1, 0));
|
||||||
|
BOOST_TEST(2.71 == toml::find<double>(v, 1, 1, 1));
|
||||||
|
|
||||||
|
// reference that can be used to modify the content
|
||||||
|
auto& num = toml::find<toml::integer>(v, 1, 0, 2);
|
||||||
|
num = 42;
|
||||||
|
BOOST_TEST( 1 == toml::find<int>(v, 1, 0, 0));
|
||||||
|
BOOST_TEST( 2 == toml::find<int>(v, 1, 0, 1));
|
||||||
|
BOOST_TEST(42 == toml::find<int>(v, 1, 0, 2));
|
||||||
|
|
||||||
|
// move value
|
||||||
|
auto num2 = toml::find<toml::integer>(std::move(v), 1, 0, 2);
|
||||||
|
BOOST_TEST(42 == num2);
|
||||||
|
}
|
||||||
|
// recursively search mixtures
|
||||||
|
{
|
||||||
|
toml::value v = toml::table{{"array", toml::array{
|
||||||
|
toml::array{1, 2, 3},
|
||||||
|
toml::array{
|
||||||
|
toml::table{{"foo", "bar"}, {"baz", "qux"}},
|
||||||
|
toml::table{{"pi", 3.14}, {"e", 2.71}}
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
|
||||||
|
BOOST_TEST(1 == toml::find<int>(v, "array", 0, 0));
|
||||||
|
BOOST_TEST(2 == toml::find<int>(v, "array", 0, 1));
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, "array", 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST("bar" == toml::find<std::string>(v, "array", 1, 0, "foo"));
|
||||||
|
BOOST_TEST("qux" == toml::find<std::string>(v, "array", 1, 0, "baz"));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, "pi"));
|
||||||
|
BOOST_TEST(2.71 == toml::find<double>(v, "array", 1, 1, "e"));
|
||||||
|
|
||||||
|
const std::string ar("array");
|
||||||
|
const auto ar_c = "array";
|
||||||
|
|
||||||
|
const std::string pi("pi");
|
||||||
|
const auto pi_c = "pi";
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, "pi"));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, pi));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, pi_c));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, "pi"));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, pi));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, pi_c));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, pi));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, pi_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,10 +449,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_ty
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
value_type v{{"key", 3.14}};
|
value_type v{{"key", 3.14}};
|
||||||
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(v, "key"));
|
const double ref(3.14);
|
||||||
BOOST_TEST(static_cast<double >(3.14) == toml::find<double >(v, "key"));
|
BOOST_TEST(static_cast<float >(ref) == toml::find<float >(v, "key"));
|
||||||
BOOST_TEST(static_cast<long double>(3.14) == toml::find<long double>(v, "key"));
|
BOOST_TEST( ref == toml::find<double >(v, "key"));
|
||||||
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(std::move(v), "key"));
|
BOOST_TEST(static_cast<long double>(ref) == toml::find<long double>(v, "key"));
|
||||||
|
BOOST_TEST(static_cast<float >(ref) == toml::find<float >(std::move(v), "key"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,14 +514,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array, value_type, test_value_types
|
|||||||
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
||||||
|
|
||||||
std::array<int, 4> ary = toml::find<std::array<int, 4>>(v, "key");
|
std::array<int, 4> ary = toml::find<std::array<int, 4>>(v, "key");
|
||||||
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
BOOST_TEST(42 == ary.at(0));
|
||||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
BOOST_TEST(54 == ary.at(1));
|
||||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
BOOST_TEST(69 == ary.at(2));
|
||||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
BOOST_TEST(72 == ary.at(3));
|
||||||
|
|
||||||
std::tuple<int, short, unsigned, long> tpl =
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
toml::find<std::tuple<int, short, unsigned, long>>(v, "key");
|
toml::find<std::tuple<int, short, unsigned, long>>(v, "key");
|
||||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
BOOST_TEST( 42 == std::get<0>(tpl));
|
||||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(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<unsigned>(69) == std::get<2>(tpl));
|
||||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||||
@@ -420,14 +561,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array, value_type, test_value_
|
|||||||
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
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");
|
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(42 == ary.at(0));
|
||||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
BOOST_TEST(54 == ary.at(1));
|
||||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
BOOST_TEST(69 == ary.at(2));
|
||||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
BOOST_TEST(72 == ary.at(3));
|
||||||
|
|
||||||
std::tuple<int, short, unsigned, long> tpl =
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
toml::find<std::tuple<int, short, unsigned, long>>(std::move(v5), "key");
|
toml::find<std::tuple<int, short, unsigned, long>>(std::move(v5), "key");
|
||||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
BOOST_TEST( 42 == std::get<0>(tpl));
|
||||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(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<unsigned>(69) == std::get<2>(tpl));
|
||||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||||
|
|||||||
@@ -375,7 +375,8 @@ BOOST_AUTO_TEST_CASE(test_find_or_floating)
|
|||||||
toml::value v1{{"key", 42}};
|
toml::value v1{{"key", 42}};
|
||||||
toml::value v2{{"key", 3.14}};
|
toml::value v2{{"key", 3.14}};
|
||||||
BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f));
|
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));
|
const double ref(3.14);
|
||||||
|
BOOST_TEST(static_cast<float>(ref) == toml::find_or(v2, "key", 2.71f));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::value v1{{"key", 42}};
|
toml::value v1{{"key", 42}};
|
||||||
@@ -383,7 +384,8 @@ BOOST_AUTO_TEST_CASE(test_find_or_floating)
|
|||||||
const auto moved1 = toml::find_or(std::move(v1), "key", 2.71f);
|
const auto moved1 = toml::find_or(std::move(v1), "key", 2.71f);
|
||||||
const auto moved2 = toml::find_or(std::move(v2), "key", 2.71f);
|
const auto moved2 = toml::find_or(std::move(v2), "key", 2.71f);
|
||||||
BOOST_TEST(2.71f == moved1);
|
BOOST_TEST(2.71f == moved1);
|
||||||
BOOST_TEST(static_cast<float>(double(3.14)) == moved2);
|
const double ref(3.14);
|
||||||
|
BOOST_TEST(static_cast<float>(ref) == moved2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -195,11 +195,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_typ
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
value_type v(3.14);
|
value_type v(3.14);
|
||||||
BOOST_TEST(static_cast<float >(3.14) == toml::get<float >(v));
|
const double ref(3.14);
|
||||||
BOOST_TEST(static_cast<double >(3.14) == toml::get<double >(v));
|
BOOST_TEST(static_cast<float >(ref) == toml::get<float >(v));
|
||||||
BOOST_TEST(static_cast<long double>(3.14) == toml::get<long double>(v));
|
BOOST_TEST( ref == toml::get<double >(v));
|
||||||
|
BOOST_TEST(static_cast<long double>(ref) == toml::get<long double>(v));
|
||||||
BOOST_TEST(3.14f == toml::get<float>(std::move(v)));
|
BOOST_TEST(static_cast<float >(ref) == toml::get<float>(std::move(v)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,14 +262,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
|
|||||||
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
||||||
|
|
||||||
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
|
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
|
||||||
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
BOOST_TEST(42 == ary.at(0));
|
||||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
BOOST_TEST(54 == ary.at(1));
|
||||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
BOOST_TEST(69 == ary.at(2));
|
||||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
BOOST_TEST(72 == ary.at(3));
|
||||||
|
|
||||||
std::tuple<int, short, unsigned, long> tpl =
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
toml::get<std::tuple<int, short, unsigned, long>>(v);
|
toml::get<std::tuple<int, short, unsigned, long>>(v);
|
||||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
BOOST_TEST( 42 == std::get<0>(tpl));
|
||||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(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<unsigned>(69) == std::get<2>(tpl));
|
||||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||||
@@ -308,16 +308,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
|
|||||||
{
|
{
|
||||||
value_type v{42, 54, 69, 72};
|
value_type v{42, 54, 69, 72};
|
||||||
std::array<int, 4> ary = toml::get<std::array<int, 4>>(std::move(v));
|
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(42 == ary.at(0));
|
||||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
BOOST_TEST(54 == ary.at(1));
|
||||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
BOOST_TEST(69 == ary.at(2));
|
||||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
BOOST_TEST(72 == ary.at(3));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v{42, 54, 69, 72};
|
value_type v{42, 54, 69, 72};
|
||||||
std::tuple<int, short, unsigned, long> tpl =
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
toml::get<std::tuple<int, short, unsigned, long>>(std::move(v));
|
toml::get<std::tuple<int, short, unsigned, long>>(std::move(v));
|
||||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
BOOST_TEST( 42 == std::get<0>(tpl));
|
||||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(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<unsigned>(69) == std::get<2>(tpl));
|
||||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||||
|
|||||||
@@ -966,3 +966,54 @@ BOOST_AUTO_TEST_CASE(test_value_bracket)
|
|||||||
BOOST_CHECK_THROW(v1["foo"], toml::type_error);
|
BOOST_CHECK_THROW(v1["foo"], toml::type_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_map_methods)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}};
|
||||||
|
|
||||||
|
BOOST_TEST(v1.count("foo") == 1u);
|
||||||
|
BOOST_TEST(v1.count("bar") == 1u);
|
||||||
|
BOOST_TEST(v1.count("baz") == 1u);
|
||||||
|
BOOST_TEST(v1.count("qux") == 0u);
|
||||||
|
|
||||||
|
BOOST_TEST( v1.contains("foo"));
|
||||||
|
BOOST_TEST( v1.contains("bar"));
|
||||||
|
BOOST_TEST( v1.contains("baz"));
|
||||||
|
BOOST_TEST(!v1.contains("qux"));
|
||||||
|
|
||||||
|
BOOST_TEST(v1.size() == 3);
|
||||||
|
|
||||||
|
v1["qux"] = 54;
|
||||||
|
BOOST_TEST(v1.count("qux") == 1u);
|
||||||
|
BOOST_TEST(v1.contains("qux"));
|
||||||
|
BOOST_TEST(v1.size() == 4);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
BOOST_CHECK_THROW(v1.size() , toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.count("k") , toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.contains("k"), toml::type_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_vector_methods)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v1{1, 2, 3, 4, 5};
|
||||||
|
|
||||||
|
BOOST_TEST(v1.size() == 5);
|
||||||
|
|
||||||
|
v1.push_back(6);
|
||||||
|
BOOST_TEST(v1.size() == 6);
|
||||||
|
|
||||||
|
v1.emplace_back(6);
|
||||||
|
BOOST_TEST(v1.size() == 7);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
BOOST_CHECK_THROW(v1.size(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.push_back(1), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.emplace_back(1), toml::type_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
172
tests/test_visit.cpp
Normal file
172
tests/test_visit.cpp
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_visit"
|
||||||
|
#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>
|
||||||
|
#include <map>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
using test_value_types = std::tuple<
|
||||||
|
toml::value,
|
||||||
|
toml::basic_value<toml::preserve_comments>,
|
||||||
|
toml::basic_value<toml::discard_comments, std::map, std::deque>,
|
||||||
|
toml::basic_value<toml::preserve_comments, std::map, std::deque>
|
||||||
|
>;
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
struct visitor1
|
||||||
|
{
|
||||||
|
std::string operator()(const toml::boolean&) const {return "boolean";}
|
||||||
|
std::string operator()(const toml::integer&) const {return "integer";}
|
||||||
|
std::string operator()(const toml::floating&) const {return "floating";}
|
||||||
|
std::string operator()(const toml::string&) const {return "string";}
|
||||||
|
std::string operator()(const toml::local_time&) const {return "local_time";}
|
||||||
|
std::string operator()(const toml::local_date&) const {return "local_date";}
|
||||||
|
std::string operator()(const toml::local_datetime&) const {return "local_datetime";}
|
||||||
|
std::string operator()(const toml::offset_datetime&) const {return "offset_datetime";}
|
||||||
|
std::string operator()(const typename Value::array_type&) const {return "array";}
|
||||||
|
std::string operator()(const typename Value::table_type&) const {return "table";}
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_visit_one, value_type, test_value_types)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const value_type v(true);
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "boolean");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v(42);
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "integer");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v(3.14);
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "floating");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v("foo");
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "string");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v(toml::local_date(2018, toml::month_t::Apr, 22));
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "local_date");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v(toml::local_time(12, 34, 56));
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "local_time");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v(toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
|
toml::local_time(12, 34, 56)));
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "local_datetime");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v(toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
|
toml::local_time(12, 34, 56),
|
||||||
|
toml::time_offset(9, 0)));
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "offset_datetime");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v{1,2,3,4,5};
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "array");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v{
|
||||||
|
{"foo", 42}, {"bar", "baz"}
|
||||||
|
};
|
||||||
|
BOOST_TEST(toml::visit(visitor1<value_type>{}, v) == "table");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
struct visitor2
|
||||||
|
{
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
std::string operator()(const T1& v1, const T2& v2) const
|
||||||
|
{
|
||||||
|
visitor1<Value> vis;
|
||||||
|
return vis(v1) + "+" + vis(v2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_visit_two, value_type, test_value_types)
|
||||||
|
{
|
||||||
|
std::vector<value_type> vs;
|
||||||
|
vs.push_back(value_type(true));
|
||||||
|
vs.push_back(value_type(42));
|
||||||
|
vs.push_back(value_type(3.14));
|
||||||
|
vs.push_back(value_type("foo"));
|
||||||
|
vs.push_back(value_type(toml::local_date(2018, toml::month_t::Apr, 22)));
|
||||||
|
vs.push_back(value_type(toml::local_time(12, 34, 56)));
|
||||||
|
vs.push_back(value_type(toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
|
toml::local_time(12, 34, 56))));
|
||||||
|
vs.push_back(value_type(toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
|
toml::local_time(12, 34, 56),
|
||||||
|
toml::time_offset(9, 0))));
|
||||||
|
vs.push_back(value_type{1,2,3,4,5});
|
||||||
|
vs.push_back(value_type{{"foo", 42}, {"bar", "baz"}});
|
||||||
|
|
||||||
|
for(const auto& v1 : vs)
|
||||||
|
{
|
||||||
|
const auto t1 = toml::visit(visitor1<value_type>{}, v1);
|
||||||
|
for(const auto& v2 : vs)
|
||||||
|
{
|
||||||
|
const auto t2 = toml::visit(visitor1<value_type>{}, v2);
|
||||||
|
BOOST_TEST(toml::visit(visitor2<value_type>{}, v1, v2) ==
|
||||||
|
t1 + "+" + t2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
struct visitor3
|
||||||
|
{
|
||||||
|
template<typename T1, typename T2, typename T3>
|
||||||
|
std::string operator()(const T1& v1, const T2& v2, const T3& v3) const
|
||||||
|
{
|
||||||
|
visitor1<Value> vis;
|
||||||
|
return vis(v1) + "+" + vis(v2) + "+" + vis(v3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_visit_three, value_type, test_value_types)
|
||||||
|
{
|
||||||
|
std::vector<value_type> vs;
|
||||||
|
vs.push_back(value_type(true));
|
||||||
|
vs.push_back(value_type(42));
|
||||||
|
vs.push_back(value_type(3.14));
|
||||||
|
vs.push_back(value_type("foo"));
|
||||||
|
vs.push_back(value_type(toml::local_date(2018, toml::month_t::Apr, 22)));
|
||||||
|
vs.push_back(value_type(toml::local_time(12, 34, 56)));
|
||||||
|
vs.push_back(value_type(toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
|
toml::local_time(12, 34, 56))));
|
||||||
|
vs.push_back(value_type(toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
|
toml::local_time(12, 34, 56),
|
||||||
|
toml::time_offset(9, 0))));
|
||||||
|
vs.push_back(value_type{1,2,3,4,5});
|
||||||
|
vs.push_back(value_type{{"foo", 42}, {"bar", "baz"}});
|
||||||
|
|
||||||
|
for(const auto& v1 : vs)
|
||||||
|
{
|
||||||
|
const auto t1 = toml::visit(visitor1<value_type>{}, v1);
|
||||||
|
for(const auto& v2 : vs)
|
||||||
|
{
|
||||||
|
const auto t2 = toml::visit(visitor1<value_type>{}, v2);
|
||||||
|
for(const auto& v3 : vs)
|
||||||
|
{
|
||||||
|
const auto t3 = toml::visit(visitor1<value_type>{}, v3);
|
||||||
|
BOOST_TEST(toml::visit(visitor3<value_type>{}, v1, v2, v3) ==
|
||||||
|
t1 + "+" + t2 + "+" + t3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -173,7 +173,7 @@ std::basic_ostream<charT, traits>&
|
|||||||
operator<<(std::basic_ostream<charT, traits>& os, const local_date& date)
|
operator<<(std::basic_ostream<charT, traits>& os, const local_date& date)
|
||||||
{
|
{
|
||||||
os << std::setfill('0') << std::setw(4) << static_cast<int>(date.year ) << '-';
|
os << std::setfill('0') << std::setw(4) << static_cast<int>(date.year ) << '-';
|
||||||
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.month + 1) << '-';
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.month) + 1 << '-';
|
||||||
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.day ) ;
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.day ) ;
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace toml
|
|||||||
struct exception : public std::exception
|
struct exception : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
exception(const source_location& loc): loc_(loc) {}
|
explicit exception(const source_location& loc): loc_(loc) {}
|
||||||
virtual ~exception() noexcept override = default;
|
virtual ~exception() noexcept override = default;
|
||||||
virtual const char* what() const noexcept override {return "";}
|
virtual const char* what() const noexcept override {return "";}
|
||||||
virtual source_location const& location() const noexcept {return loc_;}
|
virtual source_location const& location() const noexcept {return loc_;}
|
||||||
|
|||||||
197
toml/get.hpp
197
toml/get.hpp
@@ -259,6 +259,15 @@ template<typename T, typename C,
|
|||||||
std::size_t S = sizeof(::toml::from<T>)>
|
std::size_t S = sizeof(::toml::from<T>)>
|
||||||
T get(const basic_value<C, M, V>&);
|
T get(const basic_value<C, M, V>&);
|
||||||
|
|
||||||
|
// T(const toml::value&) and T is not toml::basic_value
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
detail::enable_if_t<detail::conjunction<
|
||||||
|
detail::negation<detail::is_basic_value<T>>,
|
||||||
|
std::is_constructible<T, const basic_value<C, M, V>&>
|
||||||
|
>::value, T>
|
||||||
|
get(const basic_value<C, M, V>&);
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// array-like types; most likely STL container, like std::vector, etc.
|
// array-like types; most likely STL container, like std::vector, etc.
|
||||||
|
|
||||||
@@ -417,6 +426,17 @@ T get(const basic_value<C, M, V>& v)
|
|||||||
return ::toml::from<T>::from_toml(v);
|
return ::toml::from<T>::from_toml(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
detail::enable_if_t<detail::conjunction<
|
||||||
|
detail::negation<detail::is_basic_value<T>>,
|
||||||
|
std::is_constructible<T, const basic_value<C, M, V>&>
|
||||||
|
>::value, T>
|
||||||
|
get(const basic_value<C, M, V>& v)
|
||||||
|
{
|
||||||
|
return T(v);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// find
|
// find
|
||||||
|
|
||||||
@@ -465,6 +485,52 @@ basic_value<C, M, V> find(basic_value<C, M, V>&& v, const key& ky)
|
|||||||
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// find(value, idx)
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> const&
|
||||||
|
find(const basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
const auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ary.at(idx);
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>& find(basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ary.at(idx);
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> find(basic_value<C, M, V>&& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return basic_value<C, M, V>(std::move(ary.at(idx)));
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// find<T>(value, key);
|
// find<T>(value, key);
|
||||||
|
|
||||||
@@ -516,57 +582,152 @@ find(basic_value<C, M, V>&& v, const key& ky)
|
|||||||
return ::toml::get<T>(std::move(tab.at(ky)));
|
return ::toml::get<T>(std::move(tab.at(ky)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// find<T>(value, idx)
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))
|
||||||
|
find(const basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
const auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(ary.at(idx));
|
||||||
|
}
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
||||||
|
find(basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(ary.at(idx));
|
||||||
|
}
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
||||||
|
find(basic_value<C, M, V>&& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
typename basic_value<C, M, V>::array_type ary = std::move(v).as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(std::move(ary.at(idx)));
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// It suppresses warnings by -Wsign-conversion. Let's say we have the following
|
||||||
|
// code.
|
||||||
|
// ```cpp
|
||||||
|
// const auto x = toml::find<std::string>(data, "array", 0);
|
||||||
|
// ```
|
||||||
|
// Here, the type of literal number `0` is `int`. `int` is a signed integer.
|
||||||
|
// `toml::find` takes `std::size_t` as an index. So it causes implicit sign
|
||||||
|
// conversion and `-Wsign-conversion` warns about it. Using `0u` instead of `0`
|
||||||
|
// suppresses the warning, but it makes user code messy.
|
||||||
|
// To suppress this warning, we need to be aware of type conversion caused
|
||||||
|
// by `toml::find(v, key1, key2, ... keys)`. But the thing is that the types of
|
||||||
|
// keys can be any combination of {string-like, size_t-like}. Of course we can't
|
||||||
|
// write down all the combinations. Thus we need to use some function that
|
||||||
|
// recognize the type of argument and cast it into `std::string` or
|
||||||
|
// `std::size_t` depending on the context.
|
||||||
|
// `key_cast` does the job. It has 2 overloads. One is invoked when the
|
||||||
|
// argument type is an integer and cast the argument into `std::size_t`. The
|
||||||
|
// other is invoked when the argument type is not an integer, possibly one of
|
||||||
|
// std::string, const char[N] or const char*, and construct std::string from
|
||||||
|
// the argument.
|
||||||
|
// `toml::find(v, k1, k2, ... ks)` uses `key_cast` before passing `ks` to
|
||||||
|
// `toml::find(v, k)` to suppress -Wsign-conversion.
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
enable_if_t<conjunction<std::is_integral<remove_cvref_t<T>>,
|
||||||
|
negation<std::is_same<remove_cvref_t<T>, bool>>>::value, std::size_t>
|
||||||
|
key_cast(T&& v) noexcept
|
||||||
|
{
|
||||||
|
return std::size_t(v);
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
enable_if_t<negation<conjunction<std::is_integral<remove_cvref_t<T>>,
|
||||||
|
negation<std::is_same<remove_cvref_t<T>, bool>>>>::value, std::string>
|
||||||
|
key_cast(T&& v) noexcept
|
||||||
|
{
|
||||||
|
return std::string(std::forward<T>(v));
|
||||||
|
}
|
||||||
|
} // detail
|
||||||
|
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
const basic_value<C, M, V>&
|
const basic_value<C, M, V>&
|
||||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(v, detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
basic_value<C, M, V>&
|
basic_value<C, M, V>&
|
||||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(v, detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
basic_value<C, M, V>
|
basic_value<C, M, V>
|
||||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(std::move(v), std::forward<Key1>(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>()))
|
decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>()))
|
||||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(v, detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
||||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(v, detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
||||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(std::move(v), detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ std::string read_utf8_codepoint(const region<Container>& reg,
|
|||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> std::hex >> codepoint;
|
iss >> std::hex >> codepoint;
|
||||||
|
|
||||||
const auto to_char = [](const int i) noexcept -> char {
|
const auto to_char = [](const std::uint_least32_t i) noexcept -> char {
|
||||||
const auto uc = static_cast<unsigned char>(i);
|
const auto uc = static_cast<unsigned char>(i);
|
||||||
return *reinterpret_cast<const char*>(std::addressof(uc));
|
return *reinterpret_cast<const char*>(std::addressof(uc));
|
||||||
};
|
};
|
||||||
@@ -792,13 +792,13 @@ parse_offset_datetime(location<Container>& loc)
|
|||||||
const auto str = ofs.unwrap().str();
|
const auto str = ofs.unwrap().str();
|
||||||
if(str.front() == '+')
|
if(str.front() == '+')
|
||||||
{
|
{
|
||||||
offset.hour = static_cast<std::int8_t>(from_string<int>(str.substr(1,2), 0));
|
offset = time_offset(from_string<int>(str.substr(1,2), 0),
|
||||||
offset.minute = static_cast<std::int8_t>(from_string<int>(str.substr(4,2), 0));
|
from_string<int>(str.substr(4,2), 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offset.hour = -static_cast<std::int8_t>(from_string<int>(str.substr(1,2), 0));
|
offset = time_offset(-from_string<int>(str.substr(1,2), 0),
|
||||||
offset.minute = -static_cast<std::int8_t>(from_string<int>(str.substr(4,2), 0));
|
-from_string<int>(str.substr(4,2), 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(*inner_loc.iter() != 'Z' && *inner_loc.iter() != 'z')
|
else if(*inner_loc.iter() != 'Z' && *inner_loc.iter() != 'z')
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#define TOML11_SERIALIZER_HPP
|
#define TOML11_SERIALIZER_HPP
|
||||||
#include "value.hpp"
|
#include "value.hpp"
|
||||||
#include "lexer.hpp"
|
#include "lexer.hpp"
|
||||||
|
#include "visit.hpp"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,9 @@ struct storage
|
|||||||
{
|
{
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
storage(value_type const& v): ptr(toml::make_unique<T>(v)) {}
|
explicit storage(value_type const& v): ptr(toml::make_unique<T>(v)) {}
|
||||||
storage(value_type&& v): ptr(toml::make_unique<T>(std::move(v))) {}
|
explicit storage(value_type&& v): ptr(toml::make_unique<T>(std::move(v))) {}
|
||||||
~storage() = default;
|
~storage() = default;
|
||||||
|
|
||||||
storage(const storage& rhs): ptr(toml::make_unique<T>(*rhs.ptr)) {}
|
storage(const storage& rhs): ptr(toml::make_unique<T>(*rhs.ptr)) {}
|
||||||
storage& operator=(const storage& rhs)
|
storage& operator=(const storage& rhs)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -111,6 +111,14 @@ struct has_into_toml_method
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// C++17 and/or/not
|
// C++17 and/or/not
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
|
||||||
|
using std::conjunction;
|
||||||
|
using std::disjunction;
|
||||||
|
using std::negation;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template<typename ...> struct conjunction : std::true_type{};
|
template<typename ...> struct conjunction : std::true_type{};
|
||||||
template<typename T> struct conjunction<T> : T{};
|
template<typename T> struct conjunction<T> : T{};
|
||||||
template<typename T, typename ... Ts>
|
template<typename T, typename ... Ts>
|
||||||
@@ -128,6 +136,8 @@ struct disjunction<T, Ts...> :
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
|
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// type checkers
|
// type checkers
|
||||||
|
|
||||||
@@ -182,6 +192,13 @@ struct is_basic_value<::toml::basic_value<C, M, V>>: std::true_type{};
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// C++14 index_sequence
|
// C++14 index_sequence
|
||||||
|
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
|
||||||
|
using std::index_sequence;
|
||||||
|
using std::make_index_sequence;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template<std::size_t ... Ns> struct index_sequence{};
|
template<std::size_t ... Ns> struct index_sequence{};
|
||||||
|
|
||||||
template<typename IS, std::size_t N> struct push_back_index_sequence{};
|
template<typename IS, std::size_t N> struct push_back_index_sequence{};
|
||||||
@@ -205,11 +222,22 @@ struct index_sequence_maker<0>
|
|||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
using make_index_sequence = typename index_sequence_maker<N-1>::type;
|
using make_index_sequence = typename index_sequence_maker<N-1>::type;
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 2014
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// C++14 enable_if_t
|
// C++14 enable_if_t
|
||||||
|
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
|
||||||
|
using std::enable_if_t;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template<bool B, typename T>
|
template<bool B, typename T>
|
||||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 2014
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// return_type_of_t
|
// return_type_of_t
|
||||||
|
|
||||||
|
|||||||
@@ -20,12 +20,20 @@
|
|||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template<typename T, typename ... Ts>
|
template<typename T, typename ... Ts>
|
||||||
inline std::unique_ptr<T> make_unique(Ts&& ... args)
|
inline std::unique_ptr<T> make_unique(Ts&& ... args)
|
||||||
{
|
{
|
||||||
return std::unique_ptr<T>(new T(std::forward<Ts>(args)...));
|
return std::unique_ptr<T>(new T(std::forward<Ts>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 2014
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -76,10 +84,10 @@ std::string concat_to_string(Ts&& ... args)
|
|||||||
return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...);
|
return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<typename T>
|
||||||
T from_string(const std::string& str, U&& opt)
|
T from_string(const std::string& str, T opt)
|
||||||
{
|
{
|
||||||
T v(static_cast<T>(std::forward<U>(opt)));
|
T v(opt);
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> v;
|
iss >> v;
|
||||||
return v;
|
return v;
|
||||||
|
|||||||
342
toml/value.hpp
342
toml/value.hpp
@@ -529,14 +529,6 @@ class basic_value
|
|||||||
assigner(this->boolean_, b);
|
assigner(this->boolean_, b);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(boolean b, detail::region<Container> reg)
|
|
||||||
: type_(value_t::boolean),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->boolean_, b);
|
|
||||||
}
|
|
||||||
basic_value(boolean b, std::vector<std::string> comments)
|
basic_value(boolean b, std::vector<std::string> comments)
|
||||||
: type_(value_t::boolean),
|
: type_(value_t::boolean),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -557,19 +549,6 @@ class basic_value
|
|||||||
assigner(this->integer_, static_cast<integer>(i));
|
assigner(this->integer_, static_cast<integer>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
|
||||||
detail::conjunction<
|
|
||||||
std::is_integral<T>,
|
|
||||||
detail::negation<std::is_same<T, boolean>>
|
|
||||||
>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
basic_value(T i, detail::region<Container> reg)
|
|
||||||
: type_(value_t::integer),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->integer_, static_cast<integer>(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename std::enable_if<detail::conjunction<
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
|
std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
|
||||||
std::nullptr_t>::type = nullptr>
|
std::nullptr_t>::type = nullptr>
|
||||||
@@ -604,15 +583,6 @@ class basic_value
|
|||||||
assigner(this->floating_, static_cast<floating>(f));
|
assigner(this->floating_, static_cast<floating>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
|
||||||
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
basic_value(T f, detail::region<Container> reg)
|
|
||||||
: type_(value_t::floating),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->floating_, static_cast<floating>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename std::enable_if<
|
template<typename T, typename std::enable_if<
|
||||||
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
@@ -643,14 +613,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->string_, std::move(s));
|
assigner(this->string_, std::move(s));
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(toml::string s, detail::region<Container> reg)
|
|
||||||
: type_(value_t::string),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->string_, std::move(s));
|
|
||||||
}
|
|
||||||
basic_value& operator=(toml::string s)
|
basic_value& operator=(toml::string s)
|
||||||
{
|
{
|
||||||
this->cleanup();
|
this->cleanup();
|
||||||
@@ -782,14 +744,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->local_date_, ld);
|
assigner(this->local_date_, ld);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const local_date& ld, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_date),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->local_date_, ld);
|
|
||||||
}
|
|
||||||
basic_value& operator=(const local_date& ld)
|
basic_value& operator=(const local_date& ld)
|
||||||
{
|
{
|
||||||
this->cleanup();
|
this->cleanup();
|
||||||
@@ -814,14 +768,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->local_time_, lt);
|
assigner(this->local_time_, lt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const local_time& lt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_time),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->local_time_, lt);
|
|
||||||
}
|
|
||||||
basic_value(const local_time& lt, std::vector<std::string> comments)
|
basic_value(const local_time& lt, std::vector<std::string> comments)
|
||||||
: type_(value_t::local_time),
|
: type_(value_t::local_time),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -872,14 +818,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->local_datetime_, ldt);
|
assigner(this->local_datetime_, ldt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const local_datetime& ldt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_datetime),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->local_datetime_, ldt);
|
|
||||||
}
|
|
||||||
basic_value(const local_datetime& ldt, std::vector<std::string> comments)
|
basic_value(const local_datetime& ldt, std::vector<std::string> comments)
|
||||||
: type_(value_t::local_datetime),
|
: type_(value_t::local_datetime),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -904,14 +842,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->offset_datetime_, odt);
|
assigner(this->offset_datetime_, odt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const offset_datetime& odt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::offset_datetime),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->offset_datetime_, odt);
|
|
||||||
}
|
|
||||||
basic_value(const offset_datetime& odt, std::vector<std::string> comments)
|
basic_value(const offset_datetime& odt, std::vector<std::string> comments)
|
||||||
: type_(value_t::offset_datetime),
|
: type_(value_t::offset_datetime),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -958,14 +888,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->array_, ary);
|
assigner(this->array_, ary);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const array_type& ary, detail::region<Container> reg)
|
|
||||||
: type_(value_t::array),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->array_, ary);
|
|
||||||
}
|
|
||||||
basic_value(const array_type& ary, std::vector<std::string> comments)
|
basic_value(const array_type& ary, std::vector<std::string> comments)
|
||||||
: type_(value_t::array),
|
: type_(value_t::array),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -1079,14 +1001,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->table_, tab);
|
assigner(this->table_, tab);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const table_type& tab, detail::region<Container> reg)
|
|
||||||
: type_(value_t::table),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->table_, tab);
|
|
||||||
}
|
|
||||||
basic_value(const table_type& tab, std::vector<std::string> comments)
|
basic_value(const table_type& tab, std::vector<std::string> comments)
|
||||||
: type_(value_t::table),
|
: type_(value_t::table),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -1216,6 +1130,93 @@ class basic_value
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for internal use ------------------------------------------------------
|
// for internal use ------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Those constructors take detail::region that contains parse result.
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(boolean b, detail::region<Container> reg)
|
||||||
|
: type_(value_t::boolean),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->boolean_, b);
|
||||||
|
}
|
||||||
|
template<typename T, typename Container, typename std::enable_if<
|
||||||
|
detail::conjunction<
|
||||||
|
std::is_integral<T>, detail::negation<std::is_same<T, boolean>>
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
basic_value(T i, detail::region<Container> reg)
|
||||||
|
: type_(value_t::integer),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->integer_, static_cast<integer>(i));
|
||||||
|
}
|
||||||
|
template<typename T, typename Container, typename std::enable_if<
|
||||||
|
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
basic_value(T f, detail::region<Container> reg)
|
||||||
|
: type_(value_t::floating),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->floating_, static_cast<floating>(f));
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(toml::string s, detail::region<Container> reg)
|
||||||
|
: type_(value_t::string),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->string_, std::move(s));
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const local_date& ld, detail::region<Container> reg)
|
||||||
|
: type_(value_t::local_date),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->local_date_, ld);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const local_time& lt, detail::region<Container> reg)
|
||||||
|
: type_(value_t::local_time),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->local_time_, lt);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const local_datetime& ldt, detail::region<Container> reg)
|
||||||
|
: type_(value_t::local_datetime),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->local_datetime_, ldt);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const offset_datetime& odt, detail::region<Container> reg)
|
||||||
|
: type_(value_t::offset_datetime),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->offset_datetime_, odt);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const array_type& ary, detail::region<Container> reg)
|
||||||
|
: type_(value_t::array),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->array_, ary);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const table_type& tab, detail::region<Container> reg)
|
||||||
|
: type_(value_t::table),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->table_, tab);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
template<typename T, typename Container, typename std::enable_if<
|
||||||
detail::is_exact_toml_type<T, value_type>::value,
|
detail::is_exact_toml_type<T, value_type>::value,
|
||||||
@@ -1247,7 +1248,7 @@ class basic_value
|
|||||||
bool is_array() const noexcept {return this->is(value_t::array );}
|
bool is_array() const noexcept {return this->is(value_t::array );}
|
||||||
bool is_table() const noexcept {return this->is(value_t::table );}
|
bool is_table() const noexcept {return this->is(value_t::table );}
|
||||||
|
|
||||||
value_t type() const {return type_;}
|
value_t type() const noexcept {return type_;}
|
||||||
|
|
||||||
template<value_t T>
|
template<value_t T>
|
||||||
typename detail::enum_to_type<T, value_type>::type& cast() &
|
typename detail::enum_to_type<T, value_type>::type& cast() &
|
||||||
@@ -1606,6 +1607,101 @@ class basic_value
|
|||||||
return this->as_array(std::nothrow)[idx];
|
return this->as_array(std::nothrow)[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push_back(const value_type& x)
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::array)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::push_back(value): bad_cast to array type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
this->as_array(std::nothrow).push_back(x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void push_back(value_type&& x)
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::array)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::push_back(value): bad_cast to array type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
this->as_array(std::nothrow).push_back(std::move(x));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ... Ts>
|
||||||
|
value_type& emplace_back(Ts&& ... args)
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::array)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::emplace_back(value): bad_cast to array type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
this->as_array(std::nothrow).emplace_back(std::forward<Ts>(args) ...);
|
||||||
|
return this->as_array(std::nothrow).back();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const
|
||||||
|
{
|
||||||
|
switch(this->type_)
|
||||||
|
{
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
return this->as_array().size();
|
||||||
|
}
|
||||||
|
case value_t::table:
|
||||||
|
{
|
||||||
|
return this->as_table().size();
|
||||||
|
}
|
||||||
|
case value_t::string:
|
||||||
|
{
|
||||||
|
return this->as_string().str.size();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::size(): bad_cast to container types", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t count(const key_type& k) const
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::table)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::count(key): bad_cast to table type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
return this->as_table().count(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const key_type& k) const
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::table)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::contains(key): bad_cast to table type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
return (this->as_table().count(k) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
source_location location() const
|
source_location location() const
|
||||||
{
|
{
|
||||||
return source_location(this->region_info_.get());
|
return source_location(this->region_info_.get());
|
||||||
@@ -1899,77 +1995,5 @@ inline std::string format_error(const std::string& err_msg,
|
|||||||
}, std::move(hints), colorize);
|
}, std::move(hints), colorize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Visitor, typename C,
|
|
||||||
template<typename ...> class T, template<typename ...> class A>
|
|
||||||
detail::return_type_of_t<Visitor, const toml::boolean&>
|
|
||||||
visit(Visitor&& visitor, const toml::basic_value<C, T, A>& v)
|
|
||||||
{
|
|
||||||
switch(v.type())
|
|
||||||
{
|
|
||||||
case value_t::boolean : {return visitor(v.as_boolean ());}
|
|
||||||
case value_t::integer : {return visitor(v.as_integer ());}
|
|
||||||
case value_t::floating : {return visitor(v.as_floating ());}
|
|
||||||
case value_t::string : {return visitor(v.as_string ());}
|
|
||||||
case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
|
|
||||||
case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
|
|
||||||
case value_t::local_date : {return visitor(v.as_local_date ());}
|
|
||||||
case value_t::local_time : {return visitor(v.as_local_time ());}
|
|
||||||
case value_t::array : {return visitor(v.as_array ());}
|
|
||||||
case value_t::table : {return visitor(v.as_table ());}
|
|
||||||
case value_t::empty : break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
|
|
||||||
"does not have any valid basic_value.", v, "here"));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Visitor, typename C,
|
|
||||||
template<typename ...> class T, template<typename ...> class A>
|
|
||||||
detail::return_type_of_t<Visitor, toml::boolean&>
|
|
||||||
visit(Visitor&& visitor, toml::basic_value<C, T, A>& v)
|
|
||||||
{
|
|
||||||
switch(v.type())
|
|
||||||
{
|
|
||||||
case value_t::boolean : {return visitor(v.as_boolean ());}
|
|
||||||
case value_t::integer : {return visitor(v.as_integer ());}
|
|
||||||
case value_t::floating : {return visitor(v.as_floating ());}
|
|
||||||
case value_t::string : {return visitor(v.as_string ());}
|
|
||||||
case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
|
|
||||||
case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
|
|
||||||
case value_t::local_date : {return visitor(v.as_local_date ());}
|
|
||||||
case value_t::local_time : {return visitor(v.as_local_time ());}
|
|
||||||
case value_t::array : {return visitor(v.as_array ());}
|
|
||||||
case value_t::table : {return visitor(v.as_table ());}
|
|
||||||
case value_t::empty : break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
|
|
||||||
"does not have any valid basic_value.", v, "here"));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Visitor, typename C,
|
|
||||||
template<typename ...> class T, template<typename ...> class A>
|
|
||||||
detail::return_type_of_t<Visitor, toml::boolean&&>
|
|
||||||
visit(Visitor&& visitor, toml::basic_value<C, T, A>&& v)
|
|
||||||
{
|
|
||||||
switch(v.type())
|
|
||||||
{
|
|
||||||
case value_t::boolean : {return visitor(std::move(v.as_boolean ()));}
|
|
||||||
case value_t::integer : {return visitor(std::move(v.as_integer ()));}
|
|
||||||
case value_t::floating : {return visitor(std::move(v.as_floating ()));}
|
|
||||||
case value_t::string : {return visitor(std::move(v.as_string ()));}
|
|
||||||
case value_t::offset_datetime: {return visitor(std::move(v.as_offset_datetime()));}
|
|
||||||
case value_t::local_datetime : {return visitor(std::move(v.as_local_datetime ()));}
|
|
||||||
case value_t::local_date : {return visitor(std::move(v.as_local_date ()));}
|
|
||||||
case value_t::local_time : {return visitor(std::move(v.as_local_time ()));}
|
|
||||||
case value_t::array : {return visitor(std::move(v.as_array ()));}
|
|
||||||
case value_t::table : {return visitor(std::move(v.as_table ()));}
|
|
||||||
case value_t::empty : break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
|
|
||||||
"does not have any valid basic_value.", v, "here"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}// toml
|
}// toml
|
||||||
#endif// TOML11_VALUE
|
#endif// TOML11_VALUE
|
||||||
|
|||||||
134
toml/visit.hpp
Normal file
134
toml/visit.hpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
// Copyright Toru Niina 2019.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_VISIT_HPP
|
||||||
|
#define TOML11_VISIT_HPP
|
||||||
|
#include "value.hpp"
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
template<typename Visitor, typename C,
|
||||||
|
template<typename ...> class T, template<typename ...> class A>
|
||||||
|
detail::return_type_of_t<Visitor, const toml::boolean&>
|
||||||
|
visit(Visitor&& visitor, const toml::basic_value<C, T, A>& v)
|
||||||
|
{
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case value_t::boolean : {return visitor(v.as_boolean ());}
|
||||||
|
case value_t::integer : {return visitor(v.as_integer ());}
|
||||||
|
case value_t::floating : {return visitor(v.as_floating ());}
|
||||||
|
case value_t::string : {return visitor(v.as_string ());}
|
||||||
|
case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
|
||||||
|
case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
|
||||||
|
case value_t::local_date : {return visitor(v.as_local_date ());}
|
||||||
|
case value_t::local_time : {return visitor(v.as_local_time ());}
|
||||||
|
case value_t::array : {return visitor(v.as_array ());}
|
||||||
|
case value_t::table : {return visitor(v.as_table ());}
|
||||||
|
case value_t::empty : break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
|
||||||
|
"does not have any valid basic_value.", v, "here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Visitor, typename C,
|
||||||
|
template<typename ...> class T, template<typename ...> class A>
|
||||||
|
detail::return_type_of_t<Visitor, toml::boolean&>
|
||||||
|
visit(Visitor&& visitor, toml::basic_value<C, T, A>& v)
|
||||||
|
{
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case value_t::boolean : {return visitor(v.as_boolean ());}
|
||||||
|
case value_t::integer : {return visitor(v.as_integer ());}
|
||||||
|
case value_t::floating : {return visitor(v.as_floating ());}
|
||||||
|
case value_t::string : {return visitor(v.as_string ());}
|
||||||
|
case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
|
||||||
|
case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
|
||||||
|
case value_t::local_date : {return visitor(v.as_local_date ());}
|
||||||
|
case value_t::local_time : {return visitor(v.as_local_time ());}
|
||||||
|
case value_t::array : {return visitor(v.as_array ());}
|
||||||
|
case value_t::table : {return visitor(v.as_table ());}
|
||||||
|
case value_t::empty : break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
|
||||||
|
"does not have any valid basic_value.", v, "here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Visitor, typename C,
|
||||||
|
template<typename ...> class T, template<typename ...> class A>
|
||||||
|
detail::return_type_of_t<Visitor, toml::boolean&&>
|
||||||
|
visit(Visitor&& visitor, toml::basic_value<C, T, A>&& v)
|
||||||
|
{
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case value_t::boolean : {return visitor(std::move(v.as_boolean ()));}
|
||||||
|
case value_t::integer : {return visitor(std::move(v.as_integer ()));}
|
||||||
|
case value_t::floating : {return visitor(std::move(v.as_floating ()));}
|
||||||
|
case value_t::string : {return visitor(std::move(v.as_string ()));}
|
||||||
|
case value_t::offset_datetime: {return visitor(std::move(v.as_offset_datetime()));}
|
||||||
|
case value_t::local_datetime : {return visitor(std::move(v.as_local_datetime ()));}
|
||||||
|
case value_t::local_date : {return visitor(std::move(v.as_local_date ()));}
|
||||||
|
case value_t::local_time : {return visitor(std::move(v.as_local_time ()));}
|
||||||
|
case value_t::array : {return visitor(std::move(v.as_array ()));}
|
||||||
|
case value_t::table : {return visitor(std::move(v.as_table ()));}
|
||||||
|
case value_t::empty : break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
|
||||||
|
"does not have any valid basic_value.", v, "here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename Result, typename Visitor, typename Value>
|
||||||
|
struct visitor
|
||||||
|
{
|
||||||
|
template<typename ... Ts>
|
||||||
|
Result operator()(Ts&& ... args)
|
||||||
|
{
|
||||||
|
return vis(value, args ...);
|
||||||
|
}
|
||||||
|
Visitor vis;
|
||||||
|
Value value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Result, typename Visitor, typename Value>
|
||||||
|
visitor<Result, Visitor, Value> make_visitor(Visitor&& vis, Value&& val)
|
||||||
|
{
|
||||||
|
return visitor<Result, Visitor, Value>{
|
||||||
|
std::forward<Visitor>(vis), std::forward<Value>(val)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
template<typename Visitor, typename Value, typename ... Values>
|
||||||
|
auto visit(Visitor&& visitor, Value&& v, Values&& ... vs)
|
||||||
|
-> detail::enable_if_t<detail::conjunction<
|
||||||
|
detail::is_basic_value<Value>, detail::is_basic_value<Values> ...
|
||||||
|
>::value, decltype(visitor(std::forward<Value >(v ).as_boolean(),
|
||||||
|
std::forward<Values>(vs).as_boolean()...))>
|
||||||
|
{
|
||||||
|
using result_t = decltype(visitor(v.as_boolean(), vs.as_boolean()...));
|
||||||
|
using detail::make_visitor;
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case value_t::boolean : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_boolean ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::integer : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_integer ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::floating : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_floating ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::string : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_string ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::offset_datetime: {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_offset_datetime()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::local_datetime : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_local_datetime ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::local_date : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_local_date ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::local_time : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_local_time ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::array : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_array ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::table : {return visit(make_visitor<result_t>(std::forward<Visitor>(visitor), v.as_table ()), std::forward<Values>(vs)...);}
|
||||||
|
case value_t::empty : break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
|
||||||
|
"does not have any valid basic_value.", v, "here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // toml
|
||||||
|
#endif// TOML11_VISIT_HPP
|
||||||
Reference in New Issue
Block a user