mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
78 Commits
v3.0.0-bet
...
v3.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e12fd4d944 | ||
|
|
36af02cb3a | ||
|
|
488015df49 | ||
|
|
1f951e49b1 | ||
|
|
6a7dbb7875 | ||
|
|
ad7eb56634 | ||
|
|
b01c5534ed | ||
|
|
22dac3c9f2 | ||
|
|
d5adfe8c7d | ||
|
|
4bb8045c84 | ||
|
|
babb6ab3fe | ||
|
|
d73bc6076c | ||
|
|
8d1da6e8b5 | ||
|
|
8276e12f06 | ||
|
|
f3d3f63ff9 | ||
|
|
d9689c878d | ||
|
|
df097cb09a | ||
|
|
a425e3b7c6 | ||
|
|
e4b4503b81 | ||
|
|
b44fbad925 | ||
|
|
826c9444ac | ||
|
|
a1095f3e4c | ||
|
|
483a39beb4 | ||
|
|
1409114c96 | ||
|
|
ecfc9d0c5a | ||
|
|
94f76137a3 | ||
|
|
c2e1aa9a3c | ||
|
|
5b5ece6c32 | ||
|
|
b696e327d7 | ||
|
|
757e5d60be | ||
|
|
c02093de7f | ||
|
|
4f8b62a7e9 | ||
|
|
d9b8582c47 | ||
|
|
c9543d8d9e | ||
|
|
15b68a89c6 | ||
|
|
64e7bdb835 | ||
|
|
1acf87679e | ||
|
|
7a1b5bd64e | ||
|
|
e332e018db | ||
|
|
b1ec6d87bd | ||
|
|
8dded288b4 | ||
|
|
0f491c7f3a | ||
|
|
5edf43a1d2 | ||
|
|
cffc605505 | ||
|
|
fb91936a1d | ||
|
|
8833292858 | ||
|
|
3fe04aff77 | ||
|
|
138f030b5d | ||
|
|
2eb2e0a753 | ||
|
|
87e0ba201e | ||
|
|
24a05c7c93 | ||
|
|
c3653b85f1 | ||
|
|
00b05c63b9 | ||
|
|
35b7c79ebd | ||
|
|
9ef146d022 | ||
|
|
2c192af35d | ||
|
|
c2435b0d56 | ||
|
|
9b12b17d5e | ||
|
|
e61b38fac2 | ||
|
|
716f7bacba | ||
|
|
299d1098e4 | ||
|
|
c272188060 | ||
|
|
0fc0967f6f | ||
|
|
df0d870c97 | ||
|
|
d5299fef04 | ||
|
|
937a3b4a2e | ||
|
|
0502924d25 | ||
|
|
6182f3ee9d | ||
|
|
3624e4b690 | ||
|
|
37e96ed8dc | ||
|
|
79e7511871 | ||
|
|
284f122433 | ||
|
|
134475e292 | ||
|
|
28b3f7d6fb | ||
|
|
6b5fd349aa | ||
|
|
76e44a0c48 | ||
|
|
b4bbd0a005 | ||
|
|
f9ee645dc2 |
@@ -15,6 +15,29 @@ jobs:
|
|||||||
g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check_toml_test.cpp -o check_toml_test
|
g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check_toml_test.cpp -o check_toml_test
|
||||||
go get github.com/BurntSushi/toml-test
|
go get github.com/BurntSushi/toml-test
|
||||||
$GOPATH/bin/toml-test ./check_toml_test
|
$GOPATH/bin/toml-test ./check_toml_test
|
||||||
|
test_serialization:
|
||||||
|
docker:
|
||||||
|
- image: circleci/buildpack-deps:bionic
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
g++ --version
|
||||||
|
cd tests/
|
||||||
|
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check_serialization.cpp -o check_serialization
|
||||||
|
git clone https://github.com/BurntSushi/toml-test.git
|
||||||
|
cp check_serialization toml-test/tests/valid
|
||||||
|
cd toml-test/tests/valid
|
||||||
|
for f in $(ls ./*.toml);
|
||||||
|
do echo "==> ${f}";
|
||||||
|
cat ${f};
|
||||||
|
echo "---------------------------------------";
|
||||||
|
./check_serialization ${f};
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "=======================================";
|
||||||
|
done
|
||||||
output_result:
|
output_result:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/buildpack-deps:bionic
|
- image: circleci/buildpack-deps:bionic
|
||||||
@@ -24,7 +47,7 @@ jobs:
|
|||||||
command: |
|
command: |
|
||||||
g++ --version
|
g++ --version
|
||||||
cd tests/
|
cd tests/
|
||||||
g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check.cpp -o check
|
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check.cpp -o check
|
||||||
git clone https://github.com/BurntSushi/toml-test.git
|
git clone https://github.com/BurntSushi/toml-test.git
|
||||||
cp check toml-test/tests/invalid
|
cp check toml-test/tests/invalid
|
||||||
cp check toml-test/tests/valid
|
cp check toml-test/tests/valid
|
||||||
@@ -56,4 +79,5 @@ workflows:
|
|||||||
test:
|
test:
|
||||||
jobs:
|
jobs:
|
||||||
- test_suite
|
- test_suite
|
||||||
|
- test_serialization
|
||||||
- output_result
|
- output_result
|
||||||
|
|||||||
78
.travis.yml
78
.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
|
env: COMPILER="g++-5" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
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
|
env: COMPILER="g++-6" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
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
|
env: COMPILER="g++-7" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
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
|
env: COMPILER="g++-8" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -53,7 +53,31 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-8" CXX_STANDARD=17
|
env: COMPILER="g++-8" CXX_STANDARD=11 TOML_HEAD=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=OFF
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=ON
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -65,7 +89,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-3.7" CXX_STANDARD=11
|
env: COMPILER="clang++-3.7" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -79,7 +103,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-4.0" CXX_STANDARD=11
|
env: COMPILER="clang++-4.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -93,7 +117,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-5.0" CXX_STANDARD=11
|
env: COMPILER="clang++-5.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -107,7 +131,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-6.0" CXX_STANDARD=11
|
env: COMPILER="clang++-6.0" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -121,7 +145,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-7" CXX_STANDARD=11
|
env: COMPILER="clang++-7" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -135,7 +159,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-8" CXX_STANDARD=11
|
env: COMPILER="clang++-8" CXX_STANDARD=11 TOML_HEAD=OFF
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -149,7 +173,35 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-8" CXX_STANDARD=17
|
env: COMPILER="clang++-8" CXX_STANDARD=11 TOML_HEAD=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- clang-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=OFF
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=ON
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -179,6 +231,6 @@ script:
|
|||||||
- 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 ..
|
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD -DTOML11_USE_UNRELEASED_TOML_FEATURES=${TOML_HEAD} ..
|
||||||
- make
|
- make
|
||||||
- ctest --output-on-failure
|
- ctest --output-on-failure
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ enable_testing()
|
|||||||
|
|
||||||
project(toml11)
|
project(toml11)
|
||||||
|
|
||||||
set(toml11_VERSION_MAYOR 2)
|
set(toml11_VERSION_MAYOR 3)
|
||||||
set(toml11_VERSION_MINOR 4)
|
set(toml11_VERSION_MINOR 0)
|
||||||
set(toml11_VERSION_PATCH 0)
|
set(toml11_VERSION_PATCH 1)
|
||||||
set(toml11_VERSION
|
set(toml11_VERSION
|
||||||
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
|
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
|
||||||
)
|
)
|
||||||
|
|||||||
178
README.md
178
README.md
@@ -22,7 +22,7 @@ You can see the error messages about invalid files and serialization results of
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include <toml11/toml.hpp>
|
#include <toml.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -47,8 +47,9 @@ int main()
|
|||||||
- [Decoding a toml file](#decoding-a-toml-file)
|
- [Decoding a toml file](#decoding-a-toml-file)
|
||||||
- [In the case of syntax error](#in-the-case-of-syntax-error)
|
- [In the case of syntax error](#in-the-case-of-syntax-error)
|
||||||
- [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints)
|
- [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints)
|
||||||
- [Finding a toml value](#finding-a-toml-value-from-a-table)
|
- [Finding a toml value](#finding-a-toml-value)
|
||||||
- [In the case of type error](#in-the-case-of-type-error)
|
- [Finding a value in a table](#finding-a-value-in-a-table)
|
||||||
|
- [In case of error](#in-case-of-error)
|
||||||
- [Dotted keys](#dotted-keys)
|
- [Dotted keys](#dotted-keys)
|
||||||
- [Casting a toml value](#casting-a-toml-value)
|
- [Casting a toml value](#casting-a-toml-value)
|
||||||
- [Checking value type](#checking-value-type)
|
- [Checking value type](#checking-value-type)
|
||||||
@@ -69,6 +70,7 @@ int main()
|
|||||||
- [Formatting user-defined error messages](#formatting-user-defined-error-messages)
|
- [Formatting user-defined error messages](#formatting-user-defined-error-messages)
|
||||||
- [Serializing TOML data](#serializing-toml-data)
|
- [Serializing TOML data](#serializing-toml-data)
|
||||||
- [Underlying types](#underlying-types)
|
- [Underlying types](#underlying-types)
|
||||||
|
- [Unreleased TOML features](#unreleased-toml-features)
|
||||||
- [Breaking Changes from v2](#breaking-changes-from-v2)
|
- [Breaking Changes from v2](#breaking-changes-from-v2)
|
||||||
- [Running Tests](#running-tests)
|
- [Running Tests](#running-tests)
|
||||||
- [Contributors](#contributors)
|
- [Contributors](#contributors)
|
||||||
@@ -101,19 +103,19 @@ to pass a filename to the `toml::parse` function.
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const std::string fname("sample.toml");
|
const std::string fname("sample.toml");
|
||||||
const toml::table data = toml::parse(fname);
|
const toml::value data = toml::parse(fname);
|
||||||
```
|
```
|
||||||
|
|
||||||
If it encounters an error while opening a file, it will throw `std::runtime_error`.
|
If it encounters an error while opening a file, it will throw `std::runtime_error`.
|
||||||
|
|
||||||
You can also pass a `std::istream` to the `toml::parse` function.
|
You can also pass a `std::istream` to the `toml::parse` function.
|
||||||
To show a filename in an error message, it is recommended to pass the filename
|
To show a filename in an error message, however, it is recommended to pass the
|
||||||
with the stream.
|
filename with the stream.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
std::ifstream ifs("sample.toml", std::ios_base::binary);
|
std::ifstream ifs("sample.toml", std::ios_base::binary);
|
||||||
assert(ifs.good());
|
assert(ifs.good());
|
||||||
const auto data = toml::parse(ifs, /*optional*/ "sample.toml");
|
const auto data = toml::parse(ifs, /*optional -> */ "sample.toml");
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: When you are **on Windows, open a file in binary mode**.
|
**Note**: When you are **on Windows, open a file in binary mode**.
|
||||||
@@ -185,7 +187,7 @@ representing unicode character is not a valid UTF-8 codepoint.
|
|||||||
| ^--------- should be in [0x00..0x10FFFF]
|
| ^--------- should be in [0x00..0x10FFFF]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Finding a toml value from a table
|
## Finding a toml value
|
||||||
|
|
||||||
After parsing successfully, you can obtain the values from the result of
|
After parsing successfully, you can obtain the values from the result of
|
||||||
`toml::parse` using `toml::find` function.
|
`toml::parse` using `toml::find` function.
|
||||||
@@ -196,8 +198,6 @@ answer = 42
|
|||||||
pi = 3.14
|
pi = 3.14
|
||||||
numbers = [1,2,3]
|
numbers = [1,2,3]
|
||||||
time = 1979-05-27T07:32:00Z
|
time = 1979-05-27T07:32:00Z
|
||||||
[tab]
|
|
||||||
key = "value"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
``` cpp
|
``` cpp
|
||||||
@@ -206,23 +206,16 @@ const auto answer = toml::find<std::int64_t >(data, "answer");
|
|||||||
const auto pi = toml::find<double >(data, "pi");
|
const auto pi = toml::find<double >(data, "pi");
|
||||||
const auto numbers = toml::find<std::vector<int>>(data, "numbers");
|
const auto numbers = toml::find<std::vector<int>>(data, "numbers");
|
||||||
const auto timepoint = toml::find<std::chrono::system_clock::time_point>(data, "time");
|
const auto timepoint = toml::find<std::chrono::system_clock::time_point>(data, "time");
|
||||||
const auto tab = toml::find<toml::table>(data, "tab");
|
|
||||||
const auto key = toml::find<std::string>(tab, "key");
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If the value does not exist, `toml::find` throws an error with the location of
|
By default, `toml::find` returns a `toml::value`.
|
||||||
the table.
|
|
||||||
|
|
||||||
```console
|
```cpp
|
||||||
terminate called after throwing an instance of 'std::out_of_range'
|
const toml::value& answer = toml::find(data, "answer");
|
||||||
what(): [error] key "answer" not found
|
|
||||||
--> example.toml
|
|
||||||
6 | [tab]
|
|
||||||
| ~~~~~ in this table
|
|
||||||
```
|
```
|
||||||
|
|
||||||
When you pass an exact TOML type that does not require type conversion,
|
When you pass an exact TOML type that does not require type conversion,
|
||||||
`toml::get` returns a reference without copying the value.
|
`toml::find` returns a reference without copying the value.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto data = toml::parse("sample.toml");
|
const auto data = toml::parse("sample.toml");
|
||||||
@@ -232,12 +225,6 @@ const auto& answer = toml::find<toml::integer>(data, "answer");
|
|||||||
If the specified type requires conversion, you can't take a reference to the value.
|
If the specified type requires conversion, you can't take a reference to the value.
|
||||||
See also [underlying types](#underlying-types).
|
See also [underlying types](#underlying-types).
|
||||||
|
|
||||||
By default, `toml::find` returns a `toml::value`.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
const toml::value& answer = toml::find(data, "answer");
|
|
||||||
```
|
|
||||||
|
|
||||||
**NOTE**: For some technical reason, automatic conversion between `integer` and
|
**NOTE**: For some technical reason, automatic conversion between `integer` and
|
||||||
`floating` is not supported. If you want to get a floating value even if a value
|
`floating` is not supported. If you want to get a floating value even if a value
|
||||||
has integer value, you need to convert it manually after obtaining a value,
|
has integer value, you need to convert it manually after obtaining a value,
|
||||||
@@ -250,24 +237,59 @@ double x = vx.is_floating() ? vx.as_floating(std::nothrow) :
|
|||||||
// floating nor integer.
|
// floating nor integer.
|
||||||
```
|
```
|
||||||
|
|
||||||
----
|
### Finding a value in a table
|
||||||
|
|
||||||
`toml::find` accepts arbitrary number of keys to find a value buried in a
|
There are several way to get a value defined in a table.
|
||||||
deep recursion of tables.
|
First, you can get a table as a normal value and find a value from the table.
|
||||||
|
|
||||||
```cpp
|
```toml
|
||||||
// # expecting the following example.toml
|
[fruit]
|
||||||
// answer.to.the.ultimate.question = 42
|
name = "apple"
|
||||||
// # is equivalent to {"answer": {"to":{"the":{"ultimate:{"question":42}}}}}
|
[fruit.physical]
|
||||||
|
color = "red"
|
||||||
const toml::table data = toml::parse("example.toml");
|
shape = "round"
|
||||||
const int a = toml::find<int>(data, "answer", "to", "the", "ultimate", "question");
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Of course, alternatively, you can call `toml::find` as many as you need.
|
``` cpp
|
||||||
But it is a bother.
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
const auto& fruit = toml::find(data, "fruit");
|
||||||
|
const auto name = toml::find<std::string>(fruit, "apple");
|
||||||
|
|
||||||
### In the case of type error
|
const auto& physical = toml::find(fruit, "physical");
|
||||||
|
const auto color = toml::find<std::string>(fruit, "color");
|
||||||
|
const auto shape = toml::find<std::string>(fruit, "shape");
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, variable `fruit` is a `toml::value` and can be used as the first argument
|
||||||
|
of `toml::find`.
|
||||||
|
|
||||||
|
Second, you can pass as many arguments as the number of subtables to `toml::find`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
const auto color = toml::find<std::string>(data, "fruit", "physical", "color");
|
||||||
|
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
||||||
|
```
|
||||||
|
|
||||||
|
### In case of error
|
||||||
|
|
||||||
|
If the value does not exist, `toml::find` throws an error with the location of
|
||||||
|
the table.
|
||||||
|
|
||||||
|
```console
|
||||||
|
terminate called after throwing an instance of 'std::out_of_range'
|
||||||
|
what(): [error] key "answer" not found
|
||||||
|
--> example.toml
|
||||||
|
6 | [tab]
|
||||||
|
| ~~~~~ in this table
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: It is recommended to find a table as `toml::value` because it has much information
|
||||||
|
compared to `toml::table`, which is an alias of
|
||||||
|
`std::unordered_map<std::string, toml::value>`. Since `toml::table` does not have
|
||||||
|
any information about toml file, such as where the table was defined in the file.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
If the specified type differs from the actual value contained, it throws
|
If the specified type differs from the actual value contained, it throws
|
||||||
`toml::type_error` that inherits `std::exception`.
|
`toml::type_error` that inherits `std::exception`.
|
||||||
@@ -310,13 +332,14 @@ shape = "round"
|
|||||||
You can get both of the above tables with the same c++ code.
|
You can get both of the above tables with the same c++ code.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto physical = toml::find<toml::table>(data, "physical");
|
const auto physical = toml::find(data, "physical");
|
||||||
const auto color = toml::find<std::string>(physical, "color");
|
const auto color = toml::find<std::string>(physical, "color");
|
||||||
```
|
```
|
||||||
|
|
||||||
The following code does not work for the above toml file.
|
The following code does not work for the above toml file.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
// XXX this does not work!
|
||||||
const auto color = toml::find<std::string>(data, "physical.color");
|
const auto color = toml::find<std::string>(data, "physical.color");
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -349,18 +372,22 @@ contain one of the following types.
|
|||||||
- It depends. See [customizing containers](#customizing-containers) for detail.
|
- It depends. See [customizing containers](#customizing-containers) for detail.
|
||||||
|
|
||||||
To get a value inside, you can use `toml::get<T>()`. The usage is the same as
|
To get a value inside, you can use `toml::get<T>()`. The usage is the same as
|
||||||
`toml::find<T>` (actually, `toml::find` internally uses `toml::get`).
|
`toml::find<T>` (actually, `toml::find` internally uses `toml::get` after casting
|
||||||
|
a value to `toml::table`).
|
||||||
|
|
||||||
``` cpp
|
``` cpp
|
||||||
const toml::value data = toml::parse("sample.toml");
|
const toml::value data = toml::parse("sample.toml");
|
||||||
const toml::value answer_ = toml::get<toml::table >(data).at("answer")
|
const toml::value answer_ = toml::get<toml::table >(data).at("answer");
|
||||||
const std::int64_t answer = toml::get<std::int64_t>(answer_);
|
const std::int64_t answer = toml::get<std::int64_t>(answer_);
|
||||||
```
|
```
|
||||||
|
|
||||||
When you pass an exact TOML type that does not require type conversion,
|
When you pass an exact TOML type that does not require type conversion,
|
||||||
`toml::get` returns a reference through which you can modify the content.
|
`toml::get` returns a reference through which you can modify the content
|
||||||
|
(if the `toml::value` is `const`, it returns `const` reference).
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
toml::value data = toml::parse("sample.toml");
|
||||||
|
toml::value answer_ = toml::get<toml::table >(data).at("answer");
|
||||||
toml::integer& answer = toml::get<toml::integer>(answer_);
|
toml::integer& answer = toml::get<toml::integer>(answer_);
|
||||||
answer = 6 * 9; // write to data.answer. now `answer_` contains 54.
|
answer = 6 * 9; // write to data.answer. now `answer_` contains 54.
|
||||||
```
|
```
|
||||||
@@ -427,7 +454,21 @@ class value {
|
|||||||
} // toml
|
} // toml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `at()`
|
||||||
|
|
||||||
|
You can access to the element of a table and an array by `toml::basic_value::at`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const toml::value v{1,2,3,4,5};
|
||||||
|
std::cout << v.at(2).as_integer() << std::endl; // 3
|
||||||
|
|
||||||
|
const toml::value v{{"foo", 42}, {"bar", 3.14}};
|
||||||
|
std::cout << v.at("foo").as_integer() << std::endl; // 42
|
||||||
|
```
|
||||||
|
|
||||||
|
If an invalid key (integer for a table, string for an array), it throws
|
||||||
|
`toml::type_error` for the conversion. If the provided key is out-of-range,
|
||||||
|
it throws `std::out_of_range`.
|
||||||
|
|
||||||
## Checking value type
|
## Checking value type
|
||||||
|
|
||||||
@@ -909,10 +950,17 @@ const auto data = toml::parse<
|
|||||||
>("example.toml");
|
>("example.toml");
|
||||||
```
|
```
|
||||||
|
|
||||||
__NOTE__: Needless to say, the result types from `toml::parse(...)` and
|
Needless to say, the result types from `toml::parse(...)` and
|
||||||
`toml::parse<Com, Map, Cont>(...)` are different (unless you specify the same
|
`toml::parse<Com, Map, Cont>(...)` are different (unless you specify the same
|
||||||
types as default).
|
types as default).
|
||||||
|
|
||||||
|
Note that, since `toml::table` and `toml::array` is an alias for a table and an
|
||||||
|
array of a default `toml::value`, so it is different from the types actually
|
||||||
|
contained in a `toml::basic_value` when you customize containers.
|
||||||
|
To get the actual type in a generic way, use
|
||||||
|
`typename toml::basic_type<C, T, A>::table_type` and
|
||||||
|
`typename toml::basic_type<C, T, A>::array_type`.
|
||||||
|
|
||||||
## TOML literal
|
## TOML literal
|
||||||
|
|
||||||
toml11 supports `"..."_toml` literal.
|
toml11 supports `"..."_toml` literal.
|
||||||
@@ -945,7 +993,6 @@ inline namespace literals
|
|||||||
inline namespace toml_literals
|
inline namespace toml_literals
|
||||||
{
|
{
|
||||||
toml::value operator"" _toml(const char* str, std::size_t len);
|
toml::value operator"" _toml(const char* str, std::size_t len);
|
||||||
|
|
||||||
} // toml_literals
|
} // toml_literals
|
||||||
} // literals
|
} // literals
|
||||||
} // toml
|
} // toml
|
||||||
@@ -1044,7 +1091,7 @@ namespace toml
|
|||||||
template<>
|
template<>
|
||||||
struct from<ext::foo>
|
struct from<ext::foo>
|
||||||
{
|
{
|
||||||
ext::foo from_toml(const value& v)
|
static ext::foo from_toml(const value& v)
|
||||||
{
|
{
|
||||||
ext::foo f;
|
ext::foo f;
|
||||||
f.a = find<int >(v, "a");
|
f.a = find<int >(v, "a");
|
||||||
@@ -1084,7 +1131,7 @@ template<>
|
|||||||
struct from<ext::foo>
|
struct from<ext::foo>
|
||||||
{
|
{
|
||||||
template<typename C, template<typename ...> class M, template<typename ...> class A>
|
template<typename C, template<typename ...> class M, template<typename ...> class A>
|
||||||
ext::foo from_toml(const basic_value<C, M, A>& v)
|
static ext::foo from_toml(const basic_value<C, M, A>& v)
|
||||||
{
|
{
|
||||||
ext::foo f;
|
ext::foo f;
|
||||||
f.a = find<int >(v, "a");
|
f.a = find<int >(v, "a");
|
||||||
@@ -1140,7 +1187,7 @@ namespace toml
|
|||||||
template<>
|
template<>
|
||||||
struct into<ext::foo>
|
struct into<ext::foo>
|
||||||
{
|
{
|
||||||
toml::table into_toml(const ext::foo& f)
|
static toml::table into_toml(const ext::foo& f)
|
||||||
{
|
{
|
||||||
return toml::table{{"a", f.a}, {"b", f.b}, {"c", f.c}};
|
return toml::table{{"a", f.a}, {"b", f.b}, {"c", f.c}};
|
||||||
}
|
}
|
||||||
@@ -1237,7 +1284,7 @@ const toml::source_location loc = v.location();
|
|||||||
toml11 enables you to serialize data into toml format.
|
toml11 enables you to serialize data into toml format.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto data = toml::table{{"foo", 42}, {"bar", "baz"}};
|
const toml::value data{{"foo", 42}, {"bar", "baz"}};
|
||||||
std::cout << data << std::endl;
|
std::cout << data << std::endl;
|
||||||
// bar = "baz"
|
// bar = "baz"
|
||||||
// foo = 42
|
// foo = 42
|
||||||
@@ -1247,10 +1294,10 @@ toml11 automatically makes a small table and small array inline.
|
|||||||
You can specify the width to make them inline by `std::setw` for streams.
|
You can specify the width to make them inline by `std::setw` for streams.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto data = toml::table{
|
const toml::value data{
|
||||||
{"qux", toml::table{{"foo", 42}, {"bar", "baz"}}},
|
{"qux", {{"foo", 42}, {"bar", "baz"}}},
|
||||||
{"quux", toml::array{"small", "array", "of", "strings"}},
|
{"quux", {"small", "array", "of", "strings"}},
|
||||||
{"foobar", toml::array{"this", "array", "of", "strings", "is", "too", "long",
|
{"foobar", {"this", "array", "of", "strings", "is", "too", "long",
|
||||||
"to", "print", "into", "single", "line", "isn't", "it?"}},
|
"to", "print", "into", "single", "line", "isn't", "it?"}},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1290,7 +1337,7 @@ To control the precision of floating point numbers, you need to pass
|
|||||||
`std::setprecision` to stream.
|
`std::setprecision` to stream.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto data = toml::table{
|
const toml::value data{
|
||||||
{"pi", 3.141592653589793},
|
{"pi", 3.141592653589793},
|
||||||
{"e", 2.718281828459045}
|
{"e", 2.718281828459045}
|
||||||
};
|
};
|
||||||
@@ -1356,6 +1403,9 @@ are used. See [Customizing containers](#customizing-containers) for detail.
|
|||||||
flag that represents a kind of a string, `string_t::basic` and `string_t::literal`.
|
flag that represents a kind of a string, `string_t::basic` and `string_t::literal`.
|
||||||
Although `std::string` is not an exact toml type, still you can get a reference
|
Although `std::string` is not an exact toml type, still you can get a reference
|
||||||
that points to internal `std::string` by using `toml::get<std::string>()` for convenience.
|
that points to internal `std::string` by using `toml::get<std::string>()` for convenience.
|
||||||
|
The most important difference between `std::string` and `toml::string` is that
|
||||||
|
`toml::string` will be formatted as a TOML string when outputed with `ostream`.
|
||||||
|
This feature is introduced to make it easy to write a custom serializer.
|
||||||
|
|
||||||
`Datetime` variants are `struct` that are defined in this library.
|
`Datetime` variants are `struct` that are defined in this library.
|
||||||
Because `std::chrono::system_clock::time_point` is a __time point__,
|
Because `std::chrono::system_clock::time_point` is a __time point__,
|
||||||
@@ -1363,6 +1413,16 @@ not capable of representing a Local Time independent from a specific day.
|
|||||||
|
|
||||||
It is recommended to get `datetime`s as `std::chrono` classes through `toml::get`.
|
It is recommended to get `datetime`s as `std::chrono` classes through `toml::get`.
|
||||||
|
|
||||||
|
## Unreleased TOML features
|
||||||
|
|
||||||
|
There are some unreleased features in toml-lang/toml:master.
|
||||||
|
Currently, the following features are available after defining
|
||||||
|
`TOML11_USE_UNRELEASED_TOML_FEATURES` macro flag.
|
||||||
|
|
||||||
|
- Leading zeroes in exponent parts of floats are permitted.
|
||||||
|
- e.g. `1.0e+01`, `5e+05`
|
||||||
|
- Allow raw tab characters in basic strings and multi-line basic strings.
|
||||||
|
|
||||||
## Breaking Changes from v2
|
## Breaking Changes from v2
|
||||||
|
|
||||||
Although toml11 is relatively new library (it's three years old now), it had
|
Although toml11 is relatively new library (it's three years old now), it had
|
||||||
@@ -1384,8 +1444,12 @@ Between v2 and v3, those interfaces are rearranged.
|
|||||||
- See [Casting a toml::value](#casting-a-tomlvalue) and [Checking value type](#checking-value-type) for detail.
|
- See [Casting a toml::value](#casting-a-tomlvalue) and [Checking value type](#checking-value-type) for detail.
|
||||||
- An overload of `toml::find` for `toml::table` has been dropped. Use `toml::value` version instead.
|
- An overload of `toml::find` for `toml::table` has been dropped. Use `toml::value` version instead.
|
||||||
- Because type conversion between a table and a value causes ambiguity while overload resolution
|
- Because type conversion between a table and a value causes ambiguity while overload resolution
|
||||||
|
- Since `toml::parse` now returns a `toml::value`, this feature becomes less important.
|
||||||
- Also because `toml::table` is a normal STL container, implementing utility function is easy.
|
- Also because `toml::table` is a normal STL container, implementing utility function is easy.
|
||||||
- See [Finding a toml::value](#finding-a-tomlvalue) for detail.
|
- See [Finding a toml::value](#finding-a-toml-value) for detail.
|
||||||
|
- An overload of `operator<<` and `toml::format` for `toml::table`s are dropped.
|
||||||
|
- Use `toml::value` instead.
|
||||||
|
- See [Serializing TOML data](#serializing-toml-data) for detail.
|
||||||
- Interface around comments.
|
- Interface around comments.
|
||||||
- See [Preserving Comments](#preserving-comments) for detail.
|
- See [Preserving Comments](#preserving-comments) for detail.
|
||||||
- An ancient `from_toml/into_toml` has been removed. Use arbitrary type conversion support.
|
- An ancient `from_toml/into_toml` has been removed. Use arbitrary type conversion support.
|
||||||
@@ -1428,6 +1492,8 @@ I appreciate the help of the contributors who introduced the great feature to th
|
|||||||
- Fixed warnings while type conversion
|
- Fixed warnings while type conversion
|
||||||
- @KerstinKeller
|
- @KerstinKeller
|
||||||
- Added installation script to CMake
|
- Added installation script to CMake
|
||||||
|
- J.C. Moyer (@jcmoyer)
|
||||||
|
- Fixed an example code in the documentation
|
||||||
|
|
||||||
## Licensing terms
|
## Licensing terms
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
set(TEST_NAMES
|
set(TEST_NAMES
|
||||||
test_datetime
|
test_datetime
|
||||||
|
test_string
|
||||||
test_utility
|
test_utility
|
||||||
test_result
|
test_result
|
||||||
test_traits
|
test_traits
|
||||||
@@ -49,6 +50,14 @@ if(COMPILER_SUPPORTS_WPEDANTIC)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
"use features in toml-lang/toml master while testing" OFF)
|
||||||
|
|
||||||
|
if(TOML11_USE_UNRELEASED_TOML_FEATURES)
|
||||||
|
message(STATUS "adding TOML11_USE_UNRELEASED_TOML_FEATURES flag")
|
||||||
|
add_definitions("-DTOML11_USE_UNRELEASED_TOML_FEATURES")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Disable some MSVC warnings
|
# Disable some MSVC warnings
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# conversion from 'double' to 'unsigned int', possible loss of data
|
# conversion from 'double' to 'unsigned int', possible loss of data
|
||||||
|
|||||||
57
tests/check_serialization.cpp
Normal file
57
tests/check_serialization.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include "toml.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if(argc != 2)
|
||||||
|
{
|
||||||
|
std::cerr << "usage: ./check [filename]" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string filename(argv[1]);
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto data = toml::parse(filename);
|
||||||
|
{
|
||||||
|
std::ofstream ofs("tmp.toml");
|
||||||
|
ofs << std::setprecision(16) << std::setw(80) << data;
|
||||||
|
}
|
||||||
|
const auto serialized = toml::parse("tmp.toml");
|
||||||
|
|
||||||
|
if(data != serialized)
|
||||||
|
{
|
||||||
|
std::cerr << "============================================================\n";
|
||||||
|
std::cerr << "result (w/o comment) different: " << filename << std::endl;
|
||||||
|
std::cerr << "------------------------------------------------------------\n";
|
||||||
|
std::cerr << "# serialized\n";
|
||||||
|
std::cerr << serialized;
|
||||||
|
std::cerr << "------------------------------------------------------------\n";
|
||||||
|
std::cerr << "# data\n";
|
||||||
|
std::cerr << data;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto data = toml::parse<toml::preserve_comments>(filename);
|
||||||
|
{
|
||||||
|
std::ofstream ofs("tmp.toml");
|
||||||
|
ofs << std::setprecision(16) << std::setw(80) << data;
|
||||||
|
}
|
||||||
|
const auto serialized = toml::parse<toml::preserve_comments>("tmp.toml");
|
||||||
|
if(data != serialized)
|
||||||
|
{
|
||||||
|
std::cerr << "============================================================\n";
|
||||||
|
std::cerr << "result (w/ comment) different: " << filename << std::endl;
|
||||||
|
std::cerr << "------------------------------------------------------------\n";
|
||||||
|
std::cerr << "# serialized\n";
|
||||||
|
std::cerr << serialized;
|
||||||
|
std::cerr << "------------------------------------------------------------\n";
|
||||||
|
std::cerr << "# data\n";
|
||||||
|
std::cerr << data;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -460,3 +460,55 @@ BOOST_AUTO_TEST_CASE(test_overwrite_comments)
|
|||||||
BOOST_TEST(u.as_integer() == 42);
|
BOOST_TEST(u.as_integer() == 42);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_output_comments)
|
||||||
|
{
|
||||||
|
using value_type = toml::basic_value<toml::preserve_comments>;
|
||||||
|
{
|
||||||
|
const value_type v(42, {"comment1", "comment2"});
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << v.comments();
|
||||||
|
|
||||||
|
std::ostringstream ref;
|
||||||
|
ref << "#comment1\n";
|
||||||
|
ref << "#comment2\n";
|
||||||
|
|
||||||
|
BOOST_TEST(oss.str() == ref.str());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v(42, {"comment1", "comment2"});
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
// If v is not a table, toml11 assumes that user is writing something
|
||||||
|
// like the following.
|
||||||
|
|
||||||
|
oss << "answer = " << v;
|
||||||
|
|
||||||
|
BOOST_TEST(oss.str() == "answer = 42 #comment1comment2");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const value_type v(42, {"comment1", "comment2"});
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
// If v is not a table, toml11 assumes that user is writing something
|
||||||
|
// like the following.
|
||||||
|
|
||||||
|
oss << toml::nocomment << "answer = " << v;
|
||||||
|
|
||||||
|
BOOST_TEST(oss.str() == "answer = 42");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const value_type v(42, {"comment1", "comment2"});
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
// If v is not a table, toml11 assumes that user is writing something
|
||||||
|
// like the following.
|
||||||
|
|
||||||
|
oss << toml::nocomment << toml::showcomment << "answer = " << v;
|
||||||
|
|
||||||
|
BOOST_TEST(oss.str() == "answer = 42 #comment1comment2");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,6 +33,17 @@ struct bar
|
|||||||
return toml::table{{"a", this->a}, {"b", this->b}};
|
return toml::table{{"a", this->a}, {"b", this->b}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct baz
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
|
struct qux
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
} // extlib
|
} // extlib
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
@@ -54,6 +65,24 @@ struct into<extlib::foo>
|
|||||||
return toml::table{{"a", f.a}, {"b", f.b}};
|
return toml::table{{"a", f.a}, {"b", f.b}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct from<extlib::baz>
|
||||||
|
{
|
||||||
|
static extlib::baz from_toml(const toml::value& v)
|
||||||
|
{
|
||||||
|
return extlib::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct into<extlib::qux>
|
||||||
|
{
|
||||||
|
static toml::table into_toml(const extlib::qux& f)
|
||||||
|
{
|
||||||
|
return toml::table{{"a", f.a}, {"b", f.b}};
|
||||||
|
}
|
||||||
|
};
|
||||||
} // toml
|
} // toml
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -83,6 +112,16 @@ struct bar
|
|||||||
return toml::table{{"a", this->a}, {"b", this->b}};
|
return toml::table{{"a", this->a}, {"b", this->b}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
struct baz
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
|
struct qux
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
} // extlib2
|
} // extlib2
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
@@ -105,6 +144,28 @@ struct into<extlib2::foo>
|
|||||||
return toml::table{{"a", f.a}, {"b", f.b}};
|
return toml::table{{"a", f.a}, {"b", f.b}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct from<extlib2::baz>
|
||||||
|
{
|
||||||
|
template<typename C, template<typename ...> class M, template<typename ...> class A>
|
||||||
|
static extlib2::baz from_toml(const toml::basic_value<C, M, A>& v)
|
||||||
|
{
|
||||||
|
return extlib2::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct into<extlib2::qux>
|
||||||
|
{
|
||||||
|
static toml::basic_value<toml::preserve_comments, std::map>
|
||||||
|
into_toml(const extlib2::qux& f)
|
||||||
|
{
|
||||||
|
return toml::basic_value<toml::preserve_comments, std::map>{
|
||||||
|
{"a", f.a}, {"b", f.b}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
} // toml
|
} // toml
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -188,6 +249,41 @@ BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_conversion_one_way)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::value v{{"a", 42}, {"b", "baz"}};
|
||||||
|
|
||||||
|
const auto baz = toml::get<extlib::baz>(v);
|
||||||
|
BOOST_TEST(baz.a == 42);
|
||||||
|
BOOST_TEST(baz.b == "baz");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const extlib::qux q{42, "qux"};
|
||||||
|
const toml::value v(q);
|
||||||
|
|
||||||
|
BOOST_TEST(toml::find<int>(v, "a") == 42);
|
||||||
|
BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::basic_value<toml::discard_comments, std::map> v{
|
||||||
|
{"a", 42}, {"b", "baz"}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto baz = toml::get<extlib2::baz>(v);
|
||||||
|
BOOST_TEST(baz.a == 42);
|
||||||
|
BOOST_TEST(baz.b == "baz");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const extlib::qux q{42, "qux"};
|
||||||
|
const toml::basic_value<toml::preserve_comments, std::map> v(q);
|
||||||
|
|
||||||
|
BOOST_TEST(toml::find<int>(v, "a") == 42);
|
||||||
|
BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,6 +27,32 @@ using test_value_types = std::tuple<
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_find_throws)
|
BOOST_AUTO_TEST_CASE(test_find_throws)
|
||||||
{
|
{
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// const-reference version
|
||||||
|
{
|
||||||
|
// value is not a table
|
||||||
|
const toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
const toml::value v{{"key", 42}};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
const toml::value v{{"key", 42}};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(v, "different_key"),
|
||||||
|
std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
const toml::value v{{"key", 42}};
|
||||||
|
BOOST_TEST(42 == toml::find<int>(v, "key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// reference version
|
||||||
{
|
{
|
||||||
// value is not a table
|
// value is not a table
|
||||||
toml::value v(true);
|
toml::value v(true);
|
||||||
@@ -48,6 +74,31 @@ BOOST_AUTO_TEST_CASE(test_find_throws)
|
|||||||
toml::value v{{"key", 42}};
|
toml::value v{{"key", 42}};
|
||||||
BOOST_TEST(42 == toml::find<int>(v, "key"));
|
BOOST_TEST(42 == toml::find<int>(v, "key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// move version
|
||||||
|
|
||||||
|
{
|
||||||
|
// value is not a table
|
||||||
|
toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), "key"), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
toml::value v{{"key", 42}};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), "key"), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
toml::value v{{"key", 42}};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(std::move(v), "different_key"),
|
||||||
|
std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
toml::value v{{"key", 42}};
|
||||||
|
BOOST_TEST(42 == toml::find<int>(std::move(v), "key"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
||||||
@@ -74,6 +125,9 @@ BOOST_AUTO_TEST_CASE(test_find_recursive)
|
|||||||
auto& num2 = toml::find<toml::integer>(v, a, b, c, d);
|
auto& num2 = toml::find<toml::integer>(v, a, b, c, d);
|
||||||
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);
|
||||||
|
BOOST_TEST(42 == num3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +139,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
|
|
||||||
toml::find<toml::boolean>(v, "key") = false;
|
toml::find<toml::boolean>(v, "key") = false;
|
||||||
BOOST_TEST(false == toml::find<toml::boolean>(v, "key"));
|
BOOST_TEST(false == toml::find<toml::boolean>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::boolean>(std::move(v), "key");
|
||||||
|
BOOST_TEST(false == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v{{"key", 42}};
|
value_type v{{"key", 42}};
|
||||||
@@ -92,6 +149,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
|
|
||||||
toml::find<toml::integer>(v, "key") = 54;
|
toml::find<toml::integer>(v, "key") = 54;
|
||||||
BOOST_TEST(toml::integer(54) == toml::find<toml::integer>(v, "key"));
|
BOOST_TEST(toml::integer(54) == toml::find<toml::integer>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::integer>(std::move(v), "key");
|
||||||
|
BOOST_TEST(toml::integer(54) == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v{{"key", 3.14}};
|
value_type v{{"key", 3.14}};
|
||||||
@@ -99,6 +159,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
|
|
||||||
toml::find<toml::floating>(v, "key") = 2.71;
|
toml::find<toml::floating>(v, "key") = 2.71;
|
||||||
BOOST_TEST(toml::floating(2.71) == toml::find<toml::floating>(v, "key"));
|
BOOST_TEST(toml::floating(2.71) == toml::find<toml::floating>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::floating>(std::move(v), "key");
|
||||||
|
BOOST_TEST(toml::floating(2.71) == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v{{"key", "foo"}};
|
value_type v{{"key", "foo"}};
|
||||||
@@ -108,6 +171,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
toml::find<toml::string>(v, "key").str += "bar";
|
toml::find<toml::string>(v, "key").str += "bar";
|
||||||
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
|
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
|
||||||
toml::find<toml::string>(v, "key"));
|
toml::find<toml::string>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::string>(std::move(v), "key");
|
||||||
|
BOOST_TEST(toml::string("foobar", toml::string_t::basic) == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v{{"key", value_type("foo", toml::string_t::literal)}};
|
value_type v{{"key", value_type("foo", toml::string_t::literal)}};
|
||||||
@@ -117,6 +183,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
toml::find<toml::string>(v, "key").str += "bar";
|
toml::find<toml::string>(v, "key").str += "bar";
|
||||||
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
|
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
|
||||||
toml::find<toml::string>(v, "key"));
|
toml::find<toml::string>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::string>(std::move(v), "key");
|
||||||
|
BOOST_TEST(toml::string("foobar", toml::string_t::literal) == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::local_date d(2018, toml::month_t::Apr, 22);
|
toml::local_date d(2018, toml::month_t::Apr, 22);
|
||||||
@@ -126,6 +195,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
toml::find<toml::local_date>(v, "key").year = 2017;
|
toml::find<toml::local_date>(v, "key").year = 2017;
|
||||||
d.year = 2017;
|
d.year = 2017;
|
||||||
BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
|
BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::local_date>(std::move(v), "key");
|
||||||
|
BOOST_CHECK(d == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::local_time t(12, 30, 45);
|
toml::local_time t(12, 30, 45);
|
||||||
@@ -135,6 +207,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
toml::find<toml::local_time>(v, "key").hour = 9;
|
toml::find<toml::local_time>(v, "key").hour = 9;
|
||||||
t.hour = 9;
|
t.hour = 9;
|
||||||
BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
|
BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::local_time>(std::move(v), "key");
|
||||||
|
BOOST_CHECK(t == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
@@ -145,6 +220,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
toml::find<toml::local_datetime>(v, "key").date.year = 2017;
|
toml::find<toml::local_datetime>(v, "key").date.year = 2017;
|
||||||
dt.date.year = 2017;
|
dt.date.year = 2017;
|
||||||
BOOST_CHECK(dt == toml::find<toml::local_datetime>(v, "key"));
|
BOOST_CHECK(dt == toml::find<toml::local_datetime>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::local_datetime>(std::move(v), "key");
|
||||||
|
BOOST_CHECK(dt == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::offset_datetime dt(toml::local_datetime(
|
toml::offset_datetime dt(toml::local_datetime(
|
||||||
@@ -156,6 +234,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
toml::find<toml::offset_datetime>(v, "key").date.year = 2017;
|
toml::find<toml::offset_datetime>(v, "key").date.year = 2017;
|
||||||
dt.date.year = 2017;
|
dt.date.year = 2017;
|
||||||
BOOST_CHECK(dt == toml::find<toml::offset_datetime>(v, "key"));
|
BOOST_CHECK(dt == toml::find<toml::offset_datetime>(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find<toml::offset_datetime>(std::move(v), "key");
|
||||||
|
BOOST_CHECK(dt == moved);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
typename value_type::array_type vec;
|
typename value_type::array_type vec;
|
||||||
@@ -171,6 +252,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
|
|
||||||
const bool result2 = (vec == toml::find<typename value_type::array_type>(v, "key"));
|
const bool result2 = (vec == toml::find<typename value_type::array_type>(v, "key"));
|
||||||
BOOST_CHECK(result2);
|
BOOST_CHECK(result2);
|
||||||
|
|
||||||
|
const auto moved = toml::find<typename value_type::array_type>(std::move(v), "key");
|
||||||
|
const bool result3 = (vec == moved);
|
||||||
|
BOOST_CHECK(result3);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
typename value_type::table_type tab;
|
typename value_type::table_type tab;
|
||||||
@@ -184,6 +269,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
tab["key3"] = value_type(123);
|
tab["key3"] = value_type(123);
|
||||||
const bool result2 = (tab == toml::find<typename value_type::table_type>(v, "key"));
|
const bool result2 = (tab == toml::find<typename value_type::table_type>(v, "key"));
|
||||||
BOOST_CHECK(result2);
|
BOOST_CHECK(result2);
|
||||||
|
|
||||||
|
const auto moved = toml::find<typename value_type::table_type>(std::move(v), "key");
|
||||||
|
const bool result3 = (tab == moved);
|
||||||
|
BOOST_CHECK(result3);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v1(42);
|
value_type v1(42);
|
||||||
@@ -193,6 +282,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
|
|||||||
value_type v2(54);
|
value_type v2(54);
|
||||||
toml::find(v, "key") = v2;
|
toml::find(v, "key") = v2;
|
||||||
BOOST_CHECK(v2 == toml::find(v, "key"));
|
BOOST_CHECK(v2 == toml::find(v, "key"));
|
||||||
|
|
||||||
|
const auto moved = toml::find(std::move(v), "key");
|
||||||
|
BOOST_CHECK(v2 == moved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,6 +301,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_integer_type, value_type, test_value_typ
|
|||||||
BOOST_TEST(std::uint64_t(42) == toml::find<std::uint64_t>(v, "key"));
|
BOOST_TEST(std::uint64_t(42) == toml::find<std::uint64_t>(v, "key"));
|
||||||
BOOST_TEST(std::int16_t(42) == toml::find<std::int16_t >(v, "key"));
|
BOOST_TEST(std::int16_t(42) == toml::find<std::int16_t >(v, "key"));
|
||||||
BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(v, "key"));
|
BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(v, "key"));
|
||||||
|
BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(std::move(v), "key"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,6 +312,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_ty
|
|||||||
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(v, "key"));
|
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(v, "key"));
|
||||||
BOOST_TEST(static_cast<double >(3.14) == toml::find<double >(v, "key"));
|
BOOST_TEST(static_cast<double >(3.14) == toml::find<double >(v, "key"));
|
||||||
BOOST_TEST(static_cast<long double>(3.14) == toml::find<long double>(v, "key"));
|
BOOST_TEST(static_cast<long double>(3.14) == toml::find<long double>(v, "key"));
|
||||||
|
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(std::move(v), "key"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +330,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_string_type, value_type, test_value_type
|
|||||||
toml::find<std::string>(v, "key") += "bar";
|
toml::find<std::string>(v, "key") += "bar";
|
||||||
BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
|
BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
|
||||||
|
const auto moved = toml::find<std::string>(std::move(v), "key");
|
||||||
|
BOOST_TEST("foo" == moved);
|
||||||
|
}
|
||||||
|
|
||||||
#if __cplusplus >= 201703L
|
#if __cplusplus >= 201703L
|
||||||
{
|
{
|
||||||
@@ -292,6 +391,53 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array, value_type, test_value_types
|
|||||||
BOOST_TEST(2.71 == pr.second);
|
BOOST_TEST(2.71 == pr.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array, value_type, test_value_types)
|
||||||
|
{
|
||||||
|
value_type v1{{"key", {42, 54, 69, 72}}};
|
||||||
|
value_type v2{{"key", {42, 54, 69, 72}}};
|
||||||
|
value_type v3{{"key", {42, 54, 69, 72}}};
|
||||||
|
value_type v4{{"key", {42, 54, 69, 72}}};
|
||||||
|
value_type v5{{"key", {42, 54, 69, 72}}};
|
||||||
|
|
||||||
|
const std::vector<int> vec = toml::find<std::vector<int>>(std::move(v1), "key");
|
||||||
|
const std::list<short> lst = toml::find<std::list<short>>(std::move(v2), "key");
|
||||||
|
const std::deque<std::int64_t> deq = toml::find<std::deque<std::int64_t>>(std::move(v3), "key");
|
||||||
|
|
||||||
|
BOOST_TEST(42 == vec.at(0));
|
||||||
|
BOOST_TEST(54 == vec.at(1));
|
||||||
|
BOOST_TEST(69 == vec.at(2));
|
||||||
|
BOOST_TEST(72 == vec.at(3));
|
||||||
|
|
||||||
|
std::list<short>::const_iterator iter = lst.begin();
|
||||||
|
BOOST_TEST(static_cast<short>(42) == *(iter++));
|
||||||
|
BOOST_TEST(static_cast<short>(54) == *(iter++));
|
||||||
|
BOOST_TEST(static_cast<short>(69) == *(iter++));
|
||||||
|
BOOST_TEST(static_cast<short>(72) == *(iter++));
|
||||||
|
|
||||||
|
BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
|
||||||
|
BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
|
||||||
|
BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
|
||||||
|
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
||||||
|
|
||||||
|
std::array<int, 4> ary = toml::find<std::array<int, 4>>(std::move(v4), "key");
|
||||||
|
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
||||||
|
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
||||||
|
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
||||||
|
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
||||||
|
|
||||||
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
|
toml::find<std::tuple<int, short, unsigned, long>>(std::move(v5), "key");
|
||||||
|
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
||||||
|
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
||||||
|
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
||||||
|
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||||
|
|
||||||
|
value_type p{{"key", {3.14, 2.71}}};
|
||||||
|
std::pair<double, double> pr = toml::find<std::pair<double, double> >(std::move(p), "key");
|
||||||
|
BOOST_TEST(3.14 == pr.first);
|
||||||
|
BOOST_TEST(2.71 == pr.second);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_value_types)
|
||||||
{
|
{
|
||||||
value_type v1{42, 54, 69, 72};
|
value_type v1{42, 54, 69, 72};
|
||||||
@@ -323,8 +469,42 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_va
|
|||||||
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array_of_array, value_type, test_value_types)
|
||||||
|
{
|
||||||
|
value_type a1{42, 54, 69, 72};
|
||||||
|
value_type a2{"foo", "bar", "baz"};
|
||||||
|
value_type v1{{"key", {a1, a2}}};
|
||||||
|
value_type v2{{"key", {a1, a2}}};
|
||||||
|
|
||||||
|
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||||
|
toml::find<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v1), "key");
|
||||||
|
|
||||||
|
BOOST_TEST(p.first.at(0) == 42);
|
||||||
|
BOOST_TEST(p.first.at(1) == 54);
|
||||||
|
BOOST_TEST(p.first.at(2) == 69);
|
||||||
|
BOOST_TEST(p.first.at(3) == 72);
|
||||||
|
|
||||||
|
BOOST_TEST(p.second.at(0) == "foo");
|
||||||
|
BOOST_TEST(p.second.at(1) == "bar");
|
||||||
|
BOOST_TEST(p.second.at(2) == "baz");
|
||||||
|
|
||||||
|
std::tuple<std::vector<int>, std::vector<std::string>> t =
|
||||||
|
toml::find<std::tuple<std::vector<int>, std::vector<std::string>>>(std::move(v2), "key");
|
||||||
|
|
||||||
|
BOOST_TEST(std::get<0>(t).at(0) == 42);
|
||||||
|
BOOST_TEST(std::get<0>(t).at(1) == 54);
|
||||||
|
BOOST_TEST(std::get<0>(t).at(2) == 69);
|
||||||
|
BOOST_TEST(std::get<0>(t).at(3) == 72);
|
||||||
|
|
||||||
|
BOOST_TEST(std::get<1>(t).at(0) == "foo");
|
||||||
|
BOOST_TEST(std::get<1>(t).at(1) == "bar");
|
||||||
|
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_table, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_table, value_type, test_value_types)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
value_type v1{{"key", {
|
value_type v1{{"key", {
|
||||||
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
|
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
|
||||||
}}};
|
}}};
|
||||||
@@ -333,10 +513,22 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_table, value_type, test_value_types
|
|||||||
BOOST_TEST(v.at("key2") == 2);
|
BOOST_TEST(v.at("key2") == 2);
|
||||||
BOOST_TEST(v.at("key3") == 3);
|
BOOST_TEST(v.at("key3") == 3);
|
||||||
BOOST_TEST(v.at("key4") == 4);
|
BOOST_TEST(v.at("key4") == 4);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v1{{"key", {
|
||||||
|
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
|
||||||
|
}}};
|
||||||
|
const auto v = toml::find<std::map<std::string, int>>(std::move(v1), "key");
|
||||||
|
BOOST_TEST(v.at("key1") == 1);
|
||||||
|
BOOST_TEST(v.at("key2") == 2);
|
||||||
|
BOOST_TEST(v.at("key3") == 3);
|
||||||
|
BOOST_TEST(v.at("key4") == 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_date, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_date, value_type, test_value_types)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
|
value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
|
||||||
const auto date = std::chrono::system_clock::to_time_t(
|
const auto date = std::chrono::system_clock::to_time_t(
|
||||||
toml::find<std::chrono::system_clock::time_point>(v1, "key"));
|
toml::find<std::chrono::system_clock::time_point>(v1, "key"));
|
||||||
@@ -351,18 +543,44 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_date, value_type, test_value_
|
|||||||
t.tm_isdst = -1;
|
t.tm_isdst = -1;
|
||||||
const auto c = std::mktime(&t);
|
const auto c = std::mktime(&t);
|
||||||
BOOST_TEST(c == date);
|
BOOST_TEST(c == date);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
|
||||||
|
const auto date = std::chrono::system_clock::to_time_t(
|
||||||
|
toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key"));
|
||||||
|
|
||||||
|
std::tm t;
|
||||||
|
t.tm_year = 2018 - 1900;
|
||||||
|
t.tm_mon = 4 - 1;
|
||||||
|
t.tm_mday = 1;
|
||||||
|
t.tm_hour = 0;
|
||||||
|
t.tm_min = 0;
|
||||||
|
t.tm_sec = 0;
|
||||||
|
t.tm_isdst = -1;
|
||||||
|
const auto c = std::mktime(&t);
|
||||||
|
BOOST_TEST(c == date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_time, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_time, value_type, test_value_types)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
value_type v1{{"key", toml::local_time{12, 30, 45}}};
|
value_type v1{{"key", toml::local_time{12, 30, 45}}};
|
||||||
const auto time = toml::find<std::chrono::seconds>(v1, "key");
|
const auto time = toml::find<std::chrono::seconds>(v1, "key");
|
||||||
BOOST_CHECK(time == std::chrono::hours(12) +
|
BOOST_CHECK(time == std::chrono::hours(12) +
|
||||||
std::chrono::minutes(30) + std::chrono::seconds(45));
|
std::chrono::minutes(30) + std::chrono::seconds(45));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v1{{"key", toml::local_time{12, 30, 45}}};
|
||||||
|
const auto time = toml::find<std::chrono::seconds>(std::move(v1), "key");
|
||||||
|
BOOST_CHECK(time == std::chrono::hours(12) +
|
||||||
|
std::chrono::minutes(30) + std::chrono::seconds(45));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_datetime, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_datetime, value_type, test_value_types)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
value_type v1{{"key", toml::local_datetime(
|
value_type v1{{"key", toml::local_datetime(
|
||||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||||
toml::local_time{12, 30, 45})}};
|
toml::local_time{12, 30, 45})}};
|
||||||
@@ -379,6 +597,25 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_datetime, value_type, test_va
|
|||||||
t.tm_isdst = -1;
|
t.tm_isdst = -1;
|
||||||
const auto c = std::mktime(&t);
|
const auto c = std::mktime(&t);
|
||||||
BOOST_TEST(c == date);
|
BOOST_TEST(c == date);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v1{{"key", toml::local_datetime(
|
||||||
|
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||||
|
toml::local_time{12, 30, 45})}};
|
||||||
|
|
||||||
|
const auto date = std::chrono::system_clock::to_time_t(
|
||||||
|
toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key"));
|
||||||
|
std::tm t;
|
||||||
|
t.tm_year = 2018 - 1900;
|
||||||
|
t.tm_mon = 4 - 1;
|
||||||
|
t.tm_mday = 1;
|
||||||
|
t.tm_hour = 12;
|
||||||
|
t.tm_min = 30;
|
||||||
|
t.tm_sec = 45;
|
||||||
|
t.tm_isdst = -1;
|
||||||
|
const auto c = std::mktime(&t);
|
||||||
|
BOOST_TEST(c == date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types)
|
||||||
@@ -428,5 +665,28 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_va
|
|||||||
BOOST_TEST(tm.tm_min == 30);
|
BOOST_TEST(tm.tm_min == 30);
|
||||||
BOOST_TEST(tm.tm_sec == 0);
|
BOOST_TEST(tm.tm_sec == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
value_type v1{{"key", toml::offset_datetime(
|
||||||
|
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||||
|
toml::local_time{12, 30, 0},
|
||||||
|
toml::time_offset{-8, 0})}};
|
||||||
|
// 2018-04-01T12:30:00-08:00
|
||||||
|
// == 2018-04-01T20:30:00Z
|
||||||
|
|
||||||
|
const auto date = toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key");
|
||||||
|
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||||
|
|
||||||
|
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||||
|
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
|
||||||
|
BOOST_CHECK(tmp);
|
||||||
|
const auto tm = *tmp;
|
||||||
|
BOOST_TEST(tm.tm_year + 1900 == 2018);
|
||||||
|
BOOST_TEST(tm.tm_mon + 1 == 4);
|
||||||
|
BOOST_TEST(tm.tm_mday == 1);
|
||||||
|
BOOST_TEST(tm.tm_hour == 20);
|
||||||
|
BOOST_TEST(tm.tm_min == 30);
|
||||||
|
BOOST_TEST(tm.tm_sec == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,55 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types)
|
|||||||
}
|
}
|
||||||
#undef TOML11_TEST_FIND_OR_EXACT
|
#undef TOML11_TEST_FIND_OR_EXACT
|
||||||
|
|
||||||
|
#define TOML11_TEST_FIND_OR_MOVE(toml_type, init_expr, opt_expr) \
|
||||||
|
{ \
|
||||||
|
using namespace test; \
|
||||||
|
const toml::toml_type init init_expr ; \
|
||||||
|
toml::toml_type opt opt_expr ; \
|
||||||
|
value_type v{{"key", init}}; \
|
||||||
|
BOOST_TEST(init != opt); \
|
||||||
|
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));\
|
||||||
|
BOOST_TEST(init == moved); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move, value_type, test_value_types)
|
||||||
|
{
|
||||||
|
TOML11_TEST_FIND_OR_MOVE(boolean, ( true), (false))
|
||||||
|
TOML11_TEST_FIND_OR_MOVE(integer, ( 42), ( 54))
|
||||||
|
TOML11_TEST_FIND_OR_MOVE(floating, ( 3.14), ( 2.71))
|
||||||
|
TOML11_TEST_FIND_OR_MOVE(string, ("foo"), ("bar"))
|
||||||
|
TOML11_TEST_FIND_OR_MOVE(local_time, (12, 30, 45), (6, 0, 30))
|
||||||
|
TOML11_TEST_FIND_OR_MOVE(local_date, (2019, toml::month_t::Apr, 1),
|
||||||
|
(1999, toml::month_t::Jan, 2))
|
||||||
|
TOML11_TEST_FIND_OR_MOVE(local_datetime,
|
||||||
|
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
|
||||||
|
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
|
||||||
|
)
|
||||||
|
TOML11_TEST_FIND_OR_MOVE(offset_datetime,
|
||||||
|
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
|
||||||
|
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typename value_type::array_type init{1,2,3,4,5};
|
||||||
|
typename value_type::array_type opt {6,7,8,9,10};
|
||||||
|
value_type v{{"key", init}};
|
||||||
|
BOOST_TEST(init != opt);
|
||||||
|
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
|
||||||
|
BOOST_TEST(init == moved);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
|
||||||
|
typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
|
||||||
|
value_type v{{"key", init}};
|
||||||
|
BOOST_TEST(init != opt);
|
||||||
|
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
|
||||||
|
BOOST_TEST(init == moved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef TOML11_TEST_FIND_OR_MOVE
|
||||||
|
|
||||||
|
|
||||||
#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\
|
#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\
|
||||||
{ \
|
{ \
|
||||||
using namespace test; \
|
using namespace test; \
|
||||||
@@ -304,10 +353,20 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_type
|
|||||||
BOOST_AUTO_TEST_CASE(test_find_or_integer)
|
BOOST_AUTO_TEST_CASE(test_find_or_integer)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
toml::value v = toml::table{{"num", 42}};
|
toml::value v{{"num", 42}};
|
||||||
BOOST_TEST(42u == toml::find_or(v, "num", 0u));
|
BOOST_TEST(42u == toml::find_or(v, "num", 0u));
|
||||||
BOOST_TEST(0u == toml::find_or(v, "foo", 0u));
|
BOOST_TEST(0u == toml::find_or(v, "foo", 0u));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v{{"num", 42}};
|
||||||
|
const auto moved = toml::find_or(std::move(v), "num", 0u);
|
||||||
|
BOOST_TEST(42u == moved);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v{{"num", 42}};
|
||||||
|
const auto moved = toml::find_or(std::move(v), "foo", 0u);
|
||||||
|
BOOST_TEST(0u == moved);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_find_or_floating)
|
BOOST_AUTO_TEST_CASE(test_find_or_floating)
|
||||||
@@ -318,6 +377,14 @@ BOOST_AUTO_TEST_CASE(test_find_or_floating)
|
|||||||
BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f));
|
BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f));
|
||||||
BOOST_TEST(static_cast<float>(double(3.14)) == toml::find_or(v2, "key", 2.71f));
|
BOOST_TEST(static_cast<float>(double(3.14)) == toml::find_or(v2, "key", 2.71f));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v1{{"key", 42}};
|
||||||
|
toml::value v2{{"key", 3.14}};
|
||||||
|
const auto moved1 = toml::find_or(std::move(v1), "key", 2.71f);
|
||||||
|
const auto moved2 = toml::find_or(std::move(v2), "key", 2.71f);
|
||||||
|
BOOST_TEST(2.71f == moved1);
|
||||||
|
BOOST_TEST(static_cast<float>(double(3.14)) == moved2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_find_or_string)
|
BOOST_AUTO_TEST_CASE(test_find_or_string)
|
||||||
@@ -345,6 +412,32 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
|
|||||||
s1 = "bazqux"; // restoring moved value
|
s1 = "bazqux"; // restoring moved value
|
||||||
BOOST_TEST("bazqux" == toml::find_or(std::move(v2), "key", std::move(s1)));
|
BOOST_TEST("bazqux" == toml::find_or(std::move(v2), "key", std::move(s1)));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||||
|
toml::value v2 = toml::table{{"key", 42}};
|
||||||
|
|
||||||
|
std::string s1("bazqux");
|
||||||
|
|
||||||
|
const auto moved1 = toml::find_or(std::move(v1), "key", s1);
|
||||||
|
const auto moved2 = toml::find_or(std::move(v2), "key", s1);
|
||||||
|
|
||||||
|
BOOST_TEST("foobar" == moved1);
|
||||||
|
BOOST_TEST("bazqux" == moved2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||||
|
toml::value v2 = toml::table{{"key", 42}};
|
||||||
|
|
||||||
|
std::string s1("bazqux");
|
||||||
|
std::string s2("bazqux");
|
||||||
|
|
||||||
|
const auto moved1 = toml::find_or(std::move(v1), "key", std::move(s1));
|
||||||
|
const auto moved2 = toml::find_or(std::move(v2), "key", std::move(s2));
|
||||||
|
|
||||||
|
BOOST_TEST("foobar" == moved1);
|
||||||
|
BOOST_TEST("bazqux" == moved2);
|
||||||
|
}
|
||||||
|
|
||||||
// string literal
|
// string literal
|
||||||
{
|
{
|
||||||
toml::value v1 = toml::table{{"key", "foobar"}};
|
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||||
@@ -357,4 +450,90 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
|
|||||||
BOOST_TEST("foobar" == toml::find_or(v1, "key", lit));
|
BOOST_TEST("foobar" == toml::find_or(v1, "key", lit));
|
||||||
BOOST_TEST("bazqux" == toml::find_or(v2, "key", lit));
|
BOOST_TEST("bazqux" == toml::find_or(v2, "key", lit));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||||
|
toml::value v2 = toml::table{{"key",42}};
|
||||||
|
|
||||||
|
const auto moved1 = toml::find_or(std::move(v1), "key", "bazqux");
|
||||||
|
const auto moved2 = toml::find_or(std::move(v2), "key", "bazqux");
|
||||||
|
|
||||||
|
BOOST_TEST("foobar" == moved1);
|
||||||
|
BOOST_TEST("bazqux" == moved2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||||
|
toml::value v2 = toml::table{{"key",42}};
|
||||||
|
|
||||||
|
const char* lit = "bazqux";
|
||||||
|
const auto moved1 = toml::find_or(std::move(v1), "key", lit);
|
||||||
|
const auto moved2 = toml::find_or(std::move(v2), "key", lit);
|
||||||
|
|
||||||
|
BOOST_TEST("foobar" == moved1);
|
||||||
|
BOOST_TEST("bazqux" == moved2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_find_or_map)
|
||||||
|
{
|
||||||
|
using map_type = std::map<std::string, std::string>;
|
||||||
|
{
|
||||||
|
const toml::value v1{
|
||||||
|
{"key", {{"key", "value"}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto key = toml::find_or(v1, "key", map_type{});
|
||||||
|
const auto key2 = toml::find_or(v1, "key2", map_type{});
|
||||||
|
|
||||||
|
BOOST_TEST(!key.empty());
|
||||||
|
BOOST_TEST(key2.empty());
|
||||||
|
|
||||||
|
BOOST_TEST(key.size() == 1u);
|
||||||
|
BOOST_TEST(key.at("key") == "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1{
|
||||||
|
{"key", {{"key", "value"}}}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto key = toml::find_or<map_type>(v1, "key", map_type{});
|
||||||
|
const auto key2 = toml::find_or<map_type>(v1, "key2", map_type{});
|
||||||
|
|
||||||
|
BOOST_TEST(!key.empty());
|
||||||
|
BOOST_TEST(key2.empty());
|
||||||
|
|
||||||
|
BOOST_TEST(key.size() == 1u);
|
||||||
|
BOOST_TEST(key.at("key") == "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
toml::value v1{
|
||||||
|
{"key", {{"key", "value"}}}
|
||||||
|
};
|
||||||
|
toml::value v2(v1);
|
||||||
|
|
||||||
|
const auto key = toml::find_or(std::move(v1), "key", map_type{});
|
||||||
|
const auto key2 = toml::find_or(std::move(v2), "key2", map_type{});
|
||||||
|
|
||||||
|
BOOST_TEST(!key.empty());
|
||||||
|
BOOST_TEST(key2.empty());
|
||||||
|
|
||||||
|
BOOST_TEST(key.size() == 1u);
|
||||||
|
BOOST_TEST(key.at("key") == "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1{
|
||||||
|
{"key", {{"key", "value"}}}
|
||||||
|
};
|
||||||
|
toml::value v2(v1);
|
||||||
|
|
||||||
|
const auto key = toml::find_or<map_type>(std::move(v1), "key", map_type{});
|
||||||
|
const auto key2 = toml::find_or<map_type>(std::move(v2), "key2", map_type{});
|
||||||
|
|
||||||
|
BOOST_TEST(!key.empty());
|
||||||
|
BOOST_TEST(key2.empty());
|
||||||
|
|
||||||
|
BOOST_TEST(key.size() == 1u);
|
||||||
|
BOOST_TEST(key.at("key") == "value");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <boost/test/included/unit_test.hpp>
|
#include <boost/test/included/unit_test.hpp>
|
||||||
#endif
|
#endif
|
||||||
#include <toml.hpp>
|
#include <toml.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
// to check it successfully compiles. it does not check the formatted string.
|
// to check it successfully compiles. it does not check the formatted string.
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
|
|
||||||
toml::get<toml::boolean>(v) = false;
|
toml::get<toml::boolean>(v) = false;
|
||||||
BOOST_TEST(false == toml::get<toml::boolean>(v));
|
BOOST_TEST(false == toml::get<toml::boolean>(v));
|
||||||
|
|
||||||
|
toml::boolean x = toml::get<toml::boolean>(std::move(v));
|
||||||
|
BOOST_TEST(false == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v(42);
|
value_type v(42);
|
||||||
@@ -38,6 +41,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
|
|
||||||
toml::get<toml::integer>(v) = 54;
|
toml::get<toml::integer>(v) = 54;
|
||||||
BOOST_TEST(toml::integer(54) == toml::get<toml::integer>(v));
|
BOOST_TEST(toml::integer(54) == toml::get<toml::integer>(v));
|
||||||
|
|
||||||
|
toml::integer x = toml::get<toml::integer>(std::move(v));
|
||||||
|
BOOST_TEST(toml::integer(54) == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v(3.14);
|
value_type v(3.14);
|
||||||
@@ -45,6 +51,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
|
|
||||||
toml::get<toml::floating>(v) = 2.71;
|
toml::get<toml::floating>(v) = 2.71;
|
||||||
BOOST_TEST(toml::floating(2.71) == toml::get<toml::floating>(v));
|
BOOST_TEST(toml::floating(2.71) == toml::get<toml::floating>(v));
|
||||||
|
|
||||||
|
toml::floating x = toml::get<toml::floating>(std::move(v));
|
||||||
|
BOOST_TEST(toml::floating(2.71) == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v("foo");
|
value_type v("foo");
|
||||||
@@ -54,6 +63,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
toml::get<toml::string>(v).str += "bar";
|
toml::get<toml::string>(v).str += "bar";
|
||||||
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
|
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
|
||||||
toml::get<toml::string>(v));
|
toml::get<toml::string>(v));
|
||||||
|
|
||||||
|
toml::string x = toml::get<toml::string>(std::move(v));
|
||||||
|
BOOST_TEST(toml::string("foobar") == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v("foo", toml::string_t::literal);
|
value_type v("foo", toml::string_t::literal);
|
||||||
@@ -63,6 +75,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
toml::get<toml::string>(v).str += "bar";
|
toml::get<toml::string>(v).str += "bar";
|
||||||
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
|
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
|
||||||
toml::get<toml::string>(v));
|
toml::get<toml::string>(v));
|
||||||
|
|
||||||
|
toml::string x = toml::get<toml::string>(std::move(v));
|
||||||
|
BOOST_TEST(toml::string("foobar", toml::string_t::literal) == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::local_date d(2018, toml::month_t::Apr, 22);
|
toml::local_date d(2018, toml::month_t::Apr, 22);
|
||||||
@@ -72,6 +87,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
toml::get<toml::local_date>(v).year = 2017;
|
toml::get<toml::local_date>(v).year = 2017;
|
||||||
d.year = 2017;
|
d.year = 2017;
|
||||||
BOOST_TEST(d == toml::get<toml::local_date>(v));
|
BOOST_TEST(d == toml::get<toml::local_date>(v));
|
||||||
|
|
||||||
|
toml::local_date x = toml::get<toml::local_date>(std::move(v));
|
||||||
|
BOOST_TEST(d == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::local_time t(12, 30, 45);
|
toml::local_time t(12, 30, 45);
|
||||||
@@ -81,6 +99,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
toml::get<toml::local_time>(v).hour = 9;
|
toml::get<toml::local_time>(v).hour = 9;
|
||||||
t.hour = 9;
|
t.hour = 9;
|
||||||
BOOST_TEST(t == toml::get<toml::local_time>(v));
|
BOOST_TEST(t == toml::get<toml::local_time>(v));
|
||||||
|
|
||||||
|
toml::local_time x = toml::get<toml::local_time>(std::move(v));
|
||||||
|
BOOST_TEST(t == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
@@ -91,6 +112,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
toml::get<toml::local_datetime>(v).date.year = 2017;
|
toml::get<toml::local_datetime>(v).date.year = 2017;
|
||||||
dt.date.year = 2017;
|
dt.date.year = 2017;
|
||||||
BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
|
BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
|
||||||
|
|
||||||
|
toml::local_datetime x = toml::get<toml::local_datetime>(std::move(v));
|
||||||
|
BOOST_TEST(dt == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
toml::offset_datetime dt(toml::local_datetime(
|
toml::offset_datetime dt(toml::local_datetime(
|
||||||
@@ -102,6 +126,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
toml::get<toml::offset_datetime>(v).date.year = 2017;
|
toml::get<toml::offset_datetime>(v).date.year = 2017;
|
||||||
dt.date.year = 2017;
|
dt.date.year = 2017;
|
||||||
BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
|
BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
|
||||||
|
|
||||||
|
toml::offset_datetime x = toml::get<toml::offset_datetime>(std::move(v));
|
||||||
|
BOOST_TEST(dt == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using array_type = typename value_type::array_type;
|
using array_type = typename value_type::array_type;
|
||||||
@@ -114,6 +141,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
toml::get<array_type>(v).push_back(value_type(123));
|
toml::get<array_type>(v).push_back(value_type(123));
|
||||||
vec.push_back(value_type(123));
|
vec.push_back(value_type(123));
|
||||||
BOOST_TEST(vec == toml::get<array_type>(v));
|
BOOST_TEST(vec == toml::get<array_type>(v));
|
||||||
|
|
||||||
|
array_type x = toml::get<array_type>(std::move(v));
|
||||||
|
BOOST_TEST(vec == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using table_type = typename value_type::table_type;
|
using table_type = typename value_type::table_type;
|
||||||
@@ -126,6 +156,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
toml::get<table_type>(v)["key3"] = value_type(123);
|
toml::get<table_type>(v)["key3"] = value_type(123);
|
||||||
tab["key3"] = value_type(123);
|
tab["key3"] = value_type(123);
|
||||||
BOOST_TEST(tab == toml::get<table_type>(v));
|
BOOST_TEST(tab == toml::get<table_type>(v));
|
||||||
|
|
||||||
|
table_type x = toml::get<table_type>(std::move(v));
|
||||||
|
BOOST_TEST(tab == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v1(42);
|
value_type v1(42);
|
||||||
@@ -134,6 +167,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
|
|||||||
value_type v2(54);
|
value_type v2(54);
|
||||||
toml::get<value_type>(v1) = v2;
|
toml::get<value_type>(v1) = v2;
|
||||||
BOOST_TEST(v2 == toml::get<value_type>(v1));
|
BOOST_TEST(v2 == toml::get<value_type>(v1));
|
||||||
|
|
||||||
|
value_type x = toml::get<value_type>(std::move(v1));
|
||||||
|
BOOST_TEST(v2 == x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +186,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_integer_type, value_type, test_value_type
|
|||||||
BOOST_TEST(std::uint64_t(42) == toml::get<std::uint64_t>(v));
|
BOOST_TEST(std::uint64_t(42) == toml::get<std::uint64_t>(v));
|
||||||
BOOST_TEST(std::int16_t(42) == toml::get<std::int16_t >(v));
|
BOOST_TEST(std::int16_t(42) == toml::get<std::int16_t >(v));
|
||||||
BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(v));
|
BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(v));
|
||||||
|
|
||||||
|
BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(std::move(v)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,6 +198,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_typ
|
|||||||
BOOST_TEST(static_cast<float >(3.14) == toml::get<float >(v));
|
BOOST_TEST(static_cast<float >(3.14) == toml::get<float >(v));
|
||||||
BOOST_TEST(static_cast<double >(3.14) == toml::get<double >(v));
|
BOOST_TEST(static_cast<double >(3.14) == toml::get<double >(v));
|
||||||
BOOST_TEST(static_cast<long double>(3.14) == toml::get<long double>(v));
|
BOOST_TEST(static_cast<long double>(3.14) == toml::get<long double>(v));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14f == toml::get<float>(std::move(v)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,12 +210,18 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types
|
|||||||
BOOST_TEST("foo" == toml::get<std::string>(v));
|
BOOST_TEST("foo" == toml::get<std::string>(v));
|
||||||
toml::get<std::string>(v) += "bar";
|
toml::get<std::string>(v) += "bar";
|
||||||
BOOST_TEST("foobar" == toml::get<std::string>(v));
|
BOOST_TEST("foobar" == toml::get<std::string>(v));
|
||||||
|
|
||||||
|
const auto x = toml::get<std::string>(std::move(v));
|
||||||
|
BOOST_TEST("foobar" == x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
value_type v("foo", toml::string_t::literal);
|
value_type v("foo", toml::string_t::literal);
|
||||||
BOOST_TEST("foo" == toml::get<std::string>(v));
|
BOOST_TEST("foo" == toml::get<std::string>(v));
|
||||||
toml::get<std::string>(v) += "bar";
|
toml::get<std::string>(v) += "bar";
|
||||||
BOOST_TEST("foobar" == toml::get<std::string>(v));
|
BOOST_TEST("foobar" == toml::get<std::string>(v));
|
||||||
|
|
||||||
|
const auto x = toml::get<std::string>(std::move(v));
|
||||||
|
BOOST_TEST("foobar" == x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __cplusplus >= 201703L
|
#if __cplusplus >= 201703L
|
||||||
@@ -192,6 +238,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
const value_type v{42, 54, 69, 72};
|
const value_type v{42, 54, 69, 72};
|
||||||
|
|
||||||
const std::vector<int> vec = toml::get<std::vector<int>>(v);
|
const std::vector<int> vec = toml::get<std::vector<int>>(v);
|
||||||
@@ -231,10 +278,55 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
|
|||||||
std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
|
std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
|
||||||
BOOST_TEST(3.14 == pr.first);
|
BOOST_TEST(3.14 == pr.first);
|
||||||
BOOST_TEST(2.71 == pr.second);
|
BOOST_TEST(2.71 == pr.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
value_type v{42, 54, 69, 72};
|
||||||
|
const std::vector<int> vec = toml::get<std::vector<int>>(std::move(v));
|
||||||
|
BOOST_TEST(42 == vec.at(0));
|
||||||
|
BOOST_TEST(54 == vec.at(1));
|
||||||
|
BOOST_TEST(69 == vec.at(2));
|
||||||
|
BOOST_TEST(72 == vec.at(3));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v{42, 54, 69, 72};
|
||||||
|
const std::deque<int> deq = toml::get<std::deque<int>>(std::move(v));
|
||||||
|
BOOST_TEST(42 == deq.at(0));
|
||||||
|
BOOST_TEST(54 == deq.at(1));
|
||||||
|
BOOST_TEST(69 == deq.at(2));
|
||||||
|
BOOST_TEST(72 == deq.at(3));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v{42, 54, 69, 72};
|
||||||
|
const std::list<int> lst = toml::get<std::list<int>>(std::move(v));
|
||||||
|
std::list<int>::const_iterator iter = lst.begin();
|
||||||
|
BOOST_TEST(42 == *(iter++));
|
||||||
|
BOOST_TEST(54 == *(iter++));
|
||||||
|
BOOST_TEST(69 == *(iter++));
|
||||||
|
BOOST_TEST(72 == *(iter++));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v{42, 54, 69, 72};
|
||||||
|
std::array<int, 4> ary = toml::get<std::array<int, 4>>(std::move(v));
|
||||||
|
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
||||||
|
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
||||||
|
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
||||||
|
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v{42, 54, 69, 72};
|
||||||
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
|
toml::get<std::tuple<int, short, unsigned, long>>(std::move(v));
|
||||||
|
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
||||||
|
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
||||||
|
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
||||||
|
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_value_types)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
const value_type v1{42, 54, 69, 72};
|
const value_type v1{42, 54, 69, 72};
|
||||||
const value_type v2{"foo", "bar", "baz"};
|
const value_type v2{"foo", "bar", "baz"};
|
||||||
const value_type v{v1, v2};
|
const value_type v{v1, v2};
|
||||||
@@ -242,11 +334,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_val
|
|||||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||||
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
|
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
|
||||||
|
|
||||||
|
BOOST_TEST(p.first.size() == 4u);
|
||||||
BOOST_TEST(p.first.at(0) == 42);
|
BOOST_TEST(p.first.at(0) == 42);
|
||||||
BOOST_TEST(p.first.at(1) == 54);
|
BOOST_TEST(p.first.at(1) == 54);
|
||||||
BOOST_TEST(p.first.at(2) == 69);
|
BOOST_TEST(p.first.at(2) == 69);
|
||||||
BOOST_TEST(p.first.at(3) == 72);
|
BOOST_TEST(p.first.at(3) == 72);
|
||||||
|
|
||||||
|
BOOST_TEST(p.second.size() == 3u);
|
||||||
BOOST_TEST(p.second.at(0) == "foo");
|
BOOST_TEST(p.second.at(0) == "foo");
|
||||||
BOOST_TEST(p.second.at(1) == "bar");
|
BOOST_TEST(p.second.at(1) == "bar");
|
||||||
BOOST_TEST(p.second.at(2) == "baz");
|
BOOST_TEST(p.second.at(2) == "baz");
|
||||||
@@ -262,10 +356,31 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_val
|
|||||||
BOOST_TEST(std::get<1>(t).at(0) == "foo");
|
BOOST_TEST(std::get<1>(t).at(0) == "foo");
|
||||||
BOOST_TEST(std::get<1>(t).at(1) == "bar");
|
BOOST_TEST(std::get<1>(t).at(1) == "bar");
|
||||||
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
BOOST_TEST(std::get<1>(t).at(2) == "baz");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value_type v1{42, 54, 69, 72};
|
||||||
|
const value_type v2{"foo", "bar", "baz"};
|
||||||
|
value_type v{v1, v2};
|
||||||
|
|
||||||
|
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||||
|
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v));
|
||||||
|
|
||||||
|
BOOST_TEST(p.first.size() == 4u);
|
||||||
|
BOOST_TEST(p.first.at(0) == 42);
|
||||||
|
BOOST_TEST(p.first.at(1) == 54);
|
||||||
|
BOOST_TEST(p.first.at(2) == 69);
|
||||||
|
BOOST_TEST(p.first.at(3) == 72);
|
||||||
|
|
||||||
|
BOOST_TEST(p.second.size() == 3u);
|
||||||
|
BOOST_TEST(p.second.at(0) == "foo");
|
||||||
|
BOOST_TEST(p.second.at(1) == "bar");
|
||||||
|
BOOST_TEST(p.second.at(2) == "baz");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
const value_type v1{
|
const value_type v1{
|
||||||
{"key1", 1},
|
{"key1", 1},
|
||||||
{"key2", 2},
|
{"key2", 2},
|
||||||
@@ -278,6 +393,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types)
|
|||||||
BOOST_TEST(v.at("key2") == 2);
|
BOOST_TEST(v.at("key2") == 2);
|
||||||
BOOST_TEST(v.at("key3") == 3);
|
BOOST_TEST(v.at("key3") == 3);
|
||||||
BOOST_TEST(v.at("key4") == 4);
|
BOOST_TEST(v.at("key4") == 4);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_type v1{
|
||||||
|
{"key1", 1},
|
||||||
|
{"key2", 2},
|
||||||
|
{"key3", 3},
|
||||||
|
{"key4", 4}
|
||||||
|
};
|
||||||
|
const auto v = toml::get<std::map<std::string, int>>(std::move(v1));
|
||||||
|
BOOST_TEST(v.at("key1") == 1);
|
||||||
|
BOOST_TEST(v.at("key2") == 2);
|
||||||
|
BOOST_TEST(v.at("key3") == 3);
|
||||||
|
BOOST_TEST(v.at("key4") == 4);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types)
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types)
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ using test_value_types = std::tuple<
|
|||||||
|
|
||||||
namespace test
|
namespace test
|
||||||
{
|
{
|
||||||
|
// to compare result values in BOOST_TEST().
|
||||||
|
//
|
||||||
|
// BOOST_TEST outputs the expected and actual values. Thus it includes the
|
||||||
|
// output stream operator inside. To compile it, we need operator<<s for
|
||||||
|
// containers to compare.
|
||||||
template<typename charT, typename traits, typename T, typename Alloc>
|
template<typename charT, typename traits, typename T, typename Alloc>
|
||||||
std::basic_ostream<charT, traits>&
|
std::basic_ostream<charT, traits>&
|
||||||
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
|
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
|
||||||
@@ -121,6 +126,55 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_exact, value_type, test_value_types)
|
|||||||
}
|
}
|
||||||
#undef TOML11_TEST_GET_OR_EXACT
|
#undef TOML11_TEST_GET_OR_EXACT
|
||||||
|
|
||||||
|
#define TOML11_TEST_GET_OR_MOVE_EXACT(toml_type, init_expr, opt_expr)\
|
||||||
|
{ \
|
||||||
|
using namespace test; \
|
||||||
|
const toml::toml_type init init_expr ; \
|
||||||
|
toml::toml_type opt opt_expr ; \
|
||||||
|
value_type v(init); \
|
||||||
|
BOOST_TEST(init != opt); \
|
||||||
|
const auto opt_ = toml::get_or(std::move(v), std::move(opt));\
|
||||||
|
BOOST_TEST(init == opt_); \
|
||||||
|
} \
|
||||||
|
/**/
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_move, value_type, test_value_types)
|
||||||
|
{
|
||||||
|
TOML11_TEST_GET_OR_MOVE_EXACT(boolean, ( true), (false))
|
||||||
|
TOML11_TEST_GET_OR_MOVE_EXACT(integer, ( 42), ( 54))
|
||||||
|
TOML11_TEST_GET_OR_MOVE_EXACT(floating, ( 3.14), ( 2.71))
|
||||||
|
TOML11_TEST_GET_OR_MOVE_EXACT(string, ("foo"), ("bar"))
|
||||||
|
TOML11_TEST_GET_OR_MOVE_EXACT(local_time, (12, 30, 45), (6, 0, 30))
|
||||||
|
TOML11_TEST_GET_OR_MOVE_EXACT(local_date, (2019, toml::month_t::Apr, 1),
|
||||||
|
(1999, toml::month_t::Jan, 2))
|
||||||
|
TOML11_TEST_GET_OR_MOVE_EXACT(local_datetime,
|
||||||
|
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
|
||||||
|
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
|
||||||
|
)
|
||||||
|
TOML11_TEST_GET_OR_MOVE_EXACT(offset_datetime,
|
||||||
|
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
|
||||||
|
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const typename value_type::array_type init{1,2,3,4,5};
|
||||||
|
typename value_type::array_type opt {6,7,8,9,10};
|
||||||
|
value_type v(init);
|
||||||
|
BOOST_TEST(init != opt);
|
||||||
|
const auto opt_ = toml::get_or(std::move(v), std::move(opt));
|
||||||
|
BOOST_TEST(init == opt_);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
|
||||||
|
typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
|
||||||
|
value_type v(init);
|
||||||
|
BOOST_TEST(init != opt);
|
||||||
|
const auto opt_ = toml::get_or(std::move(v), std::move(opt));
|
||||||
|
BOOST_TEST(init == opt_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef TOML11_TEST_GET_OR_MOVE_EXACT
|
||||||
|
|
||||||
|
|
||||||
#define TOML11_TEST_GET_OR_MODIFY(toml_type, init_expr, opt_expr)\
|
#define TOML11_TEST_GET_OR_MODIFY(toml_type, init_expr, opt_expr)\
|
||||||
{ \
|
{ \
|
||||||
using namespace test; \
|
using namespace test; \
|
||||||
@@ -309,6 +363,13 @@ BOOST_AUTO_TEST_CASE(test_get_or_integer)
|
|||||||
BOOST_TEST(42u == toml::get_or(v1, 0u));
|
BOOST_TEST(42u == toml::get_or(v1, 0u));
|
||||||
BOOST_TEST(0u == toml::get_or(v2, 0u));
|
BOOST_TEST(0u == toml::get_or(v2, 0u));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
toml::value v2(3.14);
|
||||||
|
BOOST_TEST(42u == toml::get_or(std::move(v1), 0u));
|
||||||
|
BOOST_TEST(0u == toml::get_or(std::move(v2), 0u));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_or_floating)
|
BOOST_AUTO_TEST_CASE(test_get_or_floating)
|
||||||
@@ -319,6 +380,12 @@ BOOST_AUTO_TEST_CASE(test_get_or_floating)
|
|||||||
BOOST_TEST(2.71f == toml::get_or(v1, 2.71f));
|
BOOST_TEST(2.71f == toml::get_or(v1, 2.71f));
|
||||||
BOOST_TEST(static_cast<float>(v2.as_floating()) == toml::get_or(v2, 2.71f));
|
BOOST_TEST(static_cast<float>(v2.as_floating()) == toml::get_or(v2, 2.71f));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
toml::value v2(3.14);
|
||||||
|
BOOST_TEST(2.71f == toml::get_or(std::move(v1), 2.71f));
|
||||||
|
BOOST_TEST(static_cast<float>(3.14) == toml::get_or(std::move(v2), 2.71f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_or_string)
|
BOOST_AUTO_TEST_CASE(test_get_or_string)
|
||||||
@@ -345,7 +412,16 @@ BOOST_AUTO_TEST_CASE(test_get_or_string)
|
|||||||
BOOST_TEST("foobar" == toml::get_or(v1, std::move(s1)));
|
BOOST_TEST("foobar" == toml::get_or(v1, std::move(s1)));
|
||||||
BOOST_TEST("bazqux" == toml::get_or(v2, std::move(s1)));
|
BOOST_TEST("bazqux" == toml::get_or(v2, std::move(s1)));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v1("foobar");
|
||||||
|
toml::value v2(42);
|
||||||
|
|
||||||
|
std::string s1("bazqux");
|
||||||
|
const std::string s2("bazqux");
|
||||||
|
|
||||||
|
BOOST_TEST("foobar" == toml::get_or(std::move(v1), s1));
|
||||||
|
BOOST_TEST("bazqux" == toml::get_or(std::move(v2), s1));
|
||||||
|
}
|
||||||
{
|
{
|
||||||
toml::value v1("foobar");
|
toml::value v1("foobar");
|
||||||
toml::value v2(42);
|
toml::value v2(42);
|
||||||
@@ -357,4 +433,20 @@ BOOST_AUTO_TEST_CASE(test_get_or_string)
|
|||||||
BOOST_TEST("foobar" == toml::get_or(v1, lit));
|
BOOST_TEST("foobar" == toml::get_or(v1, lit));
|
||||||
BOOST_TEST("bazqux" == toml::get_or(v2, lit));
|
BOOST_TEST("bazqux" == toml::get_or(v2, lit));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v1("foobar");
|
||||||
|
toml::value v2(42);
|
||||||
|
|
||||||
|
BOOST_TEST("foobar" == toml::get_or(std::move(v1), "bazqux"));
|
||||||
|
BOOST_TEST("bazqux" == toml::get_or(std::move(v2), "bazqux"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1("foobar");
|
||||||
|
toml::value v2(42);
|
||||||
|
|
||||||
|
const char* lit = "bazqux";
|
||||||
|
BOOST_TEST("foobar" == toml::get_or(v1, lit));
|
||||||
|
BOOST_TEST("bazqux" == toml::get_or(v2, lit));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,10 +51,18 @@ BOOST_AUTO_TEST_CASE(test_exponential_valid)
|
|||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "123E-10", "123E-10");
|
TOML11_TEST_LEX_ACCEPT(lex_float, "123E-10", "123E-10");
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-10", "1_2_3E-10");
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-10", "1_2_3E-10");
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-1_0", "1_2_3E-1_0");
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-1_0", "1_2_3E-1_0");
|
||||||
|
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||||
|
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-01", "1_2_3E-01");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-0_1", "1_2_3E-0_1");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_exponential_invalid)
|
BOOST_AUTO_TEST_CASE(test_exponential_invalid)
|
||||||
{
|
{
|
||||||
|
// accept partially
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1E0", "1e1");
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1E0", "1e1");
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1E1e0", "1E1");
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1E1e0", "1E1");
|
||||||
}
|
}
|
||||||
@@ -64,12 +72,26 @@ BOOST_AUTO_TEST_CASE(test_both_valid)
|
|||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e23", "6.02e23");
|
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e23", "6.02e23");
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e+23", "6.02e+23");
|
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e+23", "6.02e+23");
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1.112_650_06e-17", "1.112_650_06e-17");
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1.112_650_06e-17", "1.112_650_06e-17");
|
||||||
|
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||||
|
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e-07", "1.0e-07");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_both_invalid)
|
BOOST_AUTO_TEST_CASE(test_both_invalid)
|
||||||
{
|
{
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1.0", "1e1");
|
|
||||||
TOML11_TEST_LEX_REJECT(lex_float, "01e1.0");
|
TOML11_TEST_LEX_REJECT(lex_float, "01e1.0");
|
||||||
|
// accept partially
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1.0", "1e1");
|
||||||
|
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||||
|
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e_01", "1.0");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e0__1", "1.0e0");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_special_floating_point)
|
BOOST_AUTO_TEST_CASE(test_special_floating_point)
|
||||||
|
|||||||
@@ -45,6 +45,16 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
|
|||||||
b = "baz"
|
b = "baz"
|
||||||
)"_toml;
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(r == v);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value r{
|
||||||
|
{"array_of_tables", toml::array{toml::table{}}}
|
||||||
|
};
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
[[array_of_tables]]
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
BOOST_TEST(r == v);
|
BOOST_TEST(r == v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,13 @@ BOOST_AUTO_TEST_CASE(test_exponential)
|
|||||||
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-1_0", 123e-10);
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-1_0", 123e-10);
|
||||||
TOML11_TEST_PARSE_EQUAL(parse_floating, "+0e0", 0.0);
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+0e0", 0.0);
|
||||||
TOML11_TEST_PARSE_EQUAL(parse_floating, "-0e0", -0.0);
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-0e0", -0.0);
|
||||||
|
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||||
|
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-01", 123e-1);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-0_1", 123e-1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_exponential_value)
|
BOOST_AUTO_TEST_CASE(test_exponential_value)
|
||||||
@@ -90,6 +97,13 @@ BOOST_AUTO_TEST_CASE(test_exponential_value)
|
|||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-1_0", value(123e-10));
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-1_0", value(123e-10));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+0e0", value( 0.0));
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+0e0", value( 0.0));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0e0", value(-0.0));
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0e0", value(-0.0));
|
||||||
|
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||||
|
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-01", value(123e-1));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-0_1", value(123e-1));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
BOOST_AUTO_TEST_CASE(test_fe)
|
BOOST_AUTO_TEST_CASE(test_fe)
|
||||||
{
|
{
|
||||||
@@ -102,6 +116,12 @@ BOOST_AUTO_TEST_CASE(test_fe_vaule)
|
|||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e23", value(6.02e23));
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e23", value(6.02e23));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e+23", value(6.02e23));
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e+23", value(6.02e23));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.112_650_06e-17", value(1.11265006e-17));
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.112_650_06e-17", value(1.11265006e-17));
|
||||||
|
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
|
||||||
|
// toml-lang/toml master permits leading 0s in exp part (unreleased)
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "3.141_5e-01", value(3.1415e-1));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_inf)
|
BOOST_AUTO_TEST_CASE(test_inf)
|
||||||
|
|||||||
@@ -11,6 +11,39 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
template<typename Comment,
|
||||||
|
template<typename ...> class Table,
|
||||||
|
template<typename ...> class Array>
|
||||||
|
bool has_comment_inside(const toml::basic_value<Comment, Table, Array>& v)
|
||||||
|
{
|
||||||
|
if(!v.comments().empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// v itself does not have a comment.
|
||||||
|
if(v.is_array())
|
||||||
|
{
|
||||||
|
for(const auto& x : v.as_array())
|
||||||
|
{
|
||||||
|
if(has_comment_inside(x))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(v.is_table())
|
||||||
|
{
|
||||||
|
for(const auto& x : v.as_table())
|
||||||
|
{
|
||||||
|
if(has_comment_inside(x.second))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_example)
|
BOOST_AUTO_TEST_CASE(test_example)
|
||||||
{
|
{
|
||||||
const auto data = toml::parse("toml/tests/example.toml");
|
const auto data = toml::parse("toml/tests/example.toml");
|
||||||
@@ -37,12 +70,12 @@ BOOST_AUTO_TEST_CASE(test_example_map_dq)
|
|||||||
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
|
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
|
||||||
"toml/tests/example.toml");
|
"toml/tests/example.toml");
|
||||||
{
|
{
|
||||||
std::ofstream ofs("tmp1.toml");
|
std::ofstream ofs("tmp1_map_dq.toml");
|
||||||
ofs << std::setw(80) << data;
|
ofs << std::setw(80) << data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
|
auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
|
||||||
"tmp1.toml");
|
"tmp1_map_dq.toml");
|
||||||
{
|
{
|
||||||
auto& owner = toml::find(serialized, "owner");
|
auto& owner = toml::find(serialized, "owner");
|
||||||
auto& bio = toml::find<std::string>(owner, "bio");
|
auto& bio = toml::find<std::string>(owner, "bio");
|
||||||
@@ -80,17 +113,46 @@ BOOST_AUTO_TEST_CASE(test_example_with_comment)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_example_with_comment_nocomment)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const auto data = toml::parse<toml::preserve_comments>("toml/tests/example.toml");
|
||||||
|
{
|
||||||
|
std::ofstream ofs("tmp1_com_nocomment.toml");
|
||||||
|
ofs << std::setw(80) << toml::nocomment << data;
|
||||||
|
}
|
||||||
|
const auto serialized = toml::parse<toml::preserve_comments>("tmp1_com_nocomment.toml");
|
||||||
|
// check no comment exist
|
||||||
|
BOOST_TEST(!has_comment_inside(serialized));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto data_nocomment = toml::parse("toml/tests/example.toml");
|
||||||
|
auto serialized = toml::parse("tmp1_com_nocomment.toml");
|
||||||
|
{
|
||||||
|
auto& owner = toml::find(serialized, "owner");
|
||||||
|
auto& bio = toml::find<std::string>(owner, "bio");
|
||||||
|
const auto CR = std::find(bio.begin(), bio.end(), '\r');
|
||||||
|
if(CR != bio.end())
|
||||||
|
{
|
||||||
|
bio.erase(CR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check collectly serialized
|
||||||
|
BOOST_TEST(data_nocomment == serialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq)
|
BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq)
|
||||||
{
|
{
|
||||||
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
|
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
|
||||||
"toml/tests/example.toml");
|
"toml/tests/example.toml");
|
||||||
{
|
{
|
||||||
std::ofstream ofs("tmp1_com.toml");
|
std::ofstream ofs("tmp1_com_map_dq.toml");
|
||||||
ofs << std::setw(80) << data;
|
ofs << std::setw(80) << data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
|
auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
|
||||||
"tmp1_com.toml");
|
"tmp1_com_map_dq.toml");
|
||||||
{
|
{
|
||||||
auto& owner = toml::find(serialized, "owner");
|
auto& owner = toml::find(serialized, "owner");
|
||||||
auto& bio = toml::find<std::string>(owner, "bio");
|
auto& bio = toml::find<std::string>(owner, "bio");
|
||||||
@@ -102,11 +164,38 @@ BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq)
|
|||||||
}
|
}
|
||||||
BOOST_TEST(data == serialized);
|
BOOST_TEST(data == serialized);
|
||||||
{
|
{
|
||||||
std::ofstream ofs("tmp1_com1.toml");
|
std::ofstream ofs("tmp1_com1_map_dq.toml");
|
||||||
ofs << std::setw(80) << serialized;
|
ofs << std::setw(80) << serialized;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq_nocomment)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>("toml/tests/example.toml");
|
||||||
|
{
|
||||||
|
std::ofstream ofs("tmp1_com_map_dq_nocomment.toml");
|
||||||
|
ofs << std::setw(80) << toml::nocomment << data;
|
||||||
|
}
|
||||||
|
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>("tmp1_com_map_dq_nocomment.toml");
|
||||||
|
BOOST_TEST(!has_comment_inside(serialized));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto data_nocomment = toml::parse("toml/tests/example.toml");
|
||||||
|
auto serialized = toml::parse("tmp1_com_map_dq_nocomment.toml");
|
||||||
|
{
|
||||||
|
auto& owner = toml::find(serialized, "owner");
|
||||||
|
auto& bio = toml::find<std::string>(owner, "bio");
|
||||||
|
const auto CR = std::find(bio.begin(), bio.end(), '\r');
|
||||||
|
if(CR != bio.end())
|
||||||
|
{
|
||||||
|
bio.erase(CR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_TEST(data_nocomment == serialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_fruit)
|
BOOST_AUTO_TEST_CASE(test_fruit)
|
||||||
{
|
{
|
||||||
const auto data = toml::parse("toml/tests/fruit.toml");
|
const auto data = toml::parse("toml/tests/fruit.toml");
|
||||||
@@ -194,3 +283,23 @@ BOOST_AUTO_TEST_CASE(test_hard_example_with_comment)
|
|||||||
}
|
}
|
||||||
BOOST_TEST(data == serialized);
|
BOOST_TEST(data == serialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_format_key)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::key key("normal_bare-key");
|
||||||
|
BOOST_TEST("normal_bare-key" == toml::format_key(key));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::key key("key.include.dots");
|
||||||
|
BOOST_TEST("\"key.include.dots\"" == toml::format_key(key));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::key key("key-include-unicode-\xE3\x81\x82");
|
||||||
|
BOOST_TEST("\"key-include-unicode-\xE3\x81\x82\"" == toml::format_key(key));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::key key("special-chars-\\-\"-\b-\f-\r-\n-\t");
|
||||||
|
BOOST_TEST("\"special-chars-\\\\-\\\"-\\b-\\f-\\r-\\n-\\t\"" == toml::format_key(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
113
tests/test_string.cpp
Normal file
113
tests/test_string.cpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_string"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <toml.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_basic_string)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::string str("basic string");
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << str;
|
||||||
|
BOOST_TEST(oss.str() == "\"basic string\"");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string s1 ("basic string");
|
||||||
|
const toml::string str(s1);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << str;
|
||||||
|
BOOST_TEST(oss.str() == "\"basic string\"");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::string str("basic string", toml::string_t::basic);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << str;
|
||||||
|
BOOST_TEST(oss.str() == "\"basic string\"");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string s1 ("basic string");
|
||||||
|
const toml::string str(s1, toml::string_t::basic);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << str;
|
||||||
|
BOOST_TEST(oss.str() == "\"basic string\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_basic_ml_string)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::string str("basic\nstring");
|
||||||
|
std::ostringstream oss1;
|
||||||
|
oss1 << str;
|
||||||
|
std::ostringstream oss2;
|
||||||
|
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
|
||||||
|
BOOST_TEST(oss1.str() == oss2.str());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string s1 ("basic\nstring");
|
||||||
|
const toml::string str(s1);
|
||||||
|
std::ostringstream oss1;
|
||||||
|
oss1 << str;
|
||||||
|
std::ostringstream oss2;
|
||||||
|
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
|
||||||
|
BOOST_TEST(oss1.str() == oss2.str());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::string str("basic\nstring", toml::string_t::basic);
|
||||||
|
std::ostringstream oss1;
|
||||||
|
oss1 << str;
|
||||||
|
std::ostringstream oss2;
|
||||||
|
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
|
||||||
|
BOOST_TEST(oss1.str() == oss2.str());
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string s1 ("basic\nstring");
|
||||||
|
const toml::string str(s1, toml::string_t::basic);
|
||||||
|
std::ostringstream oss1;
|
||||||
|
oss1 << str;
|
||||||
|
std::ostringstream oss2;
|
||||||
|
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
|
||||||
|
BOOST_TEST(oss1.str() == oss2.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_literal_string)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::string str("literal string", toml::string_t::literal);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << str;
|
||||||
|
BOOST_TEST(oss.str() == "'literal string'");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string s1 ("literal string");
|
||||||
|
const toml::string str(s1, toml::string_t::literal);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << str;
|
||||||
|
BOOST_TEST(oss.str() == "'literal string'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_literal_ml_string)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::string str("literal\nstring", toml::string_t::literal);
|
||||||
|
std::ostringstream oss1;
|
||||||
|
oss1 << str;
|
||||||
|
std::ostringstream oss2;
|
||||||
|
oss2 << "'''\nliteral\nstring'''";
|
||||||
|
BOOST_TEST(oss1.str() == oss2.str());
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string s1 ("literal\nstring");
|
||||||
|
const toml::string str(s1, toml::string_t::literal);
|
||||||
|
std::ostringstream oss1;
|
||||||
|
oss1 << str;
|
||||||
|
std::ostringstream oss2;
|
||||||
|
oss2 << "'''\nliteral\nstring'''";
|
||||||
|
BOOST_TEST(oss1.str() == oss2.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -905,3 +905,32 @@ BOOST_AUTO_TEST_CASE(test_value_empty)
|
|||||||
BOOST_CHECK_THROW(v1.as_array(), toml::type_error);
|
BOOST_CHECK_THROW(v1.as_array(), toml::type_error);
|
||||||
BOOST_CHECK_THROW(v1.as_table(), toml::type_error);
|
BOOST_CHECK_THROW(v1.as_table(), toml::type_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_at)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}};
|
||||||
|
|
||||||
|
BOOST_TEST(v1.at("foo").as_integer() == 42);
|
||||||
|
BOOST_TEST(v1.at("bar").as_floating() == 3.14);
|
||||||
|
BOOST_TEST(v1.at("baz").as_string() == "qux");
|
||||||
|
|
||||||
|
BOOST_CHECK_THROW(v1.at(0), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.at("quux"), std::out_of_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
toml::value v1{1,2,3,4,5};
|
||||||
|
|
||||||
|
BOOST_TEST(v1.at(0).as_integer() == 1);
|
||||||
|
BOOST_TEST(v1.at(1).as_integer() == 2);
|
||||||
|
BOOST_TEST(v1.at(2).as_integer() == 3);
|
||||||
|
BOOST_TEST(v1.at(3).as_integer() == 4);
|
||||||
|
BOOST_TEST(v1.at(4).as_integer() == 5);
|
||||||
|
|
||||||
|
BOOST_CHECK_THROW(v1.at("foo"), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.at(5), std::out_of_range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -162,12 +162,15 @@ struct preserve_comments
|
|||||||
const_reverse_iterator crbegin() const noexcept {return comments.crbegin();}
|
const_reverse_iterator crbegin() const noexcept {return comments.crbegin();}
|
||||||
const_reverse_iterator crend() const noexcept {return comments.crend();}
|
const_reverse_iterator crend() const noexcept {return comments.crend();}
|
||||||
|
|
||||||
friend bool operator==(const preserve_comments& lhs, const preserve_comments& rhs);
|
friend bool operator==(const preserve_comments&, const preserve_comments&);
|
||||||
friend bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs);
|
friend bool operator!=(const preserve_comments&, const preserve_comments&);
|
||||||
friend bool operator< (const preserve_comments& lhs, const preserve_comments& rhs);
|
friend bool operator< (const preserve_comments&, const preserve_comments&);
|
||||||
friend bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs);
|
friend bool operator<=(const preserve_comments&, const preserve_comments&);
|
||||||
friend bool operator> (const preserve_comments& lhs, const preserve_comments& rhs);
|
friend bool operator> (const preserve_comments&, const preserve_comments&);
|
||||||
friend bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs);
|
friend bool operator>=(const preserve_comments&, const preserve_comments&);
|
||||||
|
|
||||||
|
friend void swap(preserve_comments&, std::vector<std::string>&);
|
||||||
|
friend void swap(std::vector<std::string>&, preserve_comments&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -186,6 +189,27 @@ inline void swap(preserve_comments& lhs, preserve_comments& rhs)
|
|||||||
lhs.swap(rhs);
|
lhs.swap(rhs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
inline void swap(preserve_comments& lhs, std::vector<std::string>& rhs)
|
||||||
|
{
|
||||||
|
lhs.comments.swap(rhs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inline void swap(std::vector<std::string>& lhs, preserve_comments& rhs)
|
||||||
|
{
|
||||||
|
lhs.swap(rhs.comments);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, const preserve_comments& com)
|
||||||
|
{
|
||||||
|
for(const auto& c : com)
|
||||||
|
{
|
||||||
|
os << '#' << c << '\n';
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@@ -381,5 +405,12 @@ inline bool operator>=(const discard_comments&, const discard_comments&) noexcep
|
|||||||
|
|
||||||
inline void swap(const discard_comments&, const discard_comments&) noexcept {return;}
|
inline void swap(const discard_comments&, const discard_comments&) noexcept {return;}
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, const discard_comments&)
|
||||||
|
{
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
} // toml11
|
} // toml11
|
||||||
#endif// TOML11_COMMENTS_HPP
|
#endif// TOML11_COMMENTS_HPP
|
||||||
|
|||||||
218
toml/get.hpp
218
toml/get.hpp
@@ -31,10 +31,10 @@ get(const basic_value<C, M, V>& v)
|
|||||||
|
|
||||||
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>
|
||||||
detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> &&
|
detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>
|
||||||
get(basic_value<C, M, V>&& v)
|
get(basic_value<C, M, V>&& v)
|
||||||
{
|
{
|
||||||
return std::move(v).template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>();
|
return T(std::move(v).template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -58,10 +58,10 @@ get(const basic_value<C, M, V>& v)
|
|||||||
|
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T> &&
|
inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T>
|
||||||
get(basic_value<C, M, V>&& v)
|
get(basic_value<C, M, V>&& v)
|
||||||
{
|
{
|
||||||
return std::move(v);
|
return basic_value<C, M, V>(std::move(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -90,7 +90,7 @@ inline detail::enable_if_t<detail::conjunction<
|
|||||||
>::value, T>
|
>::value, T>
|
||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
return static_cast<T>(v.template cast<value_t::integer>());
|
return static_cast<T>(v.as_integer());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -105,7 +105,7 @@ inline detail::enable_if_t<detail::conjunction<
|
|||||||
>::value, T>
|
>::value, T>
|
||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
return static_cast<T>(v.template cast<value_t::floating>());
|
return static_cast<T>(v.as_floating());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -117,7 +117,7 @@ template<typename T, typename C,
|
|||||||
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
|
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
|
||||||
get(basic_value<C, M, V>& v)
|
get(basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
return v.template cast<value_t::string>().str;
|
return v.as_string().str;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
@@ -125,15 +125,15 @@ template<typename T, typename C,
|
|||||||
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
|
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
|
||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
return v.template cast<value_t::string>().str;
|
return v.as_string().str;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
|
inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>
|
||||||
get(basic_value<C, M, V>&& v)
|
get(basic_value<C, M, V>&& v)
|
||||||
{
|
{
|
||||||
return std::move(v.template cast<value_t::string>().str);
|
return std::string(std::move(v.as_string().str));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -145,7 +145,7 @@ template<typename T, typename C,
|
|||||||
inline detail::enable_if_t<std::is_same<T, std::string_view>::value, std::string_view>
|
inline detail::enable_if_t<std::is_same<T, std::string_view>::value, std::string_view>
|
||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
return std::string_view(v.template cast<value_t::string>().str);
|
return std::string_view(v.as_string().str);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ inline detail::enable_if_t<detail::is_chrono_duration<T>::value, T>
|
|||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
return std::chrono::duration_cast<T>(
|
return std::chrono::duration_cast<T>(
|
||||||
std::chrono::nanoseconds(v.template cast<value_t::local_time>()));
|
std::chrono::nanoseconds(v.as_local_time()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -174,18 +174,15 @@ get(const basic_value<C, M, V>& v)
|
|||||||
{
|
{
|
||||||
case value_t::local_date:
|
case value_t::local_date:
|
||||||
{
|
{
|
||||||
return std::chrono::system_clock::time_point(
|
return std::chrono::system_clock::time_point(v.as_local_date());
|
||||||
v.template cast<value_t::local_date>());
|
|
||||||
}
|
}
|
||||||
case value_t::local_datetime:
|
case value_t::local_datetime:
|
||||||
{
|
{
|
||||||
return std::chrono::system_clock::time_point(
|
return std::chrono::system_clock::time_point(v.as_local_datetime());
|
||||||
v.template cast<value_t::local_datetime>());
|
|
||||||
}
|
}
|
||||||
case value_t::offset_datetime:
|
case value_t::offset_datetime:
|
||||||
{
|
{
|
||||||
return std::chrono::system_clock::time_point(
|
return std::chrono::system_clock::time_point(v.as_offset_datetime());
|
||||||
v.template cast<value_t::offset_datetime>());
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@@ -259,7 +256,7 @@ get(const basic_value<C, M, V>&);
|
|||||||
// toml::from<T>::from_toml(v)
|
// toml::from<T>::from_toml(v)
|
||||||
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,
|
||||||
std::size_t S = sizeof(::toml::into<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>&);
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -276,7 +273,7 @@ detail::enable_if_t<detail::conjunction<
|
|||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
using value_type = typename T::value_type;
|
using value_type = typename T::value_type;
|
||||||
const auto& ar = v.template cast<value_t::array>();
|
const auto& ar = v.as_array();
|
||||||
T container;
|
T container;
|
||||||
container.resize(ar.size());
|
container.resize(ar.size());
|
||||||
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
||||||
@@ -298,7 +295,7 @@ detail::enable_if_t<detail::conjunction<
|
|||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
using value_type = typename T::value_type;
|
using value_type = typename T::value_type;
|
||||||
const auto& ar = v.template cast<value_t::array>();
|
const auto& ar = v.as_array();
|
||||||
|
|
||||||
T container;
|
T container;
|
||||||
if(ar.size() != container.size())
|
if(ar.size() != container.size())
|
||||||
@@ -325,7 +322,7 @@ get(const basic_value<C, M, V>& v)
|
|||||||
using first_type = typename T::first_type;
|
using first_type = typename T::first_type;
|
||||||
using second_type = typename T::second_type;
|
using second_type = typename T::second_type;
|
||||||
|
|
||||||
const auto& ar = v.template cast<value_t::array>();
|
const auto& ar = v.as_array();
|
||||||
if(ar.size() != 2)
|
if(ar.size() != 2)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
@@ -356,7 +353,7 @@ template<typename T, typename C,
|
|||||||
detail::enable_if_t<detail::is_std_tuple<T>::value, T>
|
detail::enable_if_t<detail::is_std_tuple<T>::value, T>
|
||||||
get(const basic_value<C, M, V>& v)
|
get(const basic_value<C, M, V>& v)
|
||||||
{
|
{
|
||||||
const auto& ar = v.template cast<value_t::array>();
|
const auto& ar = v.as_array();
|
||||||
if(ar.size() != std::tuple_size<T>::value)
|
if(ar.size() != std::tuple_size<T>::value)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
@@ -388,7 +385,7 @@ get(const basic_value<C, M, V>& v)
|
|||||||
"toml::get only supports map type of which key_type is "
|
"toml::get only supports map type of which key_type is "
|
||||||
"convertible from std::string.");
|
"convertible from std::string.");
|
||||||
T map;
|
T map;
|
||||||
for(const auto& kv : v.template cast<value_t::table>())
|
for(const auto& kv : v.as_table())
|
||||||
{
|
{
|
||||||
map[key_type(kv.first)] = ::toml::get<mapped_type>(kv.second);
|
map[key_type(kv.first)] = ::toml::get<mapped_type>(kv.second);
|
||||||
}
|
}
|
||||||
@@ -421,7 +418,7 @@ T get(const basic_value<C, M, V>& v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// find and get
|
// find
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// these overloads do not require to set T. and returns value itself.
|
// these overloads do not require to set T. and returns value itself.
|
||||||
@@ -429,7 +426,7 @@ template<typename C,
|
|||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
basic_value<C, M, V> const& find(const basic_value<C, M, V>& v, const key& ky)
|
basic_value<C, M, V> const& find(const basic_value<C, M, V>& v, const key& ky)
|
||||||
{
|
{
|
||||||
const auto& tab = v.template cast<value_t::table>();
|
const auto& tab = v.as_table();
|
||||||
if(tab.count(ky) == 0)
|
if(tab.count(ky) == 0)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
@@ -443,7 +440,7 @@ template<typename C,
|
|||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
basic_value<C, M, V>& find(basic_value<C, M, V>& v, const key& ky)
|
basic_value<C, M, V>& find(basic_value<C, M, V>& v, const key& ky)
|
||||||
{
|
{
|
||||||
auto& tab = v.template cast<value_t::table>();
|
auto& tab = v.as_table();
|
||||||
if(tab.count(ky) == 0)
|
if(tab.count(ky) == 0)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
@@ -455,9 +452,9 @@ basic_value<C, M, V>& find(basic_value<C, M, V>& v, const key& ky)
|
|||||||
}
|
}
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
basic_value<C, M, V>&& find(basic_value<C, M, V>&& v, const key& ky)
|
basic_value<C, M, V> find(basic_value<C, M, V>&& v, const key& ky)
|
||||||
{
|
{
|
||||||
auto& tab = v.template cast<value_t::table>();
|
typename basic_value<C, M, V>::table_type tab = std::move(v).as_table();
|
||||||
if(tab.count(ky) == 0)
|
if(tab.count(ky) == 0)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
@@ -465,7 +462,7 @@ basic_value<C, M, V>&& find(basic_value<C, M, V>&& v, const key& ky)
|
|||||||
{std::addressof(detail::get_region(v)), "in this table"}
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return std::move(tab.at(ky));
|
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -476,7 +473,7 @@ template<typename T, typename C,
|
|||||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))
|
||||||
find(const basic_value<C, M, V>& v, const key& ky)
|
find(const basic_value<C, M, V>& v, const key& ky)
|
||||||
{
|
{
|
||||||
const auto& tab = v.template cast<value_t::table>();
|
const auto& tab = v.as_table();
|
||||||
if(tab.count(ky) == 0)
|
if(tab.count(ky) == 0)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
@@ -492,7 +489,7 @@ template<typename T, typename C,
|
|||||||
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 key& ky)
|
find(basic_value<C, M, V>& v, const key& ky)
|
||||||
{
|
{
|
||||||
auto& tab = v.template cast<value_t::table>();
|
auto& tab = v.as_table();
|
||||||
if(tab.count(ky) == 0)
|
if(tab.count(ky) == 0)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
@@ -508,7 +505,7 @@ template<typename T, typename C,
|
|||||||
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 key& ky)
|
find(basic_value<C, M, V>&& v, const key& ky)
|
||||||
{
|
{
|
||||||
auto& tab = v.template cast<value_t::table>();
|
typename basic_value<C, M, V>::table_type tab = std::move(v).as_table();
|
||||||
if(tab.count(ky) == 0)
|
if(tab.count(ky) == 0)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
@@ -541,7 +538,7 @@ find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... 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 ... Ts>
|
||||||
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, const ::toml::key& ky, Ts&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
||||||
@@ -575,6 +572,28 @@ find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// get_or(value, fallback)
|
// get_or(value, fallback)
|
||||||
|
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> const&
|
||||||
|
get_or(const basic_value<C, M, V>& v, const basic_value<C, M, V>&)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>&
|
||||||
|
get_or(basic_value<C, M, V>& v, basic_value<C, M, V>&)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>
|
||||||
|
get_or(basic_value<C, M, V>&& v, basic_value<C, M, V>&&)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// specialization for the exact toml types (return type becomes lvalue ref)
|
// specialization for the exact toml types (return type becomes lvalue ref)
|
||||||
|
|
||||||
@@ -586,8 +605,7 @@ get_or(const basic_value<C, M, V>& v, const T& opt)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return get<typename std::remove_cv<
|
return get<detail::remove_cvref_t<T>>(v);
|
||||||
typename std::remove_reference<T>::type>::type>(v);
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@@ -602,8 +620,7 @@ get_or(basic_value<C, M, V>& v, T& opt)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return get<typename std::remove_cv<
|
return get<detail::remove_cvref_t<T>>(v);
|
||||||
typename std::remove_reference<T>::type>::type>(v);
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@@ -612,18 +629,17 @@ get_or(basic_value<C, M, V>& v, T& opt)
|
|||||||
}
|
}
|
||||||
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>
|
||||||
detail::enable_if_t<
|
detail::enable_if_t<detail::is_exact_toml_type<detail::remove_cvref_t<T>,
|
||||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&&
|
basic_value<C, M, V>>::value, detail::remove_cvref_t<T>>
|
||||||
get_or(basic_value<C, M, V>&& v, T&& opt)
|
get_or(basic_value<C, M, V>&& v, T&& opt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return get<typename std::remove_cv<
|
return get<detail::remove_cvref_t<T>>(std::move(v));
|
||||||
typename std::remove_reference<T>::type>::type>(v);
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return opt;
|
return detail::remove_cvref_t<T>(std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,14 +648,13 @@ get_or(basic_value<C, M, V>&& v, T&& opt)
|
|||||||
|
|
||||||
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>
|
||||||
detail::enable_if_t<std::is_same<
|
detail::enable_if_t<std::is_same<detail::remove_cvref_t<T>, std::string>::value,
|
||||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
|
std::string> const&
|
||||||
std::string>::value, std::string> const&
|
get_or(const basic_value<C, M, V>& v, const T& opt)
|
||||||
get_or(const basic_value<C, M, V>& v, T&& opt)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return v.template cast<value_t::string>().str;
|
return v.as_string().str;
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@@ -653,7 +668,7 @@ get_or(basic_value<C, M, V>& v, T& opt)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return v.template cast<value_t::string>().str;
|
return v.as_string().str;
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@@ -662,18 +677,17 @@ get_or(basic_value<C, M, V>& v, T& opt)
|
|||||||
}
|
}
|
||||||
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>
|
||||||
detail::enable_if_t<std::is_same<
|
detail::enable_if_t<
|
||||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
|
std::is_same<detail::remove_cvref_t<T>, std::string>::value, std::string>
|
||||||
std::string>::value, std::string>
|
|
||||||
get_or(basic_value<C, M, V>&& v, T&& opt)
|
get_or(basic_value<C, M, V>&& v, T&& opt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return std::move(v.template cast<value_t::string>().str);
|
return std::move(v.as_string().str);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return std::forward<T>(opt);
|
return std::string(std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,11 +702,11 @@ get_or(const basic_value<C, M, V>& v, T&& opt)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return std::move(v.template cast<value_t::string>().str);
|
return std::move(v.as_string().str);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return std::string(opt);
|
return std::string(std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,30 +716,61 @@ get_or(const basic_value<C, M, V>& v, T&& opt)
|
|||||||
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>
|
||||||
detail::enable_if_t<detail::conjunction<
|
detail::enable_if_t<detail::conjunction<
|
||||||
detail::negation<detail::is_exact_toml_type<
|
detail::negation<detail::is_exact_toml_type<detail::remove_cvref_t<T>,
|
||||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
|
|
||||||
basic_value<C, M, V>>>,
|
basic_value<C, M, V>>>,
|
||||||
detail::negation<std::is_same<std::string,
|
detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>,
|
||||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
|
||||||
detail::negation<detail::is_string_literal<
|
detail::negation<detail::is_string_literal<
|
||||||
typename std::remove_reference<T>::type>>
|
typename std::remove_reference<T>::type>>
|
||||||
>::value, typename std::remove_reference<T>::type>
|
>::value, detail::remove_cvref_t<T>>
|
||||||
get_or(const basic_value<C, M, V>& v, T&& opt)
|
get_or(const basic_value<C, M, V>& v, T&& opt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return get<typename std::remove_cv<
|
return get<detail::remove_cvref_t<T>>(v);
|
||||||
typename std::remove_reference<T>::type>::type>(v);
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return std::forward<T>(opt);
|
return detail::remove_cvref_t<T>(std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// find_or(value, key, fallback)
|
// find_or(value, key, fallback)
|
||||||
|
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> const&
|
||||||
|
find_or(const basic_value<C, M, V>& v, const key& ky,
|
||||||
|
const basic_value<C, M, V>& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
const auto& tab = v.as_table();
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return tab.at(ky);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>&
|
||||||
|
find_or(basic_value<C, M, V>& v, const toml::key& ky, basic_value<C, M, V>& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
auto& tab = v.as_table();
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return tab.at(ky);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>
|
||||||
|
find_or(basic_value<C, M, V>&& v, const toml::key& ky, basic_value<C, M, V>&& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
auto tab = std::move(v).as_table();
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// exact types (return type can be a reference)
|
// exact types (return type can be a reference)
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
@@ -749,19 +794,20 @@ find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
|
|||||||
if(!v.is_table()) {return opt;}
|
if(!v.is_table()) {return opt;}
|
||||||
auto& tab = v.as_table();
|
auto& tab = v.as_table();
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
return get_or(tab[ky], opt);
|
return get_or(tab.at(ky), opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
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>
|
||||||
detail::enable_if_t<
|
detail::enable_if_t<
|
||||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&&
|
detail::is_exact_toml_type<T, basic_value<C, M, V>>::value,
|
||||||
|
detail::remove_cvref_t<T>>
|
||||||
find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
|
find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
|
||||||
{
|
{
|
||||||
if(!v.is_table()) {return opt;}
|
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||||
auto tab = std::move(v).as_table();
|
auto tab = std::move(v).as_table();
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||||
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
return get_or(std::move(tab.at(ky)), std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -807,7 +853,7 @@ detail::enable_if_t<
|
|||||||
std::string>
|
std::string>
|
||||||
find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
||||||
{
|
{
|
||||||
if(!v.is_table()) {return opt;}
|
if(!v.is_table()) {return std::string(opt);}
|
||||||
const auto& tab = v.as_table();
|
const auto& tab = v.as_table();
|
||||||
if(tab.count(ky) == 0) {return std::string(opt);}
|
if(tab.count(ky) == 0) {return std::string(opt);}
|
||||||
return get_or(tab.at(ky), std::forward<T>(opt));
|
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
@@ -818,19 +864,20 @@ find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
|||||||
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>
|
||||||
detail::enable_if_t<detail::conjunction<
|
detail::enable_if_t<detail::conjunction<
|
||||||
|
// T is not an exact toml type
|
||||||
detail::negation<detail::is_exact_toml_type<
|
detail::negation<detail::is_exact_toml_type<
|
||||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
|
detail::remove_cvref_t<T>, basic_value<C, M, V>>>,
|
||||||
basic_value<C, M, V>>>,
|
// T is not std::string
|
||||||
detail::negation<std::is_same<std::string,
|
detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>,
|
||||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
// T is not a string literal
|
||||||
detail::negation<detail::is_string_literal<
|
detail::negation<detail::is_string_literal<
|
||||||
typename std::remove_reference<T>::type>>
|
typename std::remove_reference<T>::type>>
|
||||||
>::value, T>
|
>::value, detail::remove_cvref_t<T>>
|
||||||
find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
|
||||||
{
|
{
|
||||||
if(!v.is_table()) {return opt;}
|
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||||
const auto& tab = v.as_table();
|
const auto& tab = v.as_table();
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||||
return get_or(tab.at(ky), std::forward<T>(opt));
|
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,21 +911,6 @@ expect(const basic_value<C, M, V>& v, const toml::key& k) noexcept
|
|||||||
return err(e.what());
|
return err(e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename T, typename Table>
|
|
||||||
detail::enable_if_t<detail::conjunction<
|
|
||||||
detail::is_map<Table>, detail::is_basic_value<typename Table::mapped_type>
|
|
||||||
>::value, result<T, std::string>>
|
|
||||||
expect(const Table& t, const toml::key& k,
|
|
||||||
std::string tablename = "unknown table") noexcept
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return ok(find<T>(t, k, std::move(tablename)));
|
|
||||||
}
|
|
||||||
catch(const std::exception& e)
|
|
||||||
{
|
|
||||||
return err(e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // toml
|
} // toml
|
||||||
#endif// TOML11_GET
|
#endif// TOML11_GET
|
||||||
|
|||||||
@@ -63,12 +63,22 @@ using lex_integer = either<lex_bin_int, lex_oct_int, lex_hex_int, lex_dec_int>;
|
|||||||
using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
|
using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
|
||||||
using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
|
using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
|
||||||
using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
|
using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
|
||||||
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>, lex_dec_int>;
|
|
||||||
|
|
||||||
using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
|
using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
|
||||||
sequence<lex_underscore, lex_digit>>, unlimited>>;
|
sequence<lex_underscore, lex_digit>>, unlimited>>;
|
||||||
|
|
||||||
using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;
|
using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;
|
||||||
|
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
// use toml-lang/toml HEAD
|
||||||
|
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>,
|
||||||
|
maybe<lex_sign>, lex_zero_prefixable_int>;
|
||||||
|
#else
|
||||||
|
// strictly TOML v0.5.0
|
||||||
|
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>,
|
||||||
|
lex_dec_int>;
|
||||||
|
#endif
|
||||||
|
|
||||||
using lex_float = either<lex_special_float,
|
using lex_float = either<lex_special_float,
|
||||||
sequence<lex_dec_int, either<lex_exponent_part,
|
sequence<lex_dec_int, either<lex_exponent_part,
|
||||||
sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;
|
sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;
|
||||||
@@ -115,9 +125,17 @@ using lex_local_time = lex_partial_time;
|
|||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
||||||
using lex_quotation_mark = character<'"'>;
|
using lex_quotation_mark = character<'"'>;
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09 (tab)
|
||||||
|
in_range<0x0a, 0x1F>, // is allowed
|
||||||
|
character<0x22>, character<0x5C>,
|
||||||
|
character<0x7F>>>;
|
||||||
|
#else
|
||||||
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
|
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
|
||||||
character<0x22>, character<0x5C>,
|
character<0x22>, character<0x5C>,
|
||||||
character<0x7F>>>;
|
character<0x7F>>>;
|
||||||
|
|
||||||
|
#endif
|
||||||
using lex_escape = character<'\\'>;
|
using lex_escape = character<'\\'>;
|
||||||
using lex_escape_unicode_short = sequence<character<'u'>,
|
using lex_escape_unicode_short = sequence<character<'u'>,
|
||||||
repeat<lex_hex_dig, exactly<4>>>;
|
repeat<lex_hex_dig, exactly<4>>>;
|
||||||
@@ -137,10 +155,18 @@ using lex_basic_string = sequence<lex_quotation_mark,
|
|||||||
lex_quotation_mark>;
|
lex_quotation_mark>;
|
||||||
|
|
||||||
using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
|
using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
|
||||||
using lex_ml_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
using lex_ml_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09
|
||||||
|
in_range<0x0a, 0x1F>, // is tab
|
||||||
character<0x5C>,
|
character<0x5C>,
|
||||||
character<0x7F>,
|
character<0x7F>,
|
||||||
lex_ml_basic_string_delim>>;
|
lex_ml_basic_string_delim>>;
|
||||||
|
#else // TOML v0.5.0
|
||||||
|
using lex_ml_basic_unescaped = exclude<either<in_range<0x00,0x1F>,
|
||||||
|
character<0x5C>,
|
||||||
|
character<0x7F>,
|
||||||
|
lex_ml_basic_string_delim>>;
|
||||||
|
#endif
|
||||||
|
|
||||||
using lex_ml_basic_escaped_newline = sequence<
|
using lex_ml_basic_escaped_newline = sequence<
|
||||||
lex_escape, maybe<lex_ws>, lex_newline,
|
lex_escape, maybe<lex_ws>, lex_newline,
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
#include "lexer.hpp"
|
#include "lexer.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include "value.hpp"
|
#include "value.hpp"
|
||||||
#include <iostream>
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
@@ -1750,6 +1751,7 @@ parse_ml_table(location<Container>& loc)
|
|||||||
using skip_line = repeat<
|
using skip_line = repeat<
|
||||||
sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
|
sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
|
||||||
skip_line::invoke(loc);
|
skip_line::invoke(loc);
|
||||||
|
lex_ws::invoke(loc);
|
||||||
|
|
||||||
table_type tab;
|
table_type tab;
|
||||||
while(loc.iter() != loc.end())
|
while(loc.iter() != loc.end())
|
||||||
@@ -1973,7 +1975,7 @@ parse(std::istream& is, const std::string& fname = "unknown file")
|
|||||||
template<typename Comment = ::toml::discard_comments,
|
template<typename Comment = ::toml::discard_comments,
|
||||||
template<typename ...> class Table = std::unordered_map,
|
template<typename ...> class Table = std::unordered_map,
|
||||||
template<typename ...> class Array = std::vector>
|
template<typename ...> class Array = std::vector>
|
||||||
inline basic_value<Comment, Table, Array> parse(const std::string& fname)
|
basic_value<Comment, Table, Array> parse(const std::string& fname)
|
||||||
{
|
{
|
||||||
std::ifstream ifs(fname.c_str(), std::ios_base::binary);
|
std::ifstream ifs(fname.c_str(), std::ios_base::binary);
|
||||||
if(!ifs.good())
|
if(!ifs.good())
|
||||||
|
|||||||
@@ -10,6 +10,45 @@
|
|||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// This function serialize a key. It checks a string is a bare key and
|
||||||
|
// escapes special characters if the string is not compatible to a bare key.
|
||||||
|
// ```cpp
|
||||||
|
// std::string k("non.bare.key"); // the key itself includes `.`s.
|
||||||
|
// std::string formatted = toml::format_key(k);
|
||||||
|
// assert(formatted == "\"non.bare.key\"");
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// This function is exposed to make it easy to write a user-defined serializer.
|
||||||
|
// Since toml restricts characters available in a bare key, generally a string
|
||||||
|
// should be escaped. But checking whether a string needs to be surrounded by
|
||||||
|
// a `"` and escaping some special character is boring.
|
||||||
|
inline std::string format_key(const toml::key& key)
|
||||||
|
{
|
||||||
|
detail::location<toml::key> loc(key, key);
|
||||||
|
detail::lex_unquoted_key::invoke(loc);
|
||||||
|
if(loc.iter() == loc.end())
|
||||||
|
{
|
||||||
|
return key; // all the tokens are consumed. the key is unquoted-key.
|
||||||
|
}
|
||||||
|
std::string token("\"");
|
||||||
|
for(const char c : key)
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '\\': {token += "\\\\"; break;}
|
||||||
|
case '\"': {token += "\\\""; break;}
|
||||||
|
case '\b': {token += "\\b"; break;}
|
||||||
|
case '\t': {token += "\\t"; break;}
|
||||||
|
case '\f': {token += "\\f"; break;}
|
||||||
|
case '\n': {token += "\\n"; break;}
|
||||||
|
case '\r': {token += "\\r"; break;}
|
||||||
|
default : {token += c; break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token += "\"";
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Comment,
|
template<typename Comment,
|
||||||
template<typename ...> class Table,
|
template<typename ...> class Table,
|
||||||
template<typename ...> class Array>
|
template<typename ...> class Array>
|
||||||
@@ -32,9 +71,10 @@ struct serializer
|
|||||||
serializer(const std::size_t w = 80u,
|
serializer(const std::size_t w = 80u,
|
||||||
const int float_prec = std::numeric_limits<toml::floating>::max_digits10,
|
const int float_prec = std::numeric_limits<toml::floating>::max_digits10,
|
||||||
const bool can_be_inlined = false,
|
const bool can_be_inlined = false,
|
||||||
|
const bool no_comment = false,
|
||||||
std::vector<toml::key> ks = {})
|
std::vector<toml::key> ks = {})
|
||||||
: can_be_inlined_(can_be_inlined), float_prec_(float_prec), width_(w),
|
: can_be_inlined_(can_be_inlined), no_comment_(no_comment),
|
||||||
keys_(std::move(ks))
|
float_prec_(float_prec), width_(w), keys_(std::move(ks))
|
||||||
{}
|
{}
|
||||||
~serializer() = default;
|
~serializer() = default;
|
||||||
|
|
||||||
@@ -217,12 +257,15 @@ struct serializer
|
|||||||
failed = true;
|
failed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(!no_comment_)
|
||||||
|
{
|
||||||
for(const auto& c : item.comments())
|
for(const auto& c : item.comments())
|
||||||
{
|
{
|
||||||
token += '#';
|
token += '#';
|
||||||
token += c;
|
token += c;
|
||||||
token += '\n';
|
token += '\n';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const auto t = this->make_inline_table(item.as_table());
|
const auto t = this->make_inline_table(item.as_table());
|
||||||
|
|
||||||
@@ -245,6 +288,8 @@ struct serializer
|
|||||||
|
|
||||||
std::string token;
|
std::string token;
|
||||||
for(const auto& item : v)
|
for(const auto& item : v)
|
||||||
|
{
|
||||||
|
if(!no_comment_)
|
||||||
{
|
{
|
||||||
for(const auto& c : item.comments())
|
for(const auto& c : item.comments())
|
||||||
{
|
{
|
||||||
@@ -252,6 +297,7 @@ struct serializer
|
|||||||
token += c;
|
token += c;
|
||||||
token += '\n';
|
token += '\n';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
token += "[[";
|
token += "[[";
|
||||||
token += this->serialize_dotted_key(keys_);
|
token += this->serialize_dotted_key(keys_);
|
||||||
token += "]]\n";
|
token += "]]\n";
|
||||||
@@ -287,7 +333,7 @@ struct serializer
|
|||||||
token += "[\n";
|
token += "[\n";
|
||||||
for(const auto& item : v)
|
for(const auto& item : v)
|
||||||
{
|
{
|
||||||
if(!item.comments().empty())
|
if(!item.comments().empty() && !no_comment_)
|
||||||
{
|
{
|
||||||
// if comment exists, the element must be the only element in the line.
|
// if comment exists, the element must be the only element in the line.
|
||||||
// e.g. the following is not allowed.
|
// e.g. the following is not allowed.
|
||||||
@@ -369,7 +415,8 @@ struct serializer
|
|||||||
token += " = ";
|
token += " = ";
|
||||||
}
|
}
|
||||||
token += this->make_inline_table(v);
|
token += this->make_inline_table(v);
|
||||||
if(token.size() < this->width_)
|
if(token.size() < this->width_ &&
|
||||||
|
token.end() == std::find(token.begin(), token.end(), '\n'))
|
||||||
{
|
{
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
@@ -390,16 +437,7 @@ struct serializer
|
|||||||
|
|
||||||
std::string serialize_key(const toml::key& key) const
|
std::string serialize_key(const toml::key& key) const
|
||||||
{
|
{
|
||||||
detail::location<toml::key> loc(key, key);
|
return ::toml::format_key(key);
|
||||||
detail::lex_unquoted_key::invoke(loc);
|
|
||||||
if(loc.iter() == loc.end())
|
|
||||||
{
|
|
||||||
return key; // all the tokens are consumed. the key is unquoted-key.
|
|
||||||
}
|
|
||||||
std::string token("\"");
|
|
||||||
token += this->escape_basic_string(key);
|
|
||||||
token += "\"";
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string serialize_dotted_key(const std::vector<toml::key>& keys) const
|
std::string serialize_dotted_key(const std::vector<toml::key>& keys) const
|
||||||
@@ -472,6 +510,9 @@ struct serializer
|
|||||||
// if an element of a table or an array has a comment, it cannot be inlined.
|
// if an element of a table or an array has a comment, it cannot be inlined.
|
||||||
bool has_comment_inside(const array_type& a) const noexcept
|
bool has_comment_inside(const array_type& a) const noexcept
|
||||||
{
|
{
|
||||||
|
// if no_comment is set, comments would not be written.
|
||||||
|
if(this->no_comment_) {return false;}
|
||||||
|
|
||||||
for(const auto& v : a)
|
for(const auto& v : a)
|
||||||
{
|
{
|
||||||
if(!v.comments().empty()) {return true;}
|
if(!v.comments().empty()) {return true;}
|
||||||
@@ -480,6 +521,9 @@ struct serializer
|
|||||||
}
|
}
|
||||||
bool has_comment_inside(const table_type& t) const noexcept
|
bool has_comment_inside(const table_type& t) const noexcept
|
||||||
{
|
{
|
||||||
|
// if no_comment is set, comments would not be written.
|
||||||
|
if(this->no_comment_) {return false;}
|
||||||
|
|
||||||
for(const auto& kv : t)
|
for(const auto& kv : t)
|
||||||
{
|
{
|
||||||
if(!kv.second.comments().empty()) {return true;}
|
if(!kv.second.comments().empty()) {return true;}
|
||||||
@@ -536,7 +580,7 @@ struct serializer
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!kv.second.comments().empty())
|
if(!kv.second.comments().empty() && !no_comment_)
|
||||||
{
|
{
|
||||||
for(const auto& c : kv.second.comments())
|
for(const auto& c : kv.second.comments())
|
||||||
{
|
{
|
||||||
@@ -575,8 +619,8 @@ struct serializer
|
|||||||
std::vector<toml::key> ks(this->keys_);
|
std::vector<toml::key> ks(this->keys_);
|
||||||
ks.push_back(kv.first);
|
ks.push_back(kv.first);
|
||||||
|
|
||||||
auto tmp = visit(serializer(
|
auto tmp = visit(serializer(this->width_, this->float_prec_,
|
||||||
this->width_, this->float_prec_, !multiline_table_printed, ks),
|
!multiline_table_printed, this->no_comment_, ks),
|
||||||
kv.second);
|
kv.second);
|
||||||
|
|
||||||
if((!multiline_table_printed) &&
|
if((!multiline_table_printed) &&
|
||||||
@@ -590,7 +634,7 @@ struct serializer
|
|||||||
tmp += '\n';
|
tmp += '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!kv.second.comments().empty())
|
if(!kv.second.comments().empty() && !no_comment_)
|
||||||
{
|
{
|
||||||
for(const auto& c : kv.second.comments())
|
for(const auto& c : kv.second.comments())
|
||||||
{
|
{
|
||||||
@@ -614,6 +658,7 @@ struct serializer
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
bool can_be_inlined_;
|
bool can_be_inlined_;
|
||||||
|
bool no_comment_;
|
||||||
int float_prec_;
|
int float_prec_;
|
||||||
std::size_t width_;
|
std::size_t width_;
|
||||||
std::vector<toml::key> keys_;
|
std::vector<toml::key> keys_;
|
||||||
@@ -624,7 +669,7 @@ template<typename C,
|
|||||||
std::string
|
std::string
|
||||||
format(const basic_value<C, M, V>& v, std::size_t w = 80u,
|
format(const basic_value<C, M, V>& v, std::size_t w = 80u,
|
||||||
int fprec = std::numeric_limits<toml::floating>::max_digits10,
|
int fprec = std::numeric_limits<toml::floating>::max_digits10,
|
||||||
bool force_inline = false)
|
bool no_comment = false, bool force_inline = false)
|
||||||
{
|
{
|
||||||
// if value is a table, it is considered to be a root object.
|
// if value is a table, it is considered to be a root object.
|
||||||
// the root object can't be an inline table.
|
// the root object can't be an inline table.
|
||||||
@@ -633,18 +678,43 @@ format(const basic_value<C, M, V>& v, std::size_t w = 80u,
|
|||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
if(!v.comments().empty())
|
if(!v.comments().empty())
|
||||||
{
|
{
|
||||||
for(const auto& c : v.comments())
|
oss << v.comments();
|
||||||
{
|
oss << '\n'; // to split the file comment from the first element
|
||||||
oss << '#' << c << '\n';
|
|
||||||
}
|
}
|
||||||
oss << '\n';
|
oss << visit(serializer<C, M, V>(w, fprec, no_comment, false), v);
|
||||||
}
|
|
||||||
oss << visit(serializer<C, M, V>(w, fprec, false), v);
|
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
return visit(serializer<C, M, V>(w, fprec, force_inline), v);
|
return visit(serializer<C, M, V>(w, fprec, force_inline), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
int comment_index(std::basic_ostream<charT, traits>&)
|
||||||
|
{
|
||||||
|
static const int index = std::ios_base::xalloc();
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
nocomment(std::basic_ostream<charT, traits>& os)
|
||||||
|
{
|
||||||
|
// by default, it is zero. and by defalut, it shows comments.
|
||||||
|
os.iword(detail::comment_index(os)) = 1;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
showcomment(std::basic_ostream<charT, traits>& os)
|
||||||
|
{
|
||||||
|
// by default, it is zero. and by defalut, it shows comments.
|
||||||
|
os.iword(detail::comment_index(os)) = 0;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename charT, typename traits, typename C,
|
template<typename charT, typename traits, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V>
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
std::basic_ostream<charT, traits>&
|
std::basic_ostream<charT, traits>&
|
||||||
@@ -655,16 +725,40 @@ operator<<(std::basic_ostream<charT, traits>& os, const basic_value<C, M, V>& v)
|
|||||||
const int fprec = static_cast<int>(os.precision());
|
const int fprec = static_cast<int>(os.precision());
|
||||||
os.width(0);
|
os.width(0);
|
||||||
|
|
||||||
if(!v.comments().empty())
|
// by defualt, iword is initialized byl 0. And by default, toml11 outputs
|
||||||
|
// comments. So `0` means showcomment. 1 means nocommnet.
|
||||||
|
const bool no_comment = (1 == os.iword(detail::comment_index(os)));
|
||||||
|
|
||||||
|
if(!no_comment && v.is_table() && !v.comments().empty())
|
||||||
{
|
{
|
||||||
for(const auto& c : v.comments())
|
os << v.comments();
|
||||||
{
|
os << '\n'; // to split the file comment from the first element
|
||||||
os << '#' << c << '\n';
|
|
||||||
}
|
|
||||||
os << '\n';
|
|
||||||
}
|
}
|
||||||
// the root object can't be an inline table. so pass `false`.
|
// the root object can't be an inline table. so pass `false`.
|
||||||
os << visit(serializer<C, M, V>(w, fprec, false), v);
|
os << visit(serializer<C, M, V>(w, fprec, false, no_comment), v);
|
||||||
|
|
||||||
|
// if v is a non-table value, and has only one comment, then
|
||||||
|
// put a comment just after a value. in the following way.
|
||||||
|
//
|
||||||
|
// ```toml
|
||||||
|
// key = "value" # comment.
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Since the top-level toml object is a table, one who want to put a
|
||||||
|
// non-table toml value must use this in a following way.
|
||||||
|
//
|
||||||
|
// ```cpp
|
||||||
|
// toml::value v;
|
||||||
|
// std::cout << "user-defined-key = " << v << std::endl;
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// In this case, it is impossible to put comments before key-value pair.
|
||||||
|
// The only way to preserve comments is to put all of them after a value.
|
||||||
|
if(!no_comment && !v.is_table() && !v.comments().empty())
|
||||||
|
{
|
||||||
|
os << " #";
|
||||||
|
for(const auto& c : v.comments()) {os << c;}
|
||||||
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,9 +139,74 @@ operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.s
|
|||||||
|
|
||||||
template<typename charT, typename traits>
|
template<typename charT, typename traits>
|
||||||
std::basic_ostream<charT, traits>&
|
std::basic_ostream<charT, traits>&
|
||||||
operator<<(std::basic_ostream<charT, traits>& os, const string& str)
|
operator<<(std::basic_ostream<charT, traits>& os, const string& s)
|
||||||
{
|
{
|
||||||
os << str.str;
|
if(s.kind == string_t::basic)
|
||||||
|
{
|
||||||
|
if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
|
||||||
|
{
|
||||||
|
// it contains newline. make it multiline string.
|
||||||
|
os << "\"\"\"\n";
|
||||||
|
for(auto i=s.str.cbegin(), e=s.str.cend(); i!=e; ++i)
|
||||||
|
{
|
||||||
|
switch(*i)
|
||||||
|
{
|
||||||
|
case '\\': {os << "\\\\"; break;}
|
||||||
|
case '\"': {os << "\\\""; break;}
|
||||||
|
case '\b': {os << "\\b"; break;}
|
||||||
|
case '\t': {os << "\\t"; break;}
|
||||||
|
case '\f': {os << "\\f"; break;}
|
||||||
|
case '\n': {os << '\n'; break;}
|
||||||
|
case '\r':
|
||||||
|
{
|
||||||
|
// since it is a multiline string,
|
||||||
|
// CRLF is not needed to be escaped.
|
||||||
|
if(std::next(i) != e && *std::next(i) == '\n')
|
||||||
|
{
|
||||||
|
os << "\r\n";
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << "\\r";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {os << *i; break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "\\\n\"\"\"";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
// no newline. make it inline.
|
||||||
|
os << "\"";
|
||||||
|
for(const auto c : s.str)
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '\\': {os << "\\\\"; break;}
|
||||||
|
case '\"': {os << "\\\""; break;}
|
||||||
|
case '\b': {os << "\\b"; break;}
|
||||||
|
case '\t': {os << "\\t"; break;}
|
||||||
|
case '\f': {os << "\\f"; break;}
|
||||||
|
case '\n': {os << "\\n"; break;}
|
||||||
|
case '\r': {os << "\\r"; break;}
|
||||||
|
default : {os << c; break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "\"";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
// the string `s` is literal-string.
|
||||||
|
if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
|
||||||
|
std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
|
||||||
|
{
|
||||||
|
// contains newline or single quote. make it multiline.
|
||||||
|
os << "'''\n" << s.str << "'''";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
// normal literal string
|
||||||
|
os << '\'' << s.str << '\'';
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -240,6 +240,19 @@ disjunction<
|
|||||||
>
|
>
|
||||||
>{};
|
>{};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// C++20 remove_cvref_t
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct remove_cvref
|
||||||
|
{
|
||||||
|
using type = typename std::remove_cv<
|
||||||
|
typename std::remove_reference<T>::type>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using remove_cvref_t = typename remove_cvref<T>::type;
|
||||||
|
|
||||||
}// detail
|
}// detail
|
||||||
}//toml
|
}//toml
|
||||||
#endif // TOML_TRAITS
|
#endif // TOML_TRAITS
|
||||||
|
|||||||
@@ -1567,9 +1567,31 @@ class basic_value
|
|||||||
return std::move(this->table_.value());
|
return std::move(this->table_.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// accessors =============================================================
|
||||||
|
//
|
||||||
|
// may throw type_error or out_of_range
|
||||||
|
//
|
||||||
|
value_type& at(const key& k)
|
||||||
|
{
|
||||||
|
return this->as_table().at(k);
|
||||||
|
}
|
||||||
|
value_type const& at(const key& k) const
|
||||||
|
{
|
||||||
|
return this->as_table().at(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type& at(const std::size_t idx)
|
||||||
|
{
|
||||||
|
return this->as_array().at(idx);
|
||||||
|
}
|
||||||
|
value_type const& at(const std::size_t idx) const
|
||||||
|
{
|
||||||
|
return this->as_array().at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
source_location location() const
|
source_location location() const
|
||||||
{
|
{
|
||||||
return source_location(this->region_info_);
|
return source_location(this->region_info_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
comment_type const& comments() const noexcept {return this->comments_;}
|
comment_type const& comments() const noexcept {return this->comments_;}
|
||||||
|
|||||||
Reference in New Issue
Block a user