mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa8d574dfe | ||
|
|
49fdb61731 | ||
|
|
b2bb21a473 | ||
|
|
0c58549fc6 | ||
|
|
b7b5e847d3 | ||
|
|
22d630fec1 | ||
|
|
f7bf341452 | ||
|
|
0934d90f90 | ||
|
|
f2c8d0e279 | ||
|
|
8c7d83d985 | ||
|
|
5ce44adbdc | ||
|
|
5c5b1320d0 | ||
|
|
8b737dc21f | ||
|
|
ee654b6c3f | ||
|
|
c59782d180 | ||
|
|
9bef715ccd | ||
|
|
d2b1cf5123 | ||
|
|
9f92916d1d | ||
|
|
666e4cf9dc | ||
|
|
cafee29c64 | ||
|
|
a7a2272b29 | ||
|
|
dc0bca2bb6 | ||
|
|
490abe04fd | ||
|
|
81ed4c0e9d | ||
|
|
1b07baf184 | ||
|
|
9073d52159 | ||
|
|
55260654bf | ||
|
|
aa6271af75 | ||
|
|
c54a03f189 | ||
|
|
c153c0e8c3 | ||
|
|
1f90af8e67 | ||
|
|
a0c5192b74 | ||
|
|
7f020f3f44 | ||
|
|
827b433389 | ||
|
|
b1827e6fca | ||
|
|
18f84088b4 | ||
|
|
c199bd8b49 | ||
|
|
5b35c1a74e | ||
|
|
d3513c0f84 | ||
|
|
8567f09cbf | ||
|
|
a6d24b02d5 | ||
|
|
08bf5ffbdf | ||
|
|
a945bd6eac | ||
|
|
f4ac286b0f | ||
|
|
f31dc6ba37 | ||
|
|
fecd50dfeb | ||
|
|
d48d454a61 | ||
|
|
4688c235f5 | ||
|
|
5c146857a3 | ||
|
|
bc51699415 | ||
|
|
8b923d56e9 | ||
|
|
3190c1da9f | ||
|
|
a41dc08025 | ||
|
|
0c084b3a5c | ||
|
|
8fbeaabfd9 | ||
|
|
331de4ea5d | ||
|
|
b246f5ac5c | ||
|
|
89714fb24b | ||
|
|
62c01f9826 | ||
|
|
5a8d368927 | ||
|
|
28519f5712 | ||
|
|
63fdbd25cf | ||
|
|
6d41a1adb9 | ||
|
|
26a09b2f65 | ||
|
|
7e62dad6dc | ||
|
|
2fd466a3c3 | ||
|
|
6f7539dc6a | ||
|
|
f290390c63 | ||
|
|
571baa2c26 | ||
|
|
bbe33e87d9 | ||
|
|
4c5076f263 | ||
|
|
d47174954f | ||
|
|
821eb9632b | ||
|
|
af116991b6 | ||
|
|
87bebbc37d | ||
|
|
c2d0351e69 | ||
|
|
1526b9feee | ||
|
|
281206dcc6 | ||
|
|
adf8fa9234 | ||
|
|
0a66be3257 | ||
|
|
160537360c | ||
|
|
9af2d65417 | ||
|
|
429763377f | ||
|
|
c774beb79a | ||
|
|
8240fffeca | ||
|
|
047611764c | ||
|
|
bc3eb9d967 | ||
|
|
6862264bde | ||
|
|
2ee69fc420 | ||
|
|
6a15e8360f | ||
|
|
b4c6d26842 | ||
|
|
41eb1d6887 | ||
|
|
3ca712a8da | ||
|
|
8e589ff4d7 | ||
|
|
56812114c3 | ||
|
|
f98615d0df | ||
|
|
37769e28f0 | ||
|
|
2acdec00aa | ||
|
|
354cfc979a | ||
|
|
3dc3b001ff | ||
|
|
ea24a91f4c | ||
|
|
5bba73a8ca | ||
|
|
54eced6c82 | ||
|
|
258e62f8f3 | ||
|
|
06086a9ff7 | ||
|
|
b4b35ea33e | ||
|
|
d7b4d104d3 | ||
|
|
1148d01c70 | ||
|
|
e12fd4d944 | ||
|
|
36af02cb3a | ||
|
|
488015df49 | ||
|
|
1f951e49b1 | ||
|
|
6a7dbb7875 | ||
|
|
17d78553ff | ||
|
|
4c12dad51f | ||
|
|
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 |
@@ -12,7 +12,7 @@ jobs:
|
|||||||
command: |
|
command: |
|
||||||
g++ --version
|
g++ --version
|
||||||
cd tests/
|
cd tests/
|
||||||
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 -DTOML11_COLORIZE_ERROR_MESSAGE -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:
|
test_serialization:
|
||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
command: |
|
command: |
|
||||||
g++ --version
|
g++ --version
|
||||||
cd tests/
|
cd tests/
|
||||||
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check_serialization.cpp -o check_serialization
|
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -DTOML11_COLORIZE_ERROR_MESSAGE -I../ check_serialization.cpp -o check_serialization
|
||||||
git clone https://github.com/BurntSushi/toml-test.git
|
git clone https://github.com/BurntSushi/toml-test.git
|
||||||
cp check_serialization toml-test/tests/valid
|
cp check_serialization toml-test/tests/valid
|
||||||
cd toml-test/tests/valid
|
cd toml-test/tests/valid
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
command: |
|
command: |
|
||||||
g++ --version
|
g++ --version
|
||||||
cd tests/
|
cd tests/
|
||||||
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check.cpp -o check
|
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -DTOML11_COLORIZE_ERROR_MESSAGE -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
|
||||||
|
|||||||
183
.travis.yml
183
.travis.yml
@@ -9,7 +9,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
packages:
|
packages:
|
||||||
- g++-5
|
- g++-5
|
||||||
@@ -21,7 +21,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
packages:
|
packages:
|
||||||
- g++-6
|
- g++-6
|
||||||
@@ -33,7 +33,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
packages:
|
packages:
|
||||||
- g++-7
|
- g++-7
|
||||||
@@ -45,7 +45,31 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8" CXX_STANDARD=11 TOML_HEAD=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8" CXX_STANDARD=14
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
packages:
|
packages:
|
||||||
- g++-8
|
- g++-8
|
||||||
@@ -57,7 +81,19 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
packages:
|
packages:
|
||||||
- g++-8
|
- g++-8
|
||||||
@@ -65,16 +101,16 @@ 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.9" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- llvm-toolchain-precise-3.7
|
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-3.9
|
||||||
packages:
|
packages:
|
||||||
- g++-8
|
- g++-8
|
||||||
- clang-3.7
|
- clang-3.9
|
||||||
- boost1.70
|
- boost1.70
|
||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
@@ -83,9 +119,9 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- llvm-toolchain-trusty-4.0
|
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-4.0
|
||||||
packages:
|
packages:
|
||||||
- g++-8
|
- g++-8
|
||||||
- clang-4.0
|
- clang-4.0
|
||||||
@@ -97,9 +133,9 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- llvm-toolchain-trusty-5.0
|
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-5.0
|
||||||
packages:
|
packages:
|
||||||
- g++-8
|
- g++-8
|
||||||
- clang-5.0
|
- clang-5.0
|
||||||
@@ -111,9 +147,9 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- llvm-toolchain-trusty-6.0
|
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-6.0
|
||||||
packages:
|
packages:
|
||||||
- g++-8
|
- g++-8
|
||||||
- clang-6.0
|
- clang-6.0
|
||||||
@@ -125,9 +161,9 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- llvm-toolchain-trusty-7
|
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-7
|
||||||
packages:
|
packages:
|
||||||
- g++-8
|
- g++-8
|
||||||
- clang-7
|
- clang-7
|
||||||
@@ -139,13 +175,41 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- llvm-toolchain-trusty-8
|
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
packages:
|
packages:
|
||||||
- g++-8
|
- g++-8
|
||||||
- clang-8
|
- clang-8
|
||||||
- boost1.70
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=11 TOML_HEAD=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- clang-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=14
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
@@ -153,9 +217,51 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
- llvm-toolchain-trusty-8
|
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=11 WITH_ASAN=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- boost1.70
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=11 WITH_UBSAN=ON
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:ubuntu-toolchain-r/test'
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
packages:
|
packages:
|
||||||
- clang-8
|
- clang-8
|
||||||
- g++-8
|
- g++-8
|
||||||
@@ -164,6 +270,15 @@ matrix:
|
|||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: CXX_STANDARD=11
|
env: CXX_STANDARD=11
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/Library/Caches/Homebrew
|
||||||
|
addons:
|
||||||
|
homebrew:
|
||||||
|
update: true
|
||||||
|
packages:
|
||||||
|
- cmake
|
||||||
|
- boost
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- |
|
- |
|
||||||
@@ -172,13 +287,33 @@ script:
|
|||||||
travis_retry wget "https://github.com/Kitware/CMake/releases/download/v3.14.5/cmake-3.14.5-Linux-x86_64.tar.gz"
|
travis_retry wget "https://github.com/Kitware/CMake/releases/download/v3.14.5/cmake-3.14.5-Linux-x86_64.tar.gz"
|
||||||
tar xf cmake-3.14.5-Linux-x86_64.tar.gz -C cmake --strip-components=1
|
tar xf cmake-3.14.5-Linux-x86_64.tar.gz -C cmake --strip-components=1
|
||||||
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
|
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
|
||||||
else
|
|
||||||
brew upgrade cmake boost
|
|
||||||
fi
|
fi
|
||||||
|
- |
|
||||||
|
if [[ "${TOML_HEAD}" != "ON" ]]; then
|
||||||
|
export TOML_HEAD="OFF"
|
||||||
|
fi
|
||||||
|
- echo "TOML_HEAD = ${TOML_HEAD}"
|
||||||
|
- |
|
||||||
|
if [[ "${WITH_ASAN}" != "ON" ]]; then
|
||||||
|
export WITH_ASAN="OFF"
|
||||||
|
fi
|
||||||
|
- echo "WITH_ASAN = ${WITH_ASAN}"
|
||||||
|
- |
|
||||||
|
if [[ "${WITH_UBSAN}" != "ON" ]]; then
|
||||||
|
export WITH_UBSAN="OFF"
|
||||||
|
fi
|
||||||
|
- echo "WITH_UBSAN = ${WITH_UBSAN}"
|
||||||
- cmake --version
|
- cmake --version
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- git clone https://github.com/toml-lang/toml.git
|
- git clone https://github.com/toml-lang/toml.git
|
||||||
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD ..
|
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD -DTOML11_USE_UNRELEASED_TOML_FEATURES=${TOML_HEAD} -Dtoml11_TEST_WITH_ASAN=${WITH_ASAN} -Dtoml11_TEST_WITH_UBSAN=${WITH_UBSAN} ..
|
||||||
- make
|
- make
|
||||||
- ctest --output-on-failure
|
- ctest --output-on-failure
|
||||||
|
|
||||||
|
# https://stackoverflow.com/a/53331571
|
||||||
|
before_cache:
|
||||||
|
- |
|
||||||
|
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||||
|
brew cleanup
|
||||||
|
fi
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ enable_testing()
|
|||||||
project(toml11)
|
project(toml11)
|
||||||
|
|
||||||
set(toml11_VERSION_MAYOR 3)
|
set(toml11_VERSION_MAYOR 3)
|
||||||
set(toml11_VERSION_MINOR 0)
|
set(toml11_VERSION_MINOR 3)
|
||||||
set(toml11_VERSION_PATCH 1)
|
set(toml11_VERSION_PATCH 0)
|
||||||
set(toml11_VERSION
|
set(toml11_VERSION
|
||||||
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
|
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
|
||||||
)
|
)
|
||||||
|
|
||||||
option(toml11_BUILD_TEST "Build toml tests" ON)
|
option(toml11_BUILD_TEST "Build toml tests" ON)
|
||||||
|
option(toml11_TEST_WITH_ASAN "use LLVM address sanitizer" OFF)
|
||||||
|
option(toml11_TEST_WITH_UBSAN "use LLVM undefined behavior sanitizer" OFF)
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
||||||
|
|||||||
358
README.md
358
README.md
@@ -68,8 +68,12 @@ int main()
|
|||||||
- [TOML literal](#toml-literal)
|
- [TOML literal](#toml-literal)
|
||||||
- [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types)
|
- [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types)
|
||||||
- [Formatting user-defined error messages](#formatting-user-defined-error-messages)
|
- [Formatting user-defined error messages](#formatting-user-defined-error-messages)
|
||||||
|
- [Obtaining location information](#obtaining-location-information)
|
||||||
|
- [Exceptions](#exceptions)
|
||||||
|
- [Colorize Error Messages](#colorize-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)
|
||||||
@@ -270,10 +274,44 @@ const auto color = toml::find<std::string>(data, "fruit", "physical", "color");
|
|||||||
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Finding a value in an array
|
||||||
|
|
||||||
|
You can find n-th value in an array by `toml::find`.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
values = ["foo", "bar", "baz"]
|
||||||
|
```
|
||||||
|
|
||||||
|
``` cpp
|
||||||
|
const auto data = toml::parse("sample.toml");
|
||||||
|
const auto values = toml::find(data, "values");
|
||||||
|
const auto bar = toml::find<std::string>(values, 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
`toml::find` can also search array recursively.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
const auto bar = toml::find<std::string>(data, "values", 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
Before calling `toml::find`, you can check if a value corresponding to a key
|
||||||
|
exists. You can use both `bool toml::value::contains(const key&) const` and
|
||||||
|
`std::size_t toml::value::count(const key&) const`. Those behaves like the
|
||||||
|
`std::map::contains` and `std::map::count`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto data = toml::parse("fruit.toml");
|
||||||
|
if(data.contains("fruit") && data.at("fruit").count("physical") != 0)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### In case of error
|
### In case of error
|
||||||
|
|
||||||
If the value does not exist, `toml::find` throws an error with the location of
|
If the value does not exist, `toml::find` throws `std::out_of_range` with the
|
||||||
the table.
|
location of the table.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
terminate called after throwing an instance of 'std::out_of_range'
|
terminate called after throwing an instance of 'std::out_of_range'
|
||||||
@@ -283,11 +321,6 @@ terminate called after throwing an instance of 'std::out_of_range'
|
|||||||
| ~~~~~ in this table
|
| ~~~~~ in this table
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: It is recommended to find a table as `toml::value` because it has much information
|
|
||||||
compared to `toml::table`, which is an alias of
|
|
||||||
`std::unordered_map<std::string, toml::value>`. Since `toml::table` does not have
|
|
||||||
any information about toml file, such as where the table was defined in the file.
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
If the specified type differs from the actual value contained, it throws
|
If the specified type differs from the actual value contained, it throws
|
||||||
@@ -350,6 +383,7 @@ The above code works with the following toml file.
|
|||||||
# NOT {"physical": {"color": "orange"}}.
|
# NOT {"physical": {"color": "orange"}}.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Casting a toml value
|
## Casting a toml value
|
||||||
|
|
||||||
### `toml::get`
|
### `toml::get`
|
||||||
@@ -453,6 +487,60 @@ 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`.
|
||||||
|
|
||||||
|
Note that, although `std::string` has `at()` member function, `toml::value::at`
|
||||||
|
throws if the contained type is a string. Because `std::string` does not
|
||||||
|
contain `toml::value`.
|
||||||
|
|
||||||
|
### `operator[]`
|
||||||
|
|
||||||
|
You can also access to the element of a table and an array by
|
||||||
|
`toml::basic_value::operator[]`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const toml::value v{1,2,3,4,5};
|
||||||
|
std::cout << v[2].as_integer() << std::endl; // 3
|
||||||
|
|
||||||
|
const toml::value v{{"foo", 42}, {"bar", 3.14}};
|
||||||
|
std::cout << v["foo"].as_integer() << std::endl; // 42
|
||||||
|
```
|
||||||
|
|
||||||
|
When you access to a `toml::value` that is not initialized yet via
|
||||||
|
`operator[](const std::string&)`, the `toml::value` will be a table,
|
||||||
|
just like the `std::map`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
toml::value v; // not initialized as a table.
|
||||||
|
v["foo"] = 42; // OK. `v` will be a table.
|
||||||
|
```
|
||||||
|
|
||||||
|
Contrary, if you access to a `toml::value` that contains an array via `operator[]`,
|
||||||
|
it does not check anything. It converts `toml::value` without type check and then
|
||||||
|
access to the n-th element without boundary check, just like the `std::vector::operator[]`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
toml::value v; // not initialized as an array
|
||||||
|
v[2] = 42; // error! UB
|
||||||
|
```
|
||||||
|
|
||||||
|
Please make sure that the `toml::value` has an array inside when you access to
|
||||||
|
its element via `operator[]`.
|
||||||
|
|
||||||
## Checking value type
|
## Checking value type
|
||||||
|
|
||||||
You can check the type of a value by `is_xxx` function.
|
You can check the type of a value by `is_xxx` function.
|
||||||
@@ -675,6 +763,7 @@ date information, but it can be converted to `std::chrono::duration` that
|
|||||||
represents a duration from the beginning of the day, `00:00:00.000`.
|
represents a duration from the beginning of the day, `00:00:00.000`.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
# sample.toml
|
||||||
date = 2018-12-23
|
date = 2018-12-23
|
||||||
time = 12:30:00
|
time = 12:30:00
|
||||||
l_dt = 2018-12-23T12:30:00
|
l_dt = 2018-12-23T12:30:00
|
||||||
@@ -691,8 +780,12 @@ const auto o_dt = toml::get<std::chrono::system_clock::time_point>(data.at("o_dt
|
|||||||
const auto time = toml::get<std::chrono::minutes>(data.at("time")); // 12 * 60 + 30 min
|
const auto time = toml::get<std::chrono::minutes>(data.at("time")); // 12 * 60 + 30 min
|
||||||
```
|
```
|
||||||
|
|
||||||
toml11 defines its own datetime classes.
|
`local_date` and `local_datetime` are assumed to be in the local timezone when
|
||||||
You can see the definitions in [toml/datetime.hpp](toml/datetime.hpp).
|
they are converted into `time_point`. On the other hand, `offset_datetime` only
|
||||||
|
uses the offset part of the data and it does not take local timezone into account.
|
||||||
|
|
||||||
|
To contain datetime data, toml11 defines its own datetime types.
|
||||||
|
For more detail, you can see the definitions in [toml/datetime.hpp](toml/datetime.hpp).
|
||||||
|
|
||||||
## Getting with a fallback
|
## Getting with a fallback
|
||||||
|
|
||||||
@@ -805,14 +898,25 @@ toml::value v(toml::local_time(std::chrono::hours(10)));
|
|||||||
```
|
```
|
||||||
|
|
||||||
You can construct an array object not only from `initializer_list`, but also
|
You can construct an array object not only from `initializer_list`, but also
|
||||||
from STL containers.
|
from STL containers. In that case, the element type must be convertible to
|
||||||
|
`toml::value`.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
std::vector<int> vec{1,2,3,4,5};
|
std::vector<int> vec{1,2,3,4,5};
|
||||||
toml::value v = vec;
|
toml::value v(vec);
|
||||||
```
|
```
|
||||||
|
|
||||||
All the elements of `initializer_list` should be convertible into `toml::value`.
|
When you construct an array value, all the elements of `initializer_list`
|
||||||
|
must be convertible into `toml::value`.
|
||||||
|
|
||||||
|
If a `toml::value` has an array, you can `push_back` an element in it.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
toml::value v{1,2,3,4,5};
|
||||||
|
v.push_back(6);
|
||||||
|
```
|
||||||
|
|
||||||
|
`emplace_back` also works.
|
||||||
|
|
||||||
## Preserving comments
|
## Preserving comments
|
||||||
|
|
||||||
@@ -1029,7 +1133,7 @@ const auto data = toml::parse("example.toml");
|
|||||||
const foo f = toml::find<ext::foo>(data, "foo");
|
const foo f = toml::find<ext::foo>(data, "foo");
|
||||||
```
|
```
|
||||||
|
|
||||||
There are 2 ways to use `toml::get` with the types that you defined.
|
There are 3 ways to use `toml::get` with the types that you defined.
|
||||||
|
|
||||||
The first one is to implement `from_toml(const toml::value&)` member function.
|
The first one is to implement `from_toml(const toml::value&)` member function.
|
||||||
|
|
||||||
@@ -1056,7 +1160,31 @@ struct foo
|
|||||||
In this way, because `toml::get` first constructs `foo` without arguments,
|
In this way, because `toml::get` first constructs `foo` without arguments,
|
||||||
the type should be default-constructible.
|
the type should be default-constructible.
|
||||||
|
|
||||||
The second is to implement specialization of `toml::from` for your type.
|
The second is to implement `constructor(const toml::value&)`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace ext
|
||||||
|
{
|
||||||
|
struct foo
|
||||||
|
{
|
||||||
|
explicit foo(const toml::value& v)
|
||||||
|
: a(toml::find<int>(v, "a")), b(toml::find<double>(v, "b")),
|
||||||
|
c(toml::find<std::string>(v, "c"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
int a;
|
||||||
|
double b;
|
||||||
|
std::string c;
|
||||||
|
};
|
||||||
|
} // ext
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that implicit default constructor declaration will be suppressed
|
||||||
|
when a constructor is defined. If you want to use the struct (here, `foo`)
|
||||||
|
in a container (e.g. `std::vector<foo>`), you may need to define default
|
||||||
|
constructor explicitly.
|
||||||
|
|
||||||
|
The third is to implement specialization of `toml::from` for your type.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
namespace ext
|
namespace ext
|
||||||
@@ -1074,7 +1202,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");
|
||||||
@@ -1114,7 +1242,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");
|
||||||
@@ -1170,7 +1298,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 +1365,28 @@ you will get an error message like this.
|
|||||||
| ~~ maximum number here
|
| ~~ maximum number here
|
||||||
```
|
```
|
||||||
|
|
||||||
### Obtaining location information
|
You can print hints at the end of the message.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::vector<std::string> hints;
|
||||||
|
hints.push_back("positive number means n >= 0.");
|
||||||
|
hints.push_back("negative number is not positive.");
|
||||||
|
std::cerr << toml::format_error("[error] value should be positive",
|
||||||
|
data.at("num"), "positive number required", hints)
|
||||||
|
<< std::endl;
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
[error] value should be positive
|
||||||
|
--> example.toml
|
||||||
|
2 | num = 42
|
||||||
|
| ~~ positive number required
|
||||||
|
|
|
||||||
|
Hint: positive number means n >= 0.
|
||||||
|
Hint: negative number is not positive.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Obtaining location information
|
||||||
|
|
||||||
You can also format error messages in your own way by using `source_location`.
|
You can also format error messages in your own way by using `source_location`.
|
||||||
|
|
||||||
@@ -1262,6 +1411,92 @@ const toml::value v = /*...*/;
|
|||||||
const toml::source_location loc = v.location();
|
const toml::source_location loc = v.location();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Exceptions
|
||||||
|
|
||||||
|
All the exceptions thrown by toml11 inherits `toml::exception` that inherits
|
||||||
|
`std::exception`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace toml {
|
||||||
|
struct exception : public std::exception {/**/};
|
||||||
|
struct syntax_error : public toml::exception {/**/};
|
||||||
|
struct type_error : public toml::exception {/**/};
|
||||||
|
struct internal_error : public toml::exception {/**/};
|
||||||
|
} // toml
|
||||||
|
```
|
||||||
|
|
||||||
|
`toml::exception` has `toml::exception::location()` member function that returns
|
||||||
|
`toml::source_location`, in addition to `what()`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace toml {
|
||||||
|
struct exception : public std::exception
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
source_location const& location() const noexcept;
|
||||||
|
};
|
||||||
|
} // toml
|
||||||
|
```
|
||||||
|
|
||||||
|
It represents where the error occurs.
|
||||||
|
|
||||||
|
## Colorize Error Messages
|
||||||
|
|
||||||
|
By defining `TOML11_COLORIZE_ERROR_MESSAGE`, the error messages from
|
||||||
|
`toml::parse` and `toml::find|get` will be colorized. By default, this feature
|
||||||
|
is turned off.
|
||||||
|
|
||||||
|
With the following toml file taken from `toml-lang/toml/tests/hard_example.toml`,
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[error]
|
||||||
|
array = [
|
||||||
|
"This might most likely happen in multiline arrays",
|
||||||
|
Like here,
|
||||||
|
"or here,
|
||||||
|
and here"
|
||||||
|
] End of array comment, forgot the #
|
||||||
|
```
|
||||||
|
|
||||||
|
the error message would be like this.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
With the following,
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[error]
|
||||||
|
# array = [
|
||||||
|
# "This might most likely happen in multiline arrays",
|
||||||
|
# Like here,
|
||||||
|
# "or here,
|
||||||
|
# and here"
|
||||||
|
# ] End of array comment, forgot the #
|
||||||
|
number = 3.14 pi <--again forgot the #
|
||||||
|
```
|
||||||
|
|
||||||
|
the error message would be like this.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The message would be messy when it is written to a file, not a terminal because
|
||||||
|
it uses [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code).
|
||||||
|
|
||||||
|
Without `TOML11_COLORIZE_ERROR_MESSAGE`, you can still colorize user-defined
|
||||||
|
error message by passing `true` to the `toml::format_error` function.
|
||||||
|
If you define `TOML11_COLORIZE_ERROR_MESSAGE`, the value is `true` by default.
|
||||||
|
If not, the defalut value would be `false`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::cerr << toml::format_error("[error] value should be positive",
|
||||||
|
data.at("num"), "positive number required",
|
||||||
|
hints, /*colorize = */ true) << std::endl;
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: It colorize `[error]` in red. That means that it detects `[error]` prefix
|
||||||
|
at the front of the error message. If there is no `[error]` prefix,
|
||||||
|
`format_error` adds it to the error message.
|
||||||
|
|
||||||
## Serializing TOML data
|
## Serializing TOML data
|
||||||
|
|
||||||
toml11 enables you to serialize data into toml format.
|
toml11 enables you to serialize data into toml format.
|
||||||
@@ -1394,7 +1629,83 @@ This feature is introduced to make it easy to write a custom serializer.
|
|||||||
Because `std::chrono::system_clock::time_point` is a __time point__,
|
Because `std::chrono::system_clock::time_point` is a __time point__,
|
||||||
not capable of representing a Local Time independent from a specific day.
|
not capable of representing a Local Time independent from a specific day.
|
||||||
|
|
||||||
It is recommended to get `datetime`s as `std::chrono` classes through `toml::get`.
|
## Unreleased TOML features
|
||||||
|
|
||||||
|
There are some unreleased features in toml-lang/toml:master.
|
||||||
|
Currently, the following features are available after defining
|
||||||
|
`TOML11_USE_UNRELEASED_TOML_FEATURES` macro flag.
|
||||||
|
|
||||||
|
To use those features, `#define` `TOML11_USE_UNRELEASED_TOML_FEATURES` before
|
||||||
|
including `toml.hpp` or pass `-DTOML11_USE_UNRELEASED_TOML_FEATURES` to your
|
||||||
|
compiler.
|
||||||
|
|
||||||
|
- Leading zeroes in exponent parts of floats are permitted.
|
||||||
|
- e.g. `1.0e+01`, `5e+05`
|
||||||
|
- [toml-lang/toml/PR/656](https://github.com/toml-lang/toml/pull/656)
|
||||||
|
- Allow raw tab characters in basic strings and multi-line basic strings.
|
||||||
|
- [toml-lang/toml/PR/627](https://github.com/toml-lang/toml/pull/627)
|
||||||
|
- Allow heterogeneous arrays
|
||||||
|
- [toml-lang/toml/PR/676](https://github.com/toml-lang/toml/pull/676)
|
||||||
|
|
||||||
|
### Note about heterogeneous arrays
|
||||||
|
|
||||||
|
Although `toml::parse` allows heterogeneous arrays, constructor of `toml::value`
|
||||||
|
does not.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// this won't be compiled
|
||||||
|
toml::value v{
|
||||||
|
"foo", 3.14, 42, {1,2,3,4,5}, {{"key", "value"}}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
There is a workaround for this issue. By explicitly converting values into
|
||||||
|
`toml::value`, you can initialize `toml::value` with a heterogeneous array.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// OK!
|
||||||
|
toml::value v{
|
||||||
|
toml::value("foo"), toml::value(3.14), toml::value(42),
|
||||||
|
toml::value{1,2,3,4,5}, toml::value{{"key", "value"}}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The reason why the first example is not allowed is the following.
|
||||||
|
Let's assume that you are initializing a `toml::value` with a table.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// # expecting TOML table.
|
||||||
|
toml::value v{ // [v]
|
||||||
|
{"answer", 42}, // answer = 42
|
||||||
|
{"pi", 3.14}, // pi = 3.14
|
||||||
|
{"foo", "bar"} // foo = "bar"
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
This is indistinguishable from a (heterogeneous) TOML array definition.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
v = [
|
||||||
|
["answer", 42],
|
||||||
|
["pi", 3.14],
|
||||||
|
["foo", "bar"],
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
This means that the above C++ code makes constructor's overload resolution
|
||||||
|
ambiguous. So a constructor that allows both "table as an initializer-list" and
|
||||||
|
"heterogeneous array as an initializer-list" cannot be implemented.
|
||||||
|
|
||||||
|
Thus, although it is painful, you need to explicitly cast values into
|
||||||
|
`toml::value` when you initialize heterogeneous array in C++ code.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// You need to do this when you want to initialize hetero array.
|
||||||
|
toml::value v{
|
||||||
|
toml::value("foo"), toml::value(3.14), toml::value(42),
|
||||||
|
toml::value{1,2,3,4,5}, toml::value{{"key", "value"}}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Breaking Changes from v2
|
## Breaking Changes from v2
|
||||||
|
|
||||||
@@ -1465,11 +1776,18 @@ 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
|
||||||
|
- Jt Freeman (@blockparty-sh)
|
||||||
|
- Fixed feature test macro around `localtime_s`
|
||||||
|
- Suppress warnings in Debug mode
|
||||||
|
- OGAWA Kenichi (@kenichiice)
|
||||||
|
- Suppress warnings on intel compiler
|
||||||
|
|
||||||
## Licensing terms
|
## Licensing terms
|
||||||
|
|
||||||
This product is licensed under the terms of the [MIT License](LICENSE).
|
This product is licensed under the terms of the [MIT License](LICENSE).
|
||||||
|
|
||||||
- Copyright (c) 2017-2019 Toru Niina
|
- Copyright (c) 2017-2020 Toru Niina
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|||||||
@@ -39,6 +39,15 @@ set(TEST_NAMES
|
|||||||
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
|
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
|
||||||
CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA)
|
CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA)
|
||||||
CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
|
CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Werror" COMPILER_SUPPORTS_WERROR)
|
||||||
|
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wsign-conversion" COMPILER_SUPPORTS_WSIGN_CONVERSION)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wconversion" COMPILER_SUPPORTS_WCONVERSION)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wduplicated-cond" COMPILER_SUPPORTS_WDUPLICATED_COND)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wduplicated-branches" COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wlogical-op" COMPILER_SUPPORTS_WLOGICAL_OP)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wuseless-cast" COMPILER_SUPPORTS_WUSELESS_CAST)
|
||||||
|
CHECK_CXX_COMPILER_FLAG("-Wdouble-promotion" COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
|
||||||
|
|
||||||
if(COMPILER_SUPPORTS_WALL)
|
if(COMPILER_SUPPORTS_WALL)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||||
@@ -49,6 +58,38 @@ endif()
|
|||||||
if(COMPILER_SUPPORTS_WPEDANTIC)
|
if(COMPILER_SUPPORTS_WPEDANTIC)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||||
endif()
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WERROR)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WSIGN_CONVERSION)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WCONVERSION)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wconversion")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WDUPLICATED_COND)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-cond")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-branches")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WLOGICAL_OP)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wlogical-op")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WUSELESS_CAST)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuseless-cast")
|
||||||
|
endif()
|
||||||
|
if(COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdouble-promotion")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
"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)
|
||||||
@@ -96,6 +137,19 @@ foreach(TEST_NAME ${TEST_NAMES})
|
|||||||
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
||||||
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
|
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
|
||||||
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
if(toml11_TEST_WITH_ASAN)
|
||||||
|
set_target_properties(${TEST_NAME} PROPERTIES
|
||||||
|
COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer"
|
||||||
|
LINK_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
|
||||||
|
elseif(toml11_TEST_WITH_UBSAN)
|
||||||
|
set_target_properties(${TEST_NAME} PROPERTIES
|
||||||
|
COMPILE_FLAGS "-fsanitize=undefined"
|
||||||
|
LINK_FLAGS "-fsanitize=undefined")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
# Set the PATH to be able to find Boost DLL
|
# Set the PATH to be able to find Boost DLL
|
||||||
|
|||||||
@@ -80,10 +80,14 @@ BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
|
BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
|
||||||
{
|
{
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
BOOST_TEST_MESSAGE("heterogeneous array will be allowed in the next release");
|
||||||
|
#else
|
||||||
std::istringstream stream(std::string(
|
std::istringstream stream(std::string(
|
||||||
"a = [1, 1.0]\n"
|
"a = [1, 1.0]\n"
|
||||||
));
|
));
|
||||||
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
|
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
|
BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
|
||||||
|
|||||||
@@ -33,6 +33,29 @@ 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct foobar
|
||||||
|
{
|
||||||
|
foobar() = default; // later we use std::vector<foobar>, default ctor is required.
|
||||||
|
|
||||||
|
// via constructor
|
||||||
|
explicit foobar(const toml::value& v)
|
||||||
|
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
|
||||||
|
{}
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
} // extlib
|
} // extlib
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
@@ -54,6 +77,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 +124,29 @@ 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct foobar
|
||||||
|
{
|
||||||
|
foobar() = default; // later we use std::vector<foobar>, default ctor is required.
|
||||||
|
|
||||||
|
template<typename C, template<typename ...> class M, template<typename ...> class A>
|
||||||
|
explicit foobar(const toml::basic_value<C, M, A>& v)
|
||||||
|
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
|
||||||
|
{}
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
|
|
||||||
} // extlib2
|
} // extlib2
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
@@ -105,6 +169,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 +274,62 @@ 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_conversion_via_constructor)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::value v{{"a", 42}, {"b", "foobar"}};
|
||||||
|
|
||||||
|
const auto foobar = toml::get<extlib::foobar>(v);
|
||||||
|
BOOST_TEST(foobar.a == 42);
|
||||||
|
BOOST_TEST(foobar.b == "foobar");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::basic_value<toml::discard_comments, std::map> v{
|
||||||
|
{"a", 42}, {"b", "foobar"}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto foobar = toml::get<extlib2::foobar>(v);
|
||||||
|
BOOST_TEST(foobar.a == 42);
|
||||||
|
BOOST_TEST(foobar.b == "foobar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -288,5 +430,63 @@ BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
|||||||
BOOST_TEST(bars.at(2).b == "quux");
|
BOOST_TEST(bars.at(2).b == "quux");
|
||||||
BOOST_TEST(bars.at(3).b == "foobar");
|
BOOST_TEST(bars.at(3).b == "foobar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// via constructor
|
||||||
|
{
|
||||||
|
const toml::value v{
|
||||||
|
toml::table{{"a", 42}, {"b", "baz"}},
|
||||||
|
toml::table{{"a", 43}, {"b", "qux"}},
|
||||||
|
toml::table{{"a", 44}, {"b", "quux"}},
|
||||||
|
toml::table{{"a", 45}, {"b", "foobar"}}
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto foobars = toml::get<std::vector<extlib::foobar>>(v);
|
||||||
|
BOOST_TEST(foobars.size() == 4ul);
|
||||||
|
BOOST_TEST(foobars.at(0).a == 42);
|
||||||
|
BOOST_TEST(foobars.at(1).a == 43);
|
||||||
|
BOOST_TEST(foobars.at(2).a == 44);
|
||||||
|
BOOST_TEST(foobars.at(3).a == 45);
|
||||||
|
|
||||||
|
BOOST_TEST(foobars.at(0).b == "baz");
|
||||||
|
BOOST_TEST(foobars.at(1).b == "qux");
|
||||||
|
BOOST_TEST(foobars.at(2).b == "quux");
|
||||||
|
BOOST_TEST(foobars.at(3).b == "foobar");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
|
||||||
|
BOOST_TEST(foobars.size() == 4ul);
|
||||||
|
BOOST_TEST(foobars.at(0).a == 42);
|
||||||
|
BOOST_TEST(foobars.at(1).a == 43);
|
||||||
|
BOOST_TEST(foobars.at(2).a == 44);
|
||||||
|
BOOST_TEST(foobars.at(3).a == 45);
|
||||||
|
|
||||||
|
BOOST_TEST(foobars.at(0).b == "baz");
|
||||||
|
BOOST_TEST(foobars.at(1).b == "qux");
|
||||||
|
BOOST_TEST(foobars.at(2).b == "quux");
|
||||||
|
BOOST_TEST(foobars.at(3).b == "foobar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::basic_value<toml::discard_comments, std::map, std::deque>
|
||||||
|
v{
|
||||||
|
toml::table{{"a", 42}, {"b", "baz"}},
|
||||||
|
toml::table{{"a", 43}, {"b", "qux"}},
|
||||||
|
toml::table{{"a", 44}, {"b", "quux"}},
|
||||||
|
toml::table{{"a", 45}, {"b", "foobar"}}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
|
||||||
|
BOOST_TEST(foobars.size() == 4ul);
|
||||||
|
BOOST_TEST(foobars.at(0).a == 42);
|
||||||
|
BOOST_TEST(foobars.at(1).a == 43);
|
||||||
|
BOOST_TEST(foobars.at(2).a == 44);
|
||||||
|
BOOST_TEST(foobars.at(3).a == 45);
|
||||||
|
|
||||||
|
BOOST_TEST(foobars.at(0).b == "baz");
|
||||||
|
BOOST_TEST(foobars.at(1).b == "qux");
|
||||||
|
BOOST_TEST(foobars.at(2).b == "quux");
|
||||||
|
BOOST_TEST(foobars.at(3).b == "foobar");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,103 @@ 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_array_throws)
|
||||||
|
{
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// const-reference version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
const toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(v, 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
const toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// non-const reference version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(v, 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// move version
|
||||||
|
{
|
||||||
|
// value is not an array
|
||||||
|
toml::value v(true);
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not the expected type
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), 0), toml::type_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the value corresponding to the key is not found
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_CHECK_THROW(toml::find<toml::integer>(std::move(v), 6), std::out_of_range);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// the positive control.
|
||||||
|
toml::value v{1, 2, 3, 4, 5};
|
||||||
|
BOOST_TEST(3 == toml::find<int>(std::move(v), 2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
BOOST_AUTO_TEST_CASE(test_find_recursive)
|
||||||
@@ -74,6 +197,77 @@ 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>(v, a, "b", c, "d");
|
||||||
|
BOOST_TEST(42 == num3);
|
||||||
|
|
||||||
|
auto num4 = toml::find<toml::integer>(std::move(v), a, b, c, d);
|
||||||
|
BOOST_TEST(42 == num4);
|
||||||
|
}
|
||||||
|
// recursively search arrays
|
||||||
|
{
|
||||||
|
toml::value v{
|
||||||
|
toml::array{"array", "of", "string"},
|
||||||
|
toml::array{toml::array{1, 2, 3}, toml::array{3.14, 2.71}}
|
||||||
|
};
|
||||||
|
BOOST_TEST("array" == toml::find<std::string>(v, 0, 0));
|
||||||
|
BOOST_TEST("of" == toml::find<std::string>(v, 0, 1));
|
||||||
|
BOOST_TEST("string" == toml::find<std::string>(v, 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST(1 == toml::find<int>(v, 1, 0, 0));
|
||||||
|
BOOST_TEST(2 == toml::find<int>(v, 1, 0, 1));
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, 1, 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, 1, 1, 0));
|
||||||
|
BOOST_TEST(2.71 == toml::find<double>(v, 1, 1, 1));
|
||||||
|
|
||||||
|
// reference that can be used to modify the content
|
||||||
|
auto& num = toml::find<toml::integer>(v, 1, 0, 2);
|
||||||
|
num = 42;
|
||||||
|
BOOST_TEST( 1 == toml::find<int>(v, 1, 0, 0));
|
||||||
|
BOOST_TEST( 2 == toml::find<int>(v, 1, 0, 1));
|
||||||
|
BOOST_TEST(42 == toml::find<int>(v, 1, 0, 2));
|
||||||
|
|
||||||
|
// move value
|
||||||
|
auto num2 = toml::find<toml::integer>(std::move(v), 1, 0, 2);
|
||||||
|
BOOST_TEST(42 == num2);
|
||||||
|
}
|
||||||
|
// recursively search mixtures
|
||||||
|
{
|
||||||
|
toml::value v = toml::table{{"array", toml::array{
|
||||||
|
toml::array{1, 2, 3},
|
||||||
|
toml::array{
|
||||||
|
toml::table{{"foo", "bar"}, {"baz", "qux"}},
|
||||||
|
toml::table{{"pi", 3.14}, {"e", 2.71}}
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
|
||||||
|
BOOST_TEST(1 == toml::find<int>(v, "array", 0, 0));
|
||||||
|
BOOST_TEST(2 == toml::find<int>(v, "array", 0, 1));
|
||||||
|
BOOST_TEST(3 == toml::find<int>(v, "array", 0, 2));
|
||||||
|
|
||||||
|
BOOST_TEST("bar" == toml::find<std::string>(v, "array", 1, 0, "foo"));
|
||||||
|
BOOST_TEST("qux" == toml::find<std::string>(v, "array", 1, 0, "baz"));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, "pi"));
|
||||||
|
BOOST_TEST(2.71 == toml::find<double>(v, "array", 1, 1, "e"));
|
||||||
|
|
||||||
|
const std::string ar("array");
|
||||||
|
const auto ar_c = "array";
|
||||||
|
|
||||||
|
const std::string pi("pi");
|
||||||
|
const auto pi_c = "pi";
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, "pi"));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, pi));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, pi_c));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, "pi"));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, pi));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, pi_c));
|
||||||
|
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, pi));
|
||||||
|
BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, pi_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +279,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 +289,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 +299,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 +311,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 +323,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 +335,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 +347,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 +360,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 +374,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 +392,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 +409,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 +422,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 +441,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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,9 +449,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_ty
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
value_type v{{"key", 3.14}};
|
value_type v{{"key", 3.14}};
|
||||||
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(v, "key"));
|
const double ref(3.14);
|
||||||
BOOST_TEST(static_cast<double >(3.14) == toml::find<double >(v, "key"));
|
BOOST_TEST(static_cast<float >(ref) == toml::find<float >(v, "key"));
|
||||||
BOOST_TEST(static_cast<long double>(3.14) == toml::find<long double>(v, "key"));
|
BOOST_TEST( ref == toml::find<double >(v, "key"));
|
||||||
|
BOOST_TEST(static_cast<long double>(ref) == toml::find<long double>(v, "key"));
|
||||||
|
BOOST_TEST(static_cast<float >(ref) == toml::find<float >(std::move(v), "key"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +471,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
|
||||||
{
|
{
|
||||||
@@ -274,14 +514,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array, value_type, test_value_types
|
|||||||
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
||||||
|
|
||||||
std::array<int, 4> ary = toml::find<std::array<int, 4>>(v, "key");
|
std::array<int, 4> ary = toml::find<std::array<int, 4>>(v, "key");
|
||||||
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
BOOST_TEST(42 == ary.at(0));
|
||||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
BOOST_TEST(54 == ary.at(1));
|
||||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
BOOST_TEST(69 == ary.at(2));
|
||||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
BOOST_TEST(72 == ary.at(3));
|
||||||
|
|
||||||
std::tuple<int, short, unsigned, long> tpl =
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
toml::find<std::tuple<int, short, unsigned, long>>(v, "key");
|
toml::find<std::tuple<int, short, unsigned, long>>(v, "key");
|
||||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
BOOST_TEST( 42 == std::get<0>(tpl));
|
||||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
||||||
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
||||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||||
@@ -292,6 +532,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(42 == ary.at(0));
|
||||||
|
BOOST_TEST(54 == ary.at(1));
|
||||||
|
BOOST_TEST(69 == ary.at(2));
|
||||||
|
BOOST_TEST(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( 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 +610,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 +654,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 +684,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 +738,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 +806,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)
|
||||||
@@ -316,7 +375,17 @@ BOOST_AUTO_TEST_CASE(test_find_or_floating)
|
|||||||
toml::value v1{{"key", 42}};
|
toml::value v1{{"key", 42}};
|
||||||
toml::value v2{{"key", 3.14}};
|
toml::value v2{{"key", 3.14}};
|
||||||
BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f));
|
BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f));
|
||||||
BOOST_TEST(static_cast<float>(double(3.14)) == toml::find_or(v2, "key", 2.71f));
|
const double ref(3.14);
|
||||||
|
BOOST_TEST(static_cast<float>(ref) == toml::find_or(v2, "key", 2.71f));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1{{"key", 42}};
|
||||||
|
toml::value 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);
|
||||||
|
const double ref(3.14);
|
||||||
|
BOOST_TEST(static_cast<float>(ref) == moved2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,6 +414,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 +452,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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,9 +195,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_typ
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
value_type v(3.14);
|
value_type v(3.14);
|
||||||
BOOST_TEST(static_cast<float >(3.14) == toml::get<float >(v));
|
const double ref(3.14);
|
||||||
BOOST_TEST(static_cast<double >(3.14) == toml::get<double >(v));
|
BOOST_TEST(static_cast<float >(ref) == toml::get<float >(v));
|
||||||
BOOST_TEST(static_cast<long double>(3.14) == toml::get<long double>(v));
|
BOOST_TEST( ref == toml::get<double >(v));
|
||||||
|
BOOST_TEST(static_cast<long double>(ref) == toml::get<long double>(v));
|
||||||
|
BOOST_TEST(static_cast<float >(ref) == 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);
|
||||||
@@ -215,14 +262,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
|
|||||||
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
|
||||||
|
|
||||||
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
|
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
|
||||||
BOOST_TEST(static_cast<int>(42) == ary.at(0));
|
BOOST_TEST(42 == ary.at(0));
|
||||||
BOOST_TEST(static_cast<int>(54) == ary.at(1));
|
BOOST_TEST(54 == ary.at(1));
|
||||||
BOOST_TEST(static_cast<int>(69) == ary.at(2));
|
BOOST_TEST(69 == ary.at(2));
|
||||||
BOOST_TEST(static_cast<int>(72) == ary.at(3));
|
BOOST_TEST(72 == ary.at(3));
|
||||||
|
|
||||||
std::tuple<int, short, unsigned, long> tpl =
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
toml::get<std::tuple<int, short, unsigned, long>>(v);
|
toml::get<std::tuple<int, short, unsigned, long>>(v);
|
||||||
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
|
BOOST_TEST( 42 == std::get<0>(tpl));
|
||||||
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
|
||||||
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
|
||||||
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
|
||||||
@@ -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(42 == ary.at(0));
|
||||||
|
BOOST_TEST(54 == ary.at(1));
|
||||||
|
BOOST_TEST(69 == ary.at(2));
|
||||||
|
BOOST_TEST(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( 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,3 +128,47 @@ BOOST_AUTO_TEST_CASE(test_multiline_array_value)
|
|||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", toml::value(a));
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", toml::value(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_heterogeneous_array)
|
||||||
|
{
|
||||||
|
#ifndef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
|
BOOST_TEST_MESSAGE("In strict TOML v0.5.0, heterogeneous arrays are not allowed.");
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value("foo");
|
||||||
|
a[1] = toml::value(3.14);
|
||||||
|
a[2] = toml::value(42);
|
||||||
|
a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
|
||||||
|
a[4] = toml::value{{"key", "value"}};
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", 3.14, 42, [\"array\", \"of\", \"hetero-array\", 1], {key = \"value\"}]", toml::value(a));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value("foo");
|
||||||
|
a[1] = toml::value(3.14);
|
||||||
|
a[2] = toml::value(42);
|
||||||
|
a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
|
||||||
|
a[4] = toml::value{{"key", "value"}};
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n 3.14,\n 42,\n [\"array\", \"of\", \"hetero-array\", 1],\n {key = \"value\"},\n]", toml::value(a));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value("foo");
|
||||||
|
a[1] = toml::value(3.14);
|
||||||
|
a[2] = toml::value(42);
|
||||||
|
a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
|
||||||
|
a[4] = toml::value{{"key", "value"}};
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",#comment\n 3.14,#comment\n 42,#comment\n [\"array\", \"of\", \"hetero-array\", 1],#comment\n {key = \"value\"},#comment\n]#comment", toml::value(a));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value("foo");
|
||||||
|
a[1] = toml::value(3.14);
|
||||||
|
a[2] = toml::value(42);
|
||||||
|
a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
|
||||||
|
a[4] = toml::value{{"key", "value"}};
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n 3.14,\n 42,\n [\"array\",\n \"of\",\n \"hetero-array\",\n 1],\n {key = \"value\"},\n]", toml::value(a));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -46,3 +46,19 @@ BOOST_AUTO_TEST_CASE(test_inline_table_value)
|
|||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{type.name = \"pug\"}", value(t));
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{type.name = \"pug\"}", value(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_inline_table_immutability)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"a = {b = 1}\n"
|
||||||
|
"a.c = 2\n"));
|
||||||
|
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"a = {b = {c = 1}}\n"
|
||||||
|
"a.b.d = 2\n"));
|
||||||
|
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -111,3 +111,44 @@ BOOST_AUTO_TEST_CASE(test_literal_ml_string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_string_add_assign)
|
||||||
|
{
|
||||||
|
// string literal
|
||||||
|
{
|
||||||
|
toml::string str("foo");
|
||||||
|
str += "bar";
|
||||||
|
BOOST_TEST(str.str == "foobar");
|
||||||
|
}
|
||||||
|
// std::string
|
||||||
|
{
|
||||||
|
toml::string str("foo");
|
||||||
|
std::string str2("bar");
|
||||||
|
str += str2;
|
||||||
|
BOOST_TEST(str.str == "foobar");
|
||||||
|
}
|
||||||
|
// toml::string
|
||||||
|
{
|
||||||
|
toml::string str("foo");
|
||||||
|
toml::string str2("bar");
|
||||||
|
str += str2;
|
||||||
|
BOOST_TEST(str.str == "foobar");
|
||||||
|
}
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
// std::string_view
|
||||||
|
{
|
||||||
|
toml::string str("foo");
|
||||||
|
str += std::string_view("bar");
|
||||||
|
BOOST_TEST(str == "foobar");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// std::string += toml::string
|
||||||
|
{
|
||||||
|
std::string str("foo");
|
||||||
|
toml::string str2("bar");
|
||||||
|
str += str2;
|
||||||
|
BOOST_TEST(str == "foobar");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -905,3 +905,115 @@ 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_bracket)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}};
|
||||||
|
|
||||||
|
BOOST_TEST(v1["foo"].as_integer() == 42);
|
||||||
|
BOOST_TEST(v1["bar"].as_floating() == 3.14);
|
||||||
|
BOOST_TEST(v1["baz"].as_string() == "qux");
|
||||||
|
|
||||||
|
v1["qux"] = 54;
|
||||||
|
BOOST_TEST(v1["qux"].as_integer() == 54);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1;
|
||||||
|
v1["foo"] = 42;
|
||||||
|
|
||||||
|
BOOST_TEST(v1.is_table());
|
||||||
|
BOOST_TEST(v1["foo"].as_integer() == 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1{1,2,3,4,5};
|
||||||
|
|
||||||
|
BOOST_TEST(v1[0].as_integer() == 1);
|
||||||
|
BOOST_TEST(v1[1].as_integer() == 2);
|
||||||
|
BOOST_TEST(v1[2].as_integer() == 3);
|
||||||
|
BOOST_TEST(v1[3].as_integer() == 4);
|
||||||
|
BOOST_TEST(v1[4].as_integer() == 5);
|
||||||
|
|
||||||
|
BOOST_CHECK_THROW(v1["foo"], toml::type_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_map_methods)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}};
|
||||||
|
|
||||||
|
BOOST_TEST(v1.count("foo") == 1u);
|
||||||
|
BOOST_TEST(v1.count("bar") == 1u);
|
||||||
|
BOOST_TEST(v1.count("baz") == 1u);
|
||||||
|
BOOST_TEST(v1.count("qux") == 0u);
|
||||||
|
|
||||||
|
BOOST_TEST( v1.contains("foo"));
|
||||||
|
BOOST_TEST( v1.contains("bar"));
|
||||||
|
BOOST_TEST( v1.contains("baz"));
|
||||||
|
BOOST_TEST(!v1.contains("qux"));
|
||||||
|
|
||||||
|
BOOST_TEST(v1.size() == 3);
|
||||||
|
|
||||||
|
v1["qux"] = 54;
|
||||||
|
BOOST_TEST(v1.count("qux") == 1u);
|
||||||
|
BOOST_TEST(v1.contains("qux"));
|
||||||
|
BOOST_TEST(v1.size() == 4);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
BOOST_CHECK_THROW(v1.size() , toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.count("k") , toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.contains("k"), toml::type_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_vector_methods)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v1{1, 2, 3, 4, 5};
|
||||||
|
|
||||||
|
BOOST_TEST(v1.size() == 5);
|
||||||
|
|
||||||
|
v1.push_back(6);
|
||||||
|
BOOST_TEST(v1.size() == 6);
|
||||||
|
|
||||||
|
v1.emplace_back(6);
|
||||||
|
BOOST_TEST(v1.size() == 7);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
BOOST_CHECK_THROW(v1.size(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.push_back(1), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.emplace_back(1), toml::type_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
64
toml/color.hpp
Normal file
64
toml/color.hpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#ifndef TOML11_COLOR_HPP
|
||||||
|
#define TOML11_COLOR_HPP
|
||||||
|
#include <ostream>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#ifdef TOML11_COLORIZE_ERROR_MESSAGE
|
||||||
|
#define TOML11_ERROR_MESSAGE_COLORIZED true
|
||||||
|
#else
|
||||||
|
#define TOML11_ERROR_MESSAGE_COLORIZED false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
|
||||||
|
// put ANSI escape sequence to ostream
|
||||||
|
namespace color_ansi
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
inline int colorize_index()
|
||||||
|
{
|
||||||
|
static const int index = std::ios_base::xalloc();
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
inline std::ostream& colorize(std::ostream& os)
|
||||||
|
{
|
||||||
|
// by default, it is zero.
|
||||||
|
os.iword(detail::colorize_index()) = 1;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
inline std::ostream& nocolorize(std::ostream& os)
|
||||||
|
{
|
||||||
|
os.iword(detail::colorize_index()) = 0;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
inline std::ostream& reset (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[00m";} return os;}
|
||||||
|
inline std::ostream& bold (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[01m";} return os;}
|
||||||
|
inline std::ostream& grey (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[30m";} return os;}
|
||||||
|
inline std::ostream& red (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[31m";} return os;}
|
||||||
|
inline std::ostream& green (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[32m";} return os;}
|
||||||
|
inline std::ostream& yellow (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[33m";} return os;}
|
||||||
|
inline std::ostream& blue (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[34m";} return os;}
|
||||||
|
inline std::ostream& magenta(std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[35m";} return os;}
|
||||||
|
inline std::ostream& cyan (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[36m";} return os;}
|
||||||
|
inline std::ostream& white (std::ostream& os)
|
||||||
|
{if(os.iword(detail::colorize_index()) == 1) {os << "\033[37m";} return os;}
|
||||||
|
} // color_ansi
|
||||||
|
|
||||||
|
// ANSI escape sequence is the only and default colorization method currently
|
||||||
|
namespace color = color_ansi;
|
||||||
|
|
||||||
|
} // toml
|
||||||
|
#endif// TOML11_COLOR_HPP
|
||||||
@@ -45,6 +45,7 @@ inline std::string show_char(const char c)
|
|||||||
buf.fill('\0');
|
buf.fill('\0');
|
||||||
const auto r = std::snprintf(
|
const auto r = std::snprintf(
|
||||||
buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
|
buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
|
||||||
|
(void) r; // Unused variable warning
|
||||||
assert(r == static_cast<int>(buf.size()) - 1);
|
assert(r == static_cast<int>(buf.size()) - 1);
|
||||||
return std::string(buf.data());
|
return std::string(buf.data());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace toml
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
// TODO: find more sophisticated way to handle this
|
// TODO: find more sophisticated way to handle this
|
||||||
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE
|
#if _POSIX_C_SOURCE >= 1 || defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_POSIX_SOURCE)
|
||||||
inline std::tm localtime_s(const std::time_t* src)
|
inline std::tm localtime_s(const std::time_t* src)
|
||||||
{
|
{
|
||||||
std::tm dst;
|
std::tm dst;
|
||||||
@@ -28,6 +28,13 @@ inline std::tm localtime_s(const std::time_t* src)
|
|||||||
if (!result) { throw std::runtime_error("localtime_r failed."); }
|
if (!result) { throw std::runtime_error("localtime_r failed."); }
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
inline std::tm gmtime_s(const std::time_t* src)
|
||||||
|
{
|
||||||
|
std::tm dst;
|
||||||
|
const auto result = ::gmtime_r(src, &dst);
|
||||||
|
if (!result) { throw std::runtime_error("gmtime_r failed."); }
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
#elif _MSC_VER
|
#elif _MSC_VER
|
||||||
inline std::tm localtime_s(const std::time_t* src)
|
inline std::tm localtime_s(const std::time_t* src)
|
||||||
{
|
{
|
||||||
@@ -36,13 +43,26 @@ inline std::tm localtime_s(const std::time_t* src)
|
|||||||
if (result) { throw std::runtime_error("localtime_s failed."); }
|
if (result) { throw std::runtime_error("localtime_s failed."); }
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
#else
|
inline std::tm gmtime_s(const std::time_t* src)
|
||||||
|
{
|
||||||
|
std::tm dst;
|
||||||
|
const auto result = ::gmtime_s(&dst, src);
|
||||||
|
if (result) { throw std::runtime_error("gmtime_s failed."); }
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
#else // fallback. not threadsafe
|
||||||
inline std::tm localtime_s(const std::time_t* src)
|
inline std::tm localtime_s(const std::time_t* src)
|
||||||
{
|
{
|
||||||
const auto result = std::localtime(src);
|
const auto result = std::localtime(src);
|
||||||
if (!result) { throw std::runtime_error("localtime failed."); }
|
if (!result) { throw std::runtime_error("localtime failed."); }
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
inline std::tm gmtime_s(const std::time_t* src)
|
||||||
|
{
|
||||||
|
const auto result = std::gmtime(src);
|
||||||
|
if (!result) { throw std::runtime_error("gmtime failed."); }
|
||||||
|
return *result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
@@ -153,8 +173,8 @@ std::basic_ostream<charT, traits>&
|
|||||||
operator<<(std::basic_ostream<charT, traits>& os, const local_date& date)
|
operator<<(std::basic_ostream<charT, traits>& os, const local_date& date)
|
||||||
{
|
{
|
||||||
os << std::setfill('0') << std::setw(4) << static_cast<int>(date.year ) << '-';
|
os << std::setfill('0') << std::setw(4) << static_cast<int>(date.year ) << '-';
|
||||||
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.month + 1) << '-';
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.month) + 1 << '-';
|
||||||
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.day );
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.day ) ;
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,10 +398,31 @@ struct local_datetime
|
|||||||
{
|
{
|
||||||
using internal_duration =
|
using internal_duration =
|
||||||
typename std::chrono::system_clock::time_point::duration;
|
typename std::chrono::system_clock::time_point::duration;
|
||||||
|
|
||||||
|
// Normally DST begins at A.M. 3 or 4. If we re-use conversion operator
|
||||||
|
// of local_date and local_time independently, the conversion fails if
|
||||||
|
// it is the day when DST begins or ends. Since local_date considers the
|
||||||
|
// time is 00:00 A.M. and local_time does not consider DST because it
|
||||||
|
// does not have any date information. We need to consider both date and
|
||||||
|
// time information at the same time to convert it correctly.
|
||||||
|
|
||||||
|
std::tm t;
|
||||||
|
t.tm_sec = static_cast<int>(this->time.second);
|
||||||
|
t.tm_min = static_cast<int>(this->time.minute);
|
||||||
|
t.tm_hour = static_cast<int>(this->time.hour);
|
||||||
|
t.tm_mday = static_cast<int>(this->date.day);
|
||||||
|
t.tm_mon = static_cast<int>(this->date.month);
|
||||||
|
t.tm_year = static_cast<int>(this->date.year) - 1900;
|
||||||
|
t.tm_wday = 0; // the value will be ignored
|
||||||
|
t.tm_yday = 0; // the value will be ignored
|
||||||
|
t.tm_isdst = -1;
|
||||||
|
|
||||||
// std::mktime returns date as local time zone. no conversion needed
|
// std::mktime returns date as local time zone. no conversion needed
|
||||||
auto dt = std::chrono::system_clock::time_point(this->date);
|
auto dt = std::chrono::system_clock::from_time_t(std::mktime(&t));
|
||||||
dt += std::chrono::duration_cast<internal_duration>(
|
dt += std::chrono::duration_cast<internal_duration>(
|
||||||
std::chrono::nanoseconds(this->time));
|
std::chrono::milliseconds(this->time.millisecond) +
|
||||||
|
std::chrono::microseconds(this->time.microsecond) +
|
||||||
|
std::chrono::nanoseconds (this->time.nanosecond));
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,40 +488,71 @@ struct offset_datetime
|
|||||||
: date(dt.date), time(dt.time), offset(o)
|
: date(dt.date), time(dt.time), offset(o)
|
||||||
{}
|
{}
|
||||||
explicit offset_datetime(const local_datetime& ld)
|
explicit offset_datetime(const local_datetime& ld)
|
||||||
: date(ld.date), time(ld.time), offset(get_local_offset())
|
: date(ld.date), time(ld.time), offset(get_local_offset(nullptr))
|
||||||
|
// use the current local timezone offset
|
||||||
{}
|
{}
|
||||||
explicit offset_datetime(const std::chrono::system_clock::time_point& tp)
|
explicit offset_datetime(const std::chrono::system_clock::time_point& tp)
|
||||||
: offset_datetime(local_datetime(tp))
|
: offset(0, 0) // use gmtime
|
||||||
{}
|
{
|
||||||
|
const auto timet = std::chrono::system_clock::to_time_t(tp);
|
||||||
|
const auto tm = detail::gmtime_s(&timet);
|
||||||
|
this->date = local_date(tm);
|
||||||
|
this->time = local_time(tm);
|
||||||
|
}
|
||||||
explicit offset_datetime(const std::time_t& t)
|
explicit offset_datetime(const std::time_t& t)
|
||||||
: offset_datetime(local_datetime(t))
|
: offset(0, 0) // use gmtime
|
||||||
{}
|
{
|
||||||
|
const auto tm = detail::gmtime_s(&t);
|
||||||
|
this->date = local_date(tm);
|
||||||
|
this->time = local_time(tm);
|
||||||
|
}
|
||||||
explicit offset_datetime(const std::tm& t)
|
explicit offset_datetime(const std::tm& t)
|
||||||
: offset_datetime(local_datetime(t))
|
: offset(0, 0) // assume gmtime
|
||||||
{}
|
{
|
||||||
|
this->date = local_date(t);
|
||||||
|
this->time = local_time(t);
|
||||||
|
}
|
||||||
|
|
||||||
operator std::chrono::system_clock::time_point() const
|
operator std::chrono::system_clock::time_point() const
|
||||||
{
|
{
|
||||||
// get date-time
|
// get date-time
|
||||||
using internal_duration =
|
using internal_duration =
|
||||||
typename std::chrono::system_clock::time_point::duration;
|
typename std::chrono::system_clock::time_point::duration;
|
||||||
std::chrono::system_clock::time_point tp =
|
|
||||||
std::chrono::system_clock::time_point(this->date) +
|
|
||||||
std::chrono::duration_cast<internal_duration>(
|
|
||||||
std::chrono::nanoseconds(this->time));
|
|
||||||
|
|
||||||
// get date-time in UTC. let's say we are in +09:00 (JPN).
|
// first, convert it to local date-time information in the same way as
|
||||||
// writing 12:00:00 in +09:00 means 03:00:00Z. to represent
|
// local_datetime does. later we will use time_t to adjust time offset.
|
||||||
// 12:00:00Z, first we need to add +09:00.
|
std::tm t;
|
||||||
const auto ofs = get_local_offset();
|
t.tm_sec = static_cast<int>(this->time.second);
|
||||||
|
t.tm_min = static_cast<int>(this->time.minute);
|
||||||
|
t.tm_hour = static_cast<int>(this->time.hour);
|
||||||
|
t.tm_mday = static_cast<int>(this->date.day);
|
||||||
|
t.tm_mon = static_cast<int>(this->date.month);
|
||||||
|
t.tm_year = static_cast<int>(this->date.year) - 1900;
|
||||||
|
t.tm_wday = 0; // the value will be ignored
|
||||||
|
t.tm_yday = 0; // the value will be ignored
|
||||||
|
t.tm_isdst = -1;
|
||||||
|
const std::time_t tp_loc = std::mktime(std::addressof(t));
|
||||||
|
|
||||||
|
auto tp = std::chrono::system_clock::from_time_t(tp_loc);
|
||||||
|
tp += std::chrono::duration_cast<internal_duration>(
|
||||||
|
std::chrono::milliseconds(this->time.millisecond) +
|
||||||
|
std::chrono::microseconds(this->time.microsecond) +
|
||||||
|
std::chrono::nanoseconds (this->time.nanosecond));
|
||||||
|
|
||||||
|
// Since mktime uses local time zone, it should be corrected.
|
||||||
|
// `12:00:00+09:00` means `03:00:00Z`. So mktime returns `03:00:00Z` if
|
||||||
|
// we are in `+09:00` timezone. To represent `12:00:00Z` there, we need
|
||||||
|
// to add `+09:00` to `03:00:00Z`.
|
||||||
|
// Here, it uses the time_t converted from date-time info to handle
|
||||||
|
// daylight saving time.
|
||||||
|
const auto ofs = get_local_offset(std::addressof(tp_loc));
|
||||||
tp += std::chrono::hours (ofs.hour);
|
tp += std::chrono::hours (ofs.hour);
|
||||||
tp += std::chrono::minutes(ofs.minute);
|
tp += std::chrono::minutes(ofs.minute);
|
||||||
|
|
||||||
// here, tp represents 12:00:00 in UTC but we have offset information.
|
// We got `12:00:00Z` by correcting local timezone applied by mktime.
|
||||||
// we need to subtract it. For example, let's say the input is
|
// Then we will apply the offset. Let's say `12:00:00-08:00` is given.
|
||||||
// 12:00:00-08:00. now we have tp = 12:00:00Z as a result of the above
|
// And now, we have `12:00:00Z`. `12:00:00-08:00` means `20:00:00Z`.
|
||||||
// conversion. But the actual time we need to return is 20:00:00Z
|
// So we need to subtract the offset.
|
||||||
// because of -08:00.
|
|
||||||
tp -= std::chrono::minutes(this->offset);
|
tp -= std::chrono::minutes(this->offset);
|
||||||
return tp;
|
return tp;
|
||||||
}
|
}
|
||||||
@@ -500,11 +572,10 @@ struct offset_datetime
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static time_offset get_local_offset()
|
static time_offset get_local_offset(const std::time_t* tp)
|
||||||
{
|
{
|
||||||
// get current timezone
|
// get local timezone with the same date-time information as mktime
|
||||||
const auto tmp1 = std::time(nullptr);
|
const auto t = detail::localtime_s(tp);
|
||||||
const auto t = detail::localtime_s(&tmp1);
|
|
||||||
|
|
||||||
std::array<char, 6> buf;
|
std::array<char, 6> buf;
|
||||||
const auto result = std::strftime(buf.data(), 6, "%z", &t); // +hhmm\0
|
const auto result = std::strftime(buf.data(), 6, "%z", &t); // +hhmm\0
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_EXCEPTION_HPP
|
#ifndef TOML11_EXCEPTION_HPP
|
||||||
#define TOML11_EXCEPTION_HPP
|
#define TOML11_EXCEPTION_HPP
|
||||||
|
#include "source_location.hpp"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -11,15 +12,21 @@ namespace toml
|
|||||||
struct exception : public std::exception
|
struct exception : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit exception(const source_location& loc): loc_(loc) {}
|
||||||
virtual ~exception() noexcept override = default;
|
virtual ~exception() noexcept override = default;
|
||||||
virtual const char* what() const noexcept override {return "";}
|
virtual const char* what() const noexcept override {return "";}
|
||||||
|
virtual source_location const& location() const noexcept {return loc_;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
source_location loc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct syntax_error : public toml::exception
|
struct syntax_error : public toml::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit syntax_error(const std::string& what_arg) : what_(what_arg){}
|
explicit syntax_error(const std::string& what_arg, const source_location& loc)
|
||||||
explicit syntax_error(const char* what_arg) : what_(what_arg){}
|
: exception(loc), what_(what_arg)
|
||||||
|
{}
|
||||||
virtual ~syntax_error() noexcept override = default;
|
virtual ~syntax_error() noexcept override = default;
|
||||||
virtual const char* what() const noexcept override {return what_.c_str();}
|
virtual const char* what() const noexcept override {return what_.c_str();}
|
||||||
|
|
||||||
@@ -30,8 +37,9 @@ struct syntax_error : public toml::exception
|
|||||||
struct type_error : public toml::exception
|
struct type_error : public toml::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit type_error(const std::string& what_arg) : what_(what_arg){}
|
explicit type_error(const std::string& what_arg, const source_location& loc)
|
||||||
explicit type_error(const char* what_arg) : what_(what_arg){}
|
: exception(loc), what_(what_arg)
|
||||||
|
{}
|
||||||
virtual ~type_error() noexcept override = default;
|
virtual ~type_error() noexcept override = default;
|
||||||
virtual const char* what() const noexcept override {return what_.c_str();}
|
virtual const char* what() const noexcept override {return what_.c_str();}
|
||||||
|
|
||||||
@@ -42,10 +50,12 @@ struct type_error : public toml::exception
|
|||||||
struct internal_error : public toml::exception
|
struct internal_error : public toml::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit internal_error(const std::string& what_arg) : what_(what_arg){}
|
explicit internal_error(const std::string& what_arg, const source_location& loc)
|
||||||
explicit internal_error(const char* what_arg) : what_(what_arg){}
|
: exception(loc), what_(what_arg)
|
||||||
|
{}
|
||||||
virtual ~internal_error() noexcept override = default;
|
virtual ~internal_error() noexcept override = default;
|
||||||
virtual const char* what() const noexcept override {return what_.c_str();}
|
virtual const char* what() const noexcept override {return what_.c_str();}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string what_;
|
std::string what_;
|
||||||
};
|
};
|
||||||
|
|||||||
387
toml/get.hpp
387
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,26 +174,23 @@ 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:
|
||||||
{
|
{
|
||||||
throw type_error(detail::format_underline("[error] toml::value "
|
throw type_error(detail::format_underline("toml::value: "
|
||||||
"bad_cast to std::chrono::system_clock::time_point", {
|
"bad_cast to std::chrono::system_clock::time_point", {
|
||||||
{std::addressof(detail::get_region(v)),
|
{std::addressof(detail::get_region(v)),
|
||||||
concat_to_string("the actual type is ", v.type())}
|
concat_to_string("the actual type is ", v.type())}
|
||||||
}));
|
}), v.location());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,9 +256,18 @@ 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>&);
|
||||||
|
|
||||||
|
// T(const toml::value&) and T is not toml::basic_value
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
detail::enable_if_t<detail::conjunction<
|
||||||
|
detail::negation<detail::is_basic_value<T>>,
|
||||||
|
std::is_constructible<T, const basic_value<C, M, V>&>
|
||||||
|
>::value, T>
|
||||||
|
get(const basic_value<C, M, V>&);
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// array-like types; most likely STL container, like std::vector, etc.
|
// array-like types; most likely STL container, like std::vector, etc.
|
||||||
|
|
||||||
@@ -276,7 +282,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,13 +304,13 @@ 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())
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"[erorr] toml::get specified container size is ", container.size(),
|
"toml::get: specified container size is ", container.size(),
|
||||||
" but there are ", ar.size(), " elements in toml array."), {
|
" but there are ", ar.size(), " elements in toml array."), {
|
||||||
{std::addressof(detail::get_region(v)), "here"}
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
}));
|
}));
|
||||||
@@ -325,11 +331,11 @@ 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(
|
||||||
"[erorr] toml::get specified std::pair but there are ", ar.size(),
|
"toml::get: specified std::pair but there are ", ar.size(),
|
||||||
" elements in toml array."), {
|
" elements in toml array."), {
|
||||||
{std::addressof(detail::get_region(v)), "here"}
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
}));
|
}));
|
||||||
@@ -356,12 +362,12 @@ 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(
|
||||||
"[erorr] toml::get specified std::tuple with ",
|
"toml::get: specified std::tuple with ",
|
||||||
std::tuple_size<T>::value, "elements, but there are ", ar.size(),
|
std::tuple_size<T>::value, " elements, but there are ", ar.size(),
|
||||||
" elements in toml array."), {
|
" elements in toml array."), {
|
||||||
{std::addressof(detail::get_region(v)), "here"}
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
}));
|
}));
|
||||||
@@ -388,7 +394,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);
|
||||||
}
|
}
|
||||||
@@ -420,8 +426,19 @@ T get(const basic_value<C, M, V>& v)
|
|||||||
return ::toml::from<T>::from_toml(v);
|
return ::toml::from<T>::from_toml(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
detail::enable_if_t<detail::conjunction<
|
||||||
|
detail::negation<detail::is_basic_value<T>>,
|
||||||
|
std::is_constructible<T, const basic_value<C, M, V>&>
|
||||||
|
>::value, T>
|
||||||
|
get(const basic_value<C, M, V>& v)
|
||||||
|
{
|
||||||
|
return T(v);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// find 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,11 +446,11 @@ 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(
|
||||||
"[error] key \"", ky, "\" not found"), {
|
"key \"", ky, "\" not found"), {
|
||||||
{std::addressof(detail::get_region(v)), "in this table"}
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -443,11 +460,11 @@ 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(
|
||||||
"[error] key \"", ky, "\" not found"), {
|
"key \"", ky, "\" not found"), {
|
||||||
{std::addressof(detail::get_region(v)), "in this table"}
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -455,17 +472,63 @@ 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(
|
||||||
"[error] key \"", ky, "\" not found"), {
|
"key \"", ky, "\" not found"), {
|
||||||
{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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// find(value, idx)
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> const&
|
||||||
|
find(const basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
const auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ary.at(idx);
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V>& find(basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ary.at(idx);
|
||||||
|
}
|
||||||
|
template<typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
basic_value<C, M, V> find(basic_value<C, M, V>&& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return basic_value<C, M, V>(std::move(ary.at(idx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -476,11 +539,11 @@ 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(
|
||||||
"[error] key \"", ky, "\" not found"), {
|
"key \"", ky, "\" not found"), {
|
||||||
{std::addressof(detail::get_region(v)), "in this table"}
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -492,11 +555,11 @@ 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(
|
||||||
"[error] key \"", ky, "\" not found"), {
|
"key \"", ky, "\" not found"), {
|
||||||
{std::addressof(detail::get_region(v)), "in this table"}
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -508,68 +571,163 @@ 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(
|
||||||
"[error] key \"", ky, "\" not found"), {
|
"key \"", ky, "\" not found"), {
|
||||||
{std::addressof(detail::get_region(v)), "in this table"}
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return ::toml::get<T>(std::move(tab.at(ky)));
|
return ::toml::get<T>(std::move(tab.at(ky)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// find<T>(value, idx)
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))
|
||||||
|
find(const basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
const auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(ary.at(idx));
|
||||||
|
}
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
||||||
|
find(basic_value<C, M, V>& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
auto& ary = v.as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(ary.at(idx));
|
||||||
|
}
|
||||||
|
template<typename T, typename C,
|
||||||
|
template<typename ...> class M, template<typename ...> class V>
|
||||||
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
||||||
|
find(basic_value<C, M, V>&& v, const std::size_t idx)
|
||||||
|
{
|
||||||
|
typename basic_value<C, M, V>::array_type ary = std::move(v).as_array();
|
||||||
|
if(ary.size() <= idx)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"index ", idx, " is out of range"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this array"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(std::move(ary.at(idx)));
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// It suppresses warnings by -Wsign-conversion. Let's say we have the following
|
||||||
|
// code.
|
||||||
|
// ```cpp
|
||||||
|
// const auto x = toml::find<std::string>(data, "array", 0);
|
||||||
|
// ```
|
||||||
|
// Here, the type of literal number `0` is `int`. `int` is a signed integer.
|
||||||
|
// `toml::find` takes `std::size_t` as an index. So it causes implicit sign
|
||||||
|
// conversion and `-Wsign-conversion` warns about it. Using `0u` instead of `0`
|
||||||
|
// suppresses the warning, but it makes user code messy.
|
||||||
|
// To suppress this warning, we need to be aware of type conversion caused
|
||||||
|
// by `toml::find(v, key1, key2, ... keys)`. But the thing is that the types of
|
||||||
|
// keys can be any combination of {string-like, size_t-like}. Of course we can't
|
||||||
|
// write down all the combinations. Thus we need to use some function that
|
||||||
|
// recognize the type of argument and cast it into `std::string` or
|
||||||
|
// `std::size_t` depending on the context.
|
||||||
|
// `key_cast` does the job. It has 2 overloads. One is invoked when the
|
||||||
|
// argument type is an integer and cast the argument into `std::size_t`. The
|
||||||
|
// other is invoked when the argument type is not an integer, possibly one of
|
||||||
|
// std::string, const char[N] or const char*, and construct std::string from
|
||||||
|
// the argument.
|
||||||
|
// `toml::find(v, k1, k2, ... ks)` uses `key_cast` before passing `ks` to
|
||||||
|
// `toml::find(v, k)` to suppress -Wsign-conversion.
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
enable_if_t<conjunction<std::is_integral<remove_cvref_t<T>>,
|
||||||
|
negation<std::is_same<remove_cvref_t<T>, bool>>>::value, std::size_t>
|
||||||
|
key_cast(T&& v) noexcept
|
||||||
|
{
|
||||||
|
return std::size_t(v);
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
enable_if_t<negation<conjunction<std::is_integral<remove_cvref_t<T>>,
|
||||||
|
negation<std::is_same<remove_cvref_t<T>, bool>>>>::value, std::string>
|
||||||
|
key_cast(T&& v) noexcept
|
||||||
|
{
|
||||||
|
return std::string(std::forward<T>(v));
|
||||||
|
}
|
||||||
|
} // detail
|
||||||
|
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
const basic_value<C, M, V>&
|
const basic_value<C, M, V>&
|
||||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(v, detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
basic_value<C, M, V>&
|
basic_value<C, M, V>&
|
||||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(v, detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename C,
|
template<typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
basic_value<C, M, V>&&
|
basic_value<C, M, V>
|
||||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
return ::toml::find(::toml::find(std::move(v), std::forward<Key1>(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>()))
|
decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>()))
|
||||||
find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(v, detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
|
||||||
find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(v, detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
template<typename T, typename C,
|
template<typename T, typename C,
|
||||||
template<typename ...> class M, template<typename ...> class V,
|
template<typename ...> class M, template<typename ...> class V,
|
||||||
typename ... Ts>
|
typename Key1, typename Key2, typename ... Keys>
|
||||||
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
|
||||||
find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
|
find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys)
|
||||||
{
|
{
|
||||||
return ::toml::find<T>(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
|
return ::toml::find<T>(::toml::find(std::move(v), detail::key_cast(k1)),
|
||||||
|
detail::key_cast(k2), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -608,8 +766,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(...)
|
||||||
{
|
{
|
||||||
@@ -624,8 +781,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(...)
|
||||||
{
|
{
|
||||||
@@ -634,18 +790,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,14 +809,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(...)
|
||||||
{
|
{
|
||||||
@@ -675,7 +829,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(...)
|
||||||
{
|
{
|
||||||
@@ -684,18 +838,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,11 +863,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,24 +877,21 @@ 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,7 +918,7 @@ find_or(basic_value<C, M, V>& v, const toml::key& ky, basic_value<C, M, V>& 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 tab[ky];
|
return tab.at(ky);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C,
|
template<typename C,
|
||||||
@@ -779,7 +929,7 @@ find_or(basic_value<C, M, V>&& v, const toml::key& ky, basic_value<C, M, V>&& op
|
|||||||
if(!v.is_table()) {return opt;}
|
if(!v.is_table()) {return 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 opt;}
|
||||||
return std::move(tab[ky]);
|
return basic_value<C, M, V>(std::move(tab.at(ky)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -805,19 +955,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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -863,7 +1014,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));
|
||||||
@@ -874,19 +1025,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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,21 +1072,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,
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ inline ::toml::value operator"" _toml(const char* str, std::size_t len)
|
|||||||
}
|
}
|
||||||
else // none of them.
|
else // none of them.
|
||||||
{
|
{
|
||||||
throw ::toml::syntax_error(data.unwrap_err());
|
throw ::toml::syntax_error(data.unwrap_err(),
|
||||||
|
source_location(std::addressof(loc)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
425
toml/parser.hpp
425
toml/parser.hpp
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@
|
|||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_REGION_HPP
|
#ifndef TOML11_REGION_HPP
|
||||||
#define TOML11_REGION_HPP
|
#define TOML11_REGION_HPP
|
||||||
#include "exception.hpp"
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -10,6 +9,7 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include "color.hpp"
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
@@ -41,6 +41,7 @@ struct region_base
|
|||||||
region_base& operator=(region_base&& ) = default;
|
region_base& operator=(region_base&& ) = default;
|
||||||
|
|
||||||
virtual bool is_ok() const noexcept {return false;}
|
virtual bool is_ok() const noexcept {return false;}
|
||||||
|
virtual char front() const noexcept {return '\0';}
|
||||||
|
|
||||||
virtual std::string str() const {return std::string("unknown region");}
|
virtual std::string str() const {return std::string("unknown region");}
|
||||||
virtual std::string name() const {return std::string("unknown file");}
|
virtual std::string name() const {return std::string("unknown file");}
|
||||||
@@ -89,6 +90,7 @@ struct location final : public region_base
|
|||||||
~location() = default;
|
~location() = default;
|
||||||
|
|
||||||
bool is_ok() const noexcept override {return static_cast<bool>(source_);}
|
bool is_ok() const noexcept override {return static_cast<bool>(source_);}
|
||||||
|
char front() const noexcept override {return *iter_;}
|
||||||
|
|
||||||
// this const prohibits codes like `++(loc.iter())`.
|
// this const prohibits codes like `++(loc.iter())`.
|
||||||
const const_iterator iter() const noexcept {return iter_;}
|
const const_iterator iter() const noexcept {return iter_;}
|
||||||
@@ -231,16 +233,16 @@ struct region final : public region_base
|
|||||||
|
|
||||||
region& operator+=(const region& other)
|
region& operator+=(const region& other)
|
||||||
{
|
{
|
||||||
if(this->begin() != other.begin() || this->end() != other.end() ||
|
// different regions cannot be concatenated
|
||||||
this->last_ != other.first_)
|
assert(this->begin() == other.begin() && this->end() == other.end() &&
|
||||||
{
|
this->last_ == other.first_);
|
||||||
throw internal_error("invalid region concatenation");
|
|
||||||
}
|
|
||||||
this->last_ = other.last_;
|
this->last_ = other.last_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_ok() const noexcept override {return static_cast<bool>(source_);}
|
bool is_ok() const noexcept override {return static_cast<bool>(source_);}
|
||||||
|
char front() const noexcept override {return *first_;}
|
||||||
|
|
||||||
std::string str() const override {return make_string(first_, last_);}
|
std::string str() const override {return make_string(first_, last_);}
|
||||||
std::string line() const override
|
std::string line() const override
|
||||||
@@ -420,7 +422,8 @@ struct region final : public region_base
|
|||||||
// to show a better error message.
|
// to show a better error message.
|
||||||
inline std::string format_underline(const std::string& message,
|
inline std::string format_underline(const std::string& message,
|
||||||
const std::vector<std::pair<region_base const*, std::string>>& reg_com,
|
const std::vector<std::pair<region_base const*, std::string>>& reg_com,
|
||||||
const std::vector<std::string>& helps = {})
|
const std::vector<std::string>& helps = {},
|
||||||
|
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
||||||
{
|
{
|
||||||
assert(!reg_com.empty());
|
assert(!reg_com.empty());
|
||||||
|
|
||||||
@@ -434,7 +437,27 @@ inline std::string format_underline(const std::string& message,
|
|||||||
)->first->line_num().size());
|
)->first->line_num().size());
|
||||||
|
|
||||||
std::ostringstream retval;
|
std::ostringstream retval;
|
||||||
retval << message << '\n';
|
|
||||||
|
if(colorize)
|
||||||
|
{
|
||||||
|
retval << color::colorize; // turn on ANSI color
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
// Here, before `colorize` support, it does not output `[error]` prefix
|
||||||
|
// automatically. So some user may output it manually and this change may
|
||||||
|
// duplicate the prefix. To avoid it, check the first 7 characters and
|
||||||
|
// if it is "[error]", it removes that part from the message shown.
|
||||||
|
if(message.size() > 7 && message.substr(0, 7) == "[error]")
|
||||||
|
{
|
||||||
|
retval << color::bold << color::red << "[error]" << color::reset
|
||||||
|
<< color::bold << message.substr(7) << color::reset << '\n';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retval << color::bold << color::red << "[error] " << color::reset
|
||||||
|
<< color::bold << message << color::reset << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
for(auto iter = reg_com.begin(); iter != reg_com.end(); ++iter)
|
for(auto iter = reg_com.begin(); iter != reg_com.end(); ++iter)
|
||||||
{
|
{
|
||||||
@@ -442,34 +465,42 @@ inline std::string format_underline(const std::string& message,
|
|||||||
if(iter != reg_com.begin() &&
|
if(iter != reg_com.begin() &&
|
||||||
std::prev(iter)->first->name() == iter->first->name())
|
std::prev(iter)->first->name() == iter->first->name())
|
||||||
{
|
{
|
||||||
retval << "\n ...\n";
|
retval << color::bold << color::blue << "\n ...\n" << color::reset;
|
||||||
}
|
}
|
||||||
else // if filename differs, print " --> filename.toml"
|
else // if filename differs, print " --> filename.toml"
|
||||||
{
|
{
|
||||||
if(iter != reg_com.begin()) {retval << '\n';}
|
if(iter != reg_com.begin()) {retval << '\n';}
|
||||||
retval << " --> " << iter->first->name() << '\n';
|
retval << color::bold << color::blue << " --> " << color::reset
|
||||||
|
<< iter->first->name() << '\n';
|
||||||
|
// add one almost-empty line for readability
|
||||||
|
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ')
|
||||||
|
<< color::bold << color::blue << " | " << color::reset << '\n';
|
||||||
}
|
}
|
||||||
const region_base* const reg = iter->first;
|
const region_base* const reg = iter->first;
|
||||||
const std::string& comment = iter->second;
|
const std::string& comment = iter->second;
|
||||||
|
|
||||||
retval << ' ' << std::setw(line_num_width) << reg->line_num();
|
retval << ' ' << color::bold << color::blue << std::setw(line_num_width)
|
||||||
retval << " | " << reg->line() << '\n';
|
<< std::right << reg->line_num() << " | " << color::reset
|
||||||
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
|
<< reg->line() << '\n';
|
||||||
retval << " | " << make_string(reg->before(), ' ');
|
|
||||||
|
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ')
|
||||||
|
<< color::bold << color::blue << " | " << color::reset
|
||||||
|
<< make_string(reg->before(), ' ');
|
||||||
|
|
||||||
if(reg->size() == 1)
|
if(reg->size() == 1)
|
||||||
{
|
{
|
||||||
// invalid
|
// invalid
|
||||||
// ^------
|
// ^------
|
||||||
retval << '^';
|
retval << color::bold << color::red
|
||||||
retval << make_string(reg->after(), '-');
|
<< '^' << make_string(reg->after(), '-') << color::reset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// invalid
|
// invalid
|
||||||
// ~~~~~~~
|
// ~~~~~~~
|
||||||
const auto underline_len = std::min(reg->size(), reg->line().size());
|
const auto underline_len = std::min(reg->size(), reg->line().size());
|
||||||
retval << make_string(underline_len, '~');
|
retval << color::bold << color::red
|
||||||
|
<< make_string(underline_len, '~') << color::reset;
|
||||||
}
|
}
|
||||||
retval << ' ';
|
retval << ' ';
|
||||||
retval << comment;
|
retval << comment;
|
||||||
@@ -479,10 +510,10 @@ inline std::string format_underline(const std::string& message,
|
|||||||
{
|
{
|
||||||
retval << '\n';
|
retval << '\n';
|
||||||
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
|
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
|
||||||
retval << " | ";
|
retval << color::bold << color::blue << " | " << color::reset;
|
||||||
for(const auto help : helps)
|
for(const auto help : helps)
|
||||||
{
|
{
|
||||||
retval << "\nHint: ";
|
retval << color::bold << "\nHint: " << color::reset;
|
||||||
retval << help;
|
retval << help;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,8 +118,14 @@ struct serializer
|
|||||||
{
|
{
|
||||||
return token; // there is no exponent part. just return it.
|
return token; // there is no exponent part. just return it.
|
||||||
}
|
}
|
||||||
|
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||||
// zero-prefix in an exponent is NOT allowed in TOML.
|
// Although currently it is not released yet, TOML will allow
|
||||||
|
// zero-prefix in an exponent part such as 1.234e+01.
|
||||||
|
// The following code removes the zero prefixes.
|
||||||
|
// If the feature is activated, the following codes can be skipped.
|
||||||
|
return token;
|
||||||
|
#endif
|
||||||
|
// zero-prefix in an exponent is NOT allowed in TOML v0.5.0.
|
||||||
// remove it if it exists.
|
// remove it if it exists.
|
||||||
bool sign_exists = false;
|
bool sign_exists = false;
|
||||||
std::size_t zero_prefix = 0;
|
std::size_t zero_prefix = 0;
|
||||||
|
|||||||
@@ -48,7 +48,11 @@ struct source_location
|
|||||||
{
|
{
|
||||||
if(reg)
|
if(reg)
|
||||||
{
|
{
|
||||||
line_num_ = static_cast<std::uint_least32_t>(std::stoul(reg->line_num()));
|
if(reg->line_num() != detail::region_base().line_num())
|
||||||
|
{
|
||||||
|
line_num_ = static_cast<std::uint_least32_t>(
|
||||||
|
std::stoul(reg->line_num()));
|
||||||
|
}
|
||||||
column_num_ = static_cast<std::uint_least32_t>(reg->before() + 1);
|
column_num_ = static_cast<std::uint_least32_t>(reg->before() + 1);
|
||||||
region_size_ = static_cast<std::uint_least32_t>(reg->size());
|
region_size_ = static_cast<std::uint_least32_t>(reg->size());
|
||||||
file_name_ = reg->name();
|
file_name_ = reg->name();
|
||||||
|
|||||||
@@ -16,10 +16,9 @@ struct storage
|
|||||||
{
|
{
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
storage(value_type const& v): ptr(toml::make_unique<T>(v)) {}
|
explicit storage(value_type const& v): ptr(toml::make_unique<T>(v)) {}
|
||||||
storage(value_type&& v): ptr(toml::make_unique<T>(std::move(v))) {}
|
explicit storage(value_type&& v): ptr(toml::make_unique<T>(std::move(v))) {}
|
||||||
~storage() = default;
|
~storage() = default;
|
||||||
|
|
||||||
storage(const storage& rhs): ptr(toml::make_unique<T>(*rhs.ptr)) {}
|
storage(const storage& rhs): ptr(toml::make_unique<T>(*rhs.ptr)) {}
|
||||||
storage& operator=(const storage& rhs)
|
storage& operator=(const storage& rhs)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_STRING_HPP
|
#ifndef TOML11_STRING_HPP
|
||||||
#define TOML11_STRING_HPP
|
#define TOML11_STRING_HPP
|
||||||
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#if __cplusplus >= 201703L
|
#if __cplusplus >= 201703L
|
||||||
@@ -45,6 +46,11 @@ struct string
|
|||||||
operator std::string const& () const& noexcept {return str;}
|
operator std::string const& () const& noexcept {return str;}
|
||||||
operator std::string&& () && noexcept {return std::move(str);}
|
operator std::string&& () && noexcept {return std::move(str);}
|
||||||
|
|
||||||
|
string& operator+=(const char* rhs) {str += rhs; return *this;}
|
||||||
|
string& operator+=(const char rhs) {str += rhs; return *this;}
|
||||||
|
string& operator+=(const std::string& rhs) {str += rhs; return *this;}
|
||||||
|
string& operator+=(const string& rhs) {str += rhs.str; return *this;}
|
||||||
|
|
||||||
#if __cplusplus >= 201703L
|
#if __cplusplus >= 201703L
|
||||||
explicit string(std::string_view s): kind(string_t::basic), str(s){}
|
explicit string(std::string_view s): kind(string_t::basic), str(s){}
|
||||||
string(std::string_view s, string_t k): kind(k), str(s){}
|
string(std::string_view s, string_t k): kind(k), str(s){}
|
||||||
@@ -54,6 +60,8 @@ struct string
|
|||||||
|
|
||||||
explicit operator std::string_view() const noexcept
|
explicit operator std::string_view() const noexcept
|
||||||
{return std::string_view(str);}
|
{return std::string_view(str);}
|
||||||
|
|
||||||
|
string& operator+=(const std::string_view& rhs) {str += rhs; return *this;}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
string_t kind;
|
string_t kind;
|
||||||
|
|||||||
@@ -105,12 +105,20 @@ struct has_into_toml_method
|
|||||||
: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
|
: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
|
||||||
|
|
||||||
#ifdef __INTEL_COMPILER
|
#ifdef __INTEL_COMPILER
|
||||||
#undef decltype(...)
|
#undef decltype
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// C++17 and/or/not
|
// C++17 and/or/not
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
|
||||||
|
using std::conjunction;
|
||||||
|
using std::disjunction;
|
||||||
|
using std::negation;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template<typename ...> struct conjunction : std::true_type{};
|
template<typename ...> struct conjunction : std::true_type{};
|
||||||
template<typename T> struct conjunction<T> : T{};
|
template<typename T> struct conjunction<T> : T{};
|
||||||
template<typename T, typename ... Ts>
|
template<typename T, typename ... Ts>
|
||||||
@@ -128,6 +136,8 @@ struct disjunction<T, Ts...> :
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
|
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// type checkers
|
// type checkers
|
||||||
|
|
||||||
@@ -182,6 +192,13 @@ struct is_basic_value<::toml::basic_value<C, M, V>>: std::true_type{};
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// C++14 index_sequence
|
// C++14 index_sequence
|
||||||
|
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
|
||||||
|
using std::index_sequence;
|
||||||
|
using std::make_index_sequence;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template<std::size_t ... Ns> struct index_sequence{};
|
template<std::size_t ... Ns> struct index_sequence{};
|
||||||
|
|
||||||
template<typename IS, std::size_t N> struct push_back_index_sequence{};
|
template<typename IS, std::size_t N> struct push_back_index_sequence{};
|
||||||
@@ -205,11 +222,22 @@ struct index_sequence_maker<0>
|
|||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
using make_index_sequence = typename index_sequence_maker<N-1>::type;
|
using make_index_sequence = typename index_sequence_maker<N-1>::type;
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 2014
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// C++14 enable_if_t
|
// C++14 enable_if_t
|
||||||
|
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
|
||||||
|
using std::enable_if_t;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template<bool B, typename T>
|
template<bool B, typename T>
|
||||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 2014
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// return_type_of_t
|
// return_type_of_t
|
||||||
|
|
||||||
@@ -240,6 +268,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
|
||||||
|
|||||||
@@ -20,12 +20,20 @@
|
|||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template<typename T, typename ... Ts>
|
template<typename T, typename ... Ts>
|
||||||
inline std::unique_ptr<T> make_unique(Ts&& ... args)
|
inline std::unique_ptr<T> make_unique(Ts&& ... args)
|
||||||
{
|
{
|
||||||
return std::unique_ptr<T>(new T(std::forward<Ts>(args)...));
|
return std::unique_ptr<T>(new T(std::forward<Ts>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 2014
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -76,10 +84,10 @@ std::string concat_to_string(Ts&& ... args)
|
|||||||
return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...);
|
return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<typename T>
|
||||||
T from_string(const std::string& str, U&& opt)
|
T from_string(const std::string& str, T opt)
|
||||||
{
|
{
|
||||||
T v(static_cast<T>(std::forward<U>(opt)));
|
T v(opt);
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> v;
|
iss >> v;
|
||||||
return v;
|
return v;
|
||||||
|
|||||||
328
toml/value.hpp
328
toml/value.hpp
@@ -32,10 +32,10 @@ template<value_t Expected,
|
|||||||
throw_bad_cast(value_t actual, const ::toml::basic_value<C, T, A>& v)
|
throw_bad_cast(value_t actual, const ::toml::basic_value<C, T, A>& v)
|
||||||
{
|
{
|
||||||
throw type_error(detail::format_underline(concat_to_string(
|
throw type_error(detail::format_underline(concat_to_string(
|
||||||
"[error] toml::value bad_cast to ", Expected), {
|
"toml::value: bad_cast to ", Expected), {
|
||||||
{std::addressof(get_region(v)),
|
{std::addressof(get_region(v)),
|
||||||
concat_to_string("the actual type is ", actual)}
|
concat_to_string("the actual type is ", actual)}
|
||||||
}));
|
}), v.location());
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch by `value_t` and call the corresponding `value::as_xxx()`. {{{
|
// switch by `value_t` and call the corresponding `value::as_xxx()`. {{{
|
||||||
@@ -529,14 +529,6 @@ class basic_value
|
|||||||
assigner(this->boolean_, b);
|
assigner(this->boolean_, b);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(boolean b, detail::region<Container> reg)
|
|
||||||
: type_(value_t::boolean),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->boolean_, b);
|
|
||||||
}
|
|
||||||
basic_value(boolean b, std::vector<std::string> comments)
|
basic_value(boolean b, std::vector<std::string> comments)
|
||||||
: type_(value_t::boolean),
|
: type_(value_t::boolean),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -557,19 +549,6 @@ class basic_value
|
|||||||
assigner(this->integer_, static_cast<integer>(i));
|
assigner(this->integer_, static_cast<integer>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
|
||||||
detail::conjunction<
|
|
||||||
std::is_integral<T>,
|
|
||||||
detail::negation<std::is_same<T, boolean>>
|
|
||||||
>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
basic_value(T i, detail::region<Container> reg)
|
|
||||||
: type_(value_t::integer),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->integer_, static_cast<integer>(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename std::enable_if<detail::conjunction<
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
|
std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
|
||||||
std::nullptr_t>::type = nullptr>
|
std::nullptr_t>::type = nullptr>
|
||||||
@@ -604,15 +583,6 @@ class basic_value
|
|||||||
assigner(this->floating_, static_cast<floating>(f));
|
assigner(this->floating_, static_cast<floating>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
|
||||||
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
basic_value(T f, detail::region<Container> reg)
|
|
||||||
: type_(value_t::floating),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->floating_, static_cast<floating>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename std::enable_if<
|
template<typename T, typename std::enable_if<
|
||||||
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
@@ -643,14 +613,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->string_, std::move(s));
|
assigner(this->string_, std::move(s));
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(toml::string s, detail::region<Container> reg)
|
|
||||||
: type_(value_t::string),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->string_, std::move(s));
|
|
||||||
}
|
|
||||||
basic_value& operator=(toml::string s)
|
basic_value& operator=(toml::string s)
|
||||||
{
|
{
|
||||||
this->cleanup();
|
this->cleanup();
|
||||||
@@ -782,14 +744,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->local_date_, ld);
|
assigner(this->local_date_, ld);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const local_date& ld, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_date),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->local_date_, ld);
|
|
||||||
}
|
|
||||||
basic_value& operator=(const local_date& ld)
|
basic_value& operator=(const local_date& ld)
|
||||||
{
|
{
|
||||||
this->cleanup();
|
this->cleanup();
|
||||||
@@ -814,14 +768,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->local_time_, lt);
|
assigner(this->local_time_, lt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const local_time& lt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_time),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->local_time_, lt);
|
|
||||||
}
|
|
||||||
basic_value(const local_time& lt, std::vector<std::string> comments)
|
basic_value(const local_time& lt, std::vector<std::string> comments)
|
||||||
: type_(value_t::local_time),
|
: type_(value_t::local_time),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -872,14 +818,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->local_datetime_, ldt);
|
assigner(this->local_datetime_, ldt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const local_datetime& ldt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_datetime),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->local_datetime_, ldt);
|
|
||||||
}
|
|
||||||
basic_value(const local_datetime& ldt, std::vector<std::string> comments)
|
basic_value(const local_datetime& ldt, std::vector<std::string> comments)
|
||||||
: type_(value_t::local_datetime),
|
: type_(value_t::local_datetime),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -904,14 +842,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->offset_datetime_, odt);
|
assigner(this->offset_datetime_, odt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const offset_datetime& odt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::offset_datetime),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->offset_datetime_, odt);
|
|
||||||
}
|
|
||||||
basic_value(const offset_datetime& odt, std::vector<std::string> comments)
|
basic_value(const offset_datetime& odt, std::vector<std::string> comments)
|
||||||
: type_(value_t::offset_datetime),
|
: type_(value_t::offset_datetime),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -958,14 +888,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->array_, ary);
|
assigner(this->array_, ary);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const array_type& ary, detail::region<Container> reg)
|
|
||||||
: type_(value_t::array),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->array_, ary);
|
|
||||||
}
|
|
||||||
basic_value(const array_type& ary, std::vector<std::string> comments)
|
basic_value(const array_type& ary, std::vector<std::string> comments)
|
||||||
: type_(value_t::array),
|
: type_(value_t::array),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -1079,14 +1001,6 @@ class basic_value
|
|||||||
{
|
{
|
||||||
assigner(this->table_, tab);
|
assigner(this->table_, tab);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
|
||||||
basic_value(const table_type& tab, detail::region<Container> reg)
|
|
||||||
: type_(value_t::table),
|
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
|
||||||
comments_(region_info_->comments())
|
|
||||||
{
|
|
||||||
assigner(this->table_, tab);
|
|
||||||
}
|
|
||||||
basic_value(const table_type& tab, std::vector<std::string> comments)
|
basic_value(const table_type& tab, std::vector<std::string> comments)
|
||||||
: type_(value_t::table),
|
: type_(value_t::table),
|
||||||
region_info_(std::make_shared<region_base>(region_base{})),
|
region_info_(std::make_shared<region_base>(region_base{})),
|
||||||
@@ -1216,6 +1130,93 @@ class basic_value
|
|||||||
}
|
}
|
||||||
|
|
||||||
// for internal use ------------------------------------------------------
|
// for internal use ------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Those constructors take detail::region that contains parse result.
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(boolean b, detail::region<Container> reg)
|
||||||
|
: type_(value_t::boolean),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->boolean_, b);
|
||||||
|
}
|
||||||
|
template<typename T, typename Container, typename std::enable_if<
|
||||||
|
detail::conjunction<
|
||||||
|
std::is_integral<T>, detail::negation<std::is_same<T, boolean>>
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
basic_value(T i, detail::region<Container> reg)
|
||||||
|
: type_(value_t::integer),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->integer_, static_cast<integer>(i));
|
||||||
|
}
|
||||||
|
template<typename T, typename Container, typename std::enable_if<
|
||||||
|
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
basic_value(T f, detail::region<Container> reg)
|
||||||
|
: type_(value_t::floating),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->floating_, static_cast<floating>(f));
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(toml::string s, detail::region<Container> reg)
|
||||||
|
: type_(value_t::string),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->string_, std::move(s));
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const local_date& ld, detail::region<Container> reg)
|
||||||
|
: type_(value_t::local_date),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->local_date_, ld);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const local_time& lt, detail::region<Container> reg)
|
||||||
|
: type_(value_t::local_time),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->local_time_, lt);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const local_datetime& ldt, detail::region<Container> reg)
|
||||||
|
: type_(value_t::local_datetime),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->local_datetime_, ldt);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const offset_datetime& odt, detail::region<Container> reg)
|
||||||
|
: type_(value_t::offset_datetime),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->offset_datetime_, odt);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const array_type& ary, detail::region<Container> reg)
|
||||||
|
: type_(value_t::array),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->array_, ary);
|
||||||
|
}
|
||||||
|
template<typename Container>
|
||||||
|
basic_value(const table_type& tab, detail::region<Container> reg)
|
||||||
|
: type_(value_t::table),
|
||||||
|
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
||||||
|
comments_(region_info_->comments())
|
||||||
|
{
|
||||||
|
assigner(this->table_, tab);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
template<typename T, typename Container, typename std::enable_if<
|
||||||
detail::is_exact_toml_type<T, value_type>::value,
|
detail::is_exact_toml_type<T, value_type>::value,
|
||||||
@@ -1247,7 +1248,7 @@ class basic_value
|
|||||||
bool is_array() const noexcept {return this->is(value_t::array );}
|
bool is_array() const noexcept {return this->is(value_t::array );}
|
||||||
bool is_table() const noexcept {return this->is(value_t::table );}
|
bool is_table() const noexcept {return this->is(value_t::table );}
|
||||||
|
|
||||||
value_t type() const {return type_;}
|
value_t type() const noexcept {return type_;}
|
||||||
|
|
||||||
template<value_t T>
|
template<value_t T>
|
||||||
typename detail::enum_to_type<T, value_type>::type& cast() &
|
typename detail::enum_to_type<T, value_type>::type& cast() &
|
||||||
@@ -1567,6 +1568,140 @@ 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& operator[](const key& k)
|
||||||
|
{
|
||||||
|
if(this->is_uninitialized())
|
||||||
|
{
|
||||||
|
*this = table_type{};
|
||||||
|
}
|
||||||
|
return this->as_table()[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);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type& operator[](const std::size_t idx) noexcept
|
||||||
|
{
|
||||||
|
return this->as_array(std::nothrow)[idx];
|
||||||
|
}
|
||||||
|
value_type const& operator[](const std::size_t idx) const noexcept
|
||||||
|
{
|
||||||
|
return this->as_array(std::nothrow)[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const value_type& x)
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::array)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::push_back(value): bad_cast to array type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
this->as_array(std::nothrow).push_back(x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void push_back(value_type&& x)
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::array)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::push_back(value): bad_cast to array type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
this->as_array(std::nothrow).push_back(std::move(x));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ... Ts>
|
||||||
|
value_type& emplace_back(Ts&& ... args)
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::array)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::emplace_back(value): bad_cast to array type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
this->as_array(std::nothrow).emplace_back(std::forward<Ts>(args) ...);
|
||||||
|
return this->as_array(std::nothrow).back();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const
|
||||||
|
{
|
||||||
|
switch(this->type_)
|
||||||
|
{
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
return this->as_array().size();
|
||||||
|
}
|
||||||
|
case value_t::table:
|
||||||
|
{
|
||||||
|
return this->as_table().size();
|
||||||
|
}
|
||||||
|
case value_t::string:
|
||||||
|
{
|
||||||
|
return this->as_string().str.size();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::size(): bad_cast to container types", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t count(const key_type& k) const
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::table)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::count(key): bad_cast to table type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
return this->as_table().count(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const key_type& k) const
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::table)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(
|
||||||
|
"toml::value::contains(key): bad_cast to table type", {
|
||||||
|
{this->region_info_.get(),
|
||||||
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
|
}), this->location());
|
||||||
|
}
|
||||||
|
return (this->as_table().count(k) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
source_location location() const
|
source_location location() const
|
||||||
{
|
{
|
||||||
return source_location(this->region_info_.get());
|
return source_location(this->region_info_.get());
|
||||||
@@ -1821,25 +1956,27 @@ operator>=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
|
|||||||
template<typename C, template<typename ...> class T, template<typename ...> class A>
|
template<typename C, template<typename ...> class T, template<typename ...> class A>
|
||||||
inline std::string format_error(const std::string& err_msg,
|
inline std::string format_error(const std::string& err_msg,
|
||||||
const basic_value<C, T, A>& v, const std::string& comment,
|
const basic_value<C, T, A>& v, const std::string& comment,
|
||||||
std::vector<std::string> hints = {})
|
std::vector<std::string> hints = {},
|
||||||
|
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
||||||
{
|
{
|
||||||
return detail::format_underline(err_msg,
|
return detail::format_underline(err_msg,
|
||||||
std::vector<std::pair<detail::region_base const*, std::string>>{
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
||||||
{std::addressof(detail::get_region(v)), comment}
|
{std::addressof(detail::get_region(v)), comment}
|
||||||
}, std::move(hints));
|
}, std::move(hints), colorize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C, template<typename ...> class T, template<typename ...> class A>
|
template<typename C, template<typename ...> class T, template<typename ...> class A>
|
||||||
inline std::string format_error(const std::string& err_msg,
|
inline std::string format_error(const std::string& err_msg,
|
||||||
const toml::basic_value<C, T, A>& v1, const std::string& comment1,
|
const toml::basic_value<C, T, A>& v1, const std::string& comment1,
|
||||||
const toml::basic_value<C, T, A>& v2, const std::string& comment2,
|
const toml::basic_value<C, T, A>& v2, const std::string& comment2,
|
||||||
std::vector<std::string> hints = {})
|
std::vector<std::string> hints = {},
|
||||||
|
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
||||||
{
|
{
|
||||||
return detail::format_underline(err_msg,
|
return detail::format_underline(err_msg,
|
||||||
std::vector<std::pair<detail::region_base const*, std::string>>{
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
||||||
{std::addressof(detail::get_region(v1)), comment1},
|
{std::addressof(detail::get_region(v1)), comment1},
|
||||||
{std::addressof(detail::get_region(v2)), comment2}
|
{std::addressof(detail::get_region(v2)), comment2}
|
||||||
}, std::move(hints));
|
}, std::move(hints), colorize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C, template<typename ...> class T, template<typename ...> class A>
|
template<typename C, template<typename ...> class T, template<typename ...> class A>
|
||||||
@@ -1847,14 +1984,15 @@ inline std::string format_error(const std::string& err_msg,
|
|||||||
const toml::basic_value<C, T, A>& v1, const std::string& comment1,
|
const toml::basic_value<C, T, A>& v1, const std::string& comment1,
|
||||||
const toml::basic_value<C, T, A>& v2, const std::string& comment2,
|
const toml::basic_value<C, T, A>& v2, const std::string& comment2,
|
||||||
const toml::basic_value<C, T, A>& v3, const std::string& comment3,
|
const toml::basic_value<C, T, A>& v3, const std::string& comment3,
|
||||||
std::vector<std::string> hints = {})
|
std::vector<std::string> hints = {},
|
||||||
|
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
||||||
{
|
{
|
||||||
return detail::format_underline(err_msg,
|
return detail::format_underline(err_msg,
|
||||||
std::vector<std::pair<detail::region_base const*, std::string>>{
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
||||||
{std::addressof(detail::get_region(v1)), comment1},
|
{std::addressof(detail::get_region(v1)), comment1},
|
||||||
{std::addressof(detail::get_region(v2)), comment2},
|
{std::addressof(detail::get_region(v2)), comment2},
|
||||||
{std::addressof(detail::get_region(v3)), comment3}
|
{std::addressof(detail::get_region(v3)), comment3}
|
||||||
}, std::move(hints));
|
}, std::move(hints), colorize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Visitor, typename C,
|
template<typename Visitor, typename C,
|
||||||
|
|||||||
Reference in New Issue
Block a user