mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
199 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
717f5929c2 | ||
|
|
81abb6c9d7 | ||
|
|
8bba3c8a14 | ||
|
|
b13e727b90 | ||
|
|
d352c9e66f | ||
|
|
c0aaba06d0 | ||
|
|
1633268d57 | ||
|
|
3bf1c2b820 | ||
|
|
4dbd2cb9fe | ||
|
|
65124a8d2e | ||
|
|
1b78f161f5 | ||
|
|
0ce259ada0 | ||
|
|
74da49f87f | ||
|
|
d5d697639c | ||
|
|
0b365ca7d3 | ||
|
|
db6f3d5d11 | ||
|
|
87be890e07 | ||
|
|
d72dc706d0 | ||
|
|
4cbbcd8f62 | ||
|
|
a2631ecacb | ||
|
|
4bcc5e8375 | ||
|
|
90f84000ba | ||
|
|
20a13754a7 | ||
|
|
aa7b9a3965 | ||
|
|
84ac1d10f3 | ||
|
|
0d623856a7 | ||
|
|
ec0d4e4e8c | ||
|
|
80ea736b3f | ||
|
|
ebaa5dfb51 | ||
|
|
f3bdf083fe | ||
|
|
1ce54a9cf9 | ||
|
|
6383a93ce7 | ||
|
|
01aa2ef5b2 | ||
|
|
819351f5a4 | ||
|
|
2967cebfb3 | ||
|
|
32e9a2c1c7 | ||
|
|
8e0a40a1aa | ||
|
|
e460826084 | ||
|
|
aa3445f38c | ||
|
|
408b7bf35e | ||
|
|
6185dfee14 | ||
|
|
37aa2739a5 | ||
|
|
d061c33a16 | ||
|
|
0c7d2d07d4 | ||
|
|
62cf4373bd | ||
|
|
a74ad23514 | ||
|
|
2d9b4992ec | ||
|
|
82e8c1e68b | ||
|
|
46be054ce9 | ||
|
|
789d784769 | ||
|
|
81deb8efde | ||
|
|
072dccd05d | ||
|
|
637c99d637 | ||
|
|
0f48852730 | ||
|
|
0499b2907d | ||
|
|
61e69c9251 | ||
|
|
4a560ea1e5 | ||
|
|
c5b6ee6f81 | ||
|
|
1a7bf63622 | ||
|
|
8847cdc0a9 | ||
|
|
c82e76a111 | ||
|
|
4db486d76d | ||
|
|
91966a6917 | ||
|
|
b3917aaadf | ||
|
|
ba307003c4 | ||
|
|
21fd1271d9 | ||
|
|
f9ab7d6f56 | ||
|
|
0a3a41a708 | ||
|
|
6c2a536fa5 | ||
|
|
26eced3640 | ||
|
|
6f950c9ec8 | ||
|
|
ea13e40889 | ||
|
|
595fb1aef3 | ||
|
|
18986978fb | ||
|
|
c3cb22a789 | ||
|
|
5aebd6b562 | ||
|
|
4c13085b35 | ||
|
|
8709e8a14e | ||
|
|
9eea46ec01 | ||
|
|
2e9f937c43 | ||
|
|
65b10b6537 | ||
|
|
b51a8d5966 | ||
|
|
55e3d70869 | ||
|
|
20ba57e389 | ||
|
|
39bc3c64fe | ||
|
|
40ccf1d912 | ||
|
|
982ae36428 | ||
|
|
d6714ec450 | ||
|
|
773c3816be | ||
|
|
1b417ddc7a | ||
|
|
7a0ecf977d | ||
|
|
aade704411 | ||
|
|
ca3f6102ef | ||
|
|
4a58b629ce | ||
|
|
3adba237b8 | ||
|
|
ccf03d9291 | ||
|
|
30ae90ebd5 | ||
|
|
d5369c3429 | ||
|
|
48f2f0555d | ||
|
|
f40fd12e25 | ||
|
|
65c2c3c238 | ||
|
|
891a61a5e3 | ||
|
|
1e6f30f6fa | ||
|
|
02346a3126 | ||
|
|
1908f18e95 | ||
|
|
3bfa7f09ba | ||
|
|
243f43fafd | ||
|
|
66e27a94b6 | ||
|
|
227688ec63 | ||
|
|
e761a503c0 | ||
|
|
209ad79a8f | ||
|
|
cdf209d7f6 | ||
|
|
77ab391885 | ||
|
|
6628fe5ace | ||
|
|
f3e3000d45 | ||
|
|
f7380c6e32 | ||
|
|
d86870e038 | ||
|
|
0908806915 | ||
|
|
d17c192681 | ||
|
|
cad8f51256 | ||
|
|
43014c6619 | ||
|
|
30a41aa710 | ||
|
|
04bfeba3f2 | ||
|
|
190636b791 | ||
|
|
31e450f9af | ||
|
|
b1b72a94a8 | ||
|
|
6929bcdf78 | ||
|
|
fd063af7ce | ||
|
|
df6dcbc4ed | ||
|
|
9b8db6a225 | ||
|
|
76863cb27f | ||
|
|
514df99e40 | ||
|
|
055353a460 | ||
|
|
9eb4008d6d | ||
|
|
a04544637b | ||
|
|
4c7dc17b78 | ||
|
|
59aaaab436 | ||
|
|
61dfa4a2dc | ||
|
|
ca337a1110 | ||
|
|
510e10de95 | ||
|
|
0babe8d589 | ||
|
|
5b2ce26721 | ||
|
|
db4d99cd4f | ||
|
|
74ceceef73 | ||
|
|
360e890cc0 | ||
|
|
46b35870c5 | ||
|
|
dddcecb034 | ||
|
|
c4c416e8b2 | ||
|
|
6693ec78f4 | ||
|
|
dc112bd6c1 | ||
|
|
084e82a8a9 | ||
|
|
f5079a7892 | ||
|
|
d90ffb63c6 | ||
|
|
b0ed122214 | ||
|
|
d88521d63c | ||
|
|
2accc9d22c | ||
|
|
363927f489 | ||
|
|
ae793fb631 | ||
|
|
944b83642a | ||
|
|
5a8e5dee73 | ||
|
|
7f870d5861 | ||
|
|
536b23dc84 | ||
|
|
0c9806e99f | ||
|
|
5a92932019 | ||
|
|
e929d2f00f | ||
|
|
1e1e4c06e8 | ||
|
|
d0726db473 | ||
|
|
4cdc15a824 | ||
|
|
b36fdf2f54 | ||
|
|
73ba6b385f | ||
|
|
30d1639aa4 | ||
|
|
d82814fc86 | ||
|
|
2220efd682 | ||
|
|
679b365cf7 | ||
|
|
83bf83b6dd | ||
|
|
321364c7c2 | ||
|
|
d8707d5867 | ||
|
|
2dd0a78c52 | ||
|
|
d7b8c3c78f | ||
|
|
2f0148a2df | ||
|
|
4accc29984 | ||
|
|
19b9af2494 | ||
|
|
0aa50e9439 | ||
|
|
a00a906482 | ||
|
|
19ad7d7c96 | ||
|
|
251e55da42 | ||
|
|
32f1b2060a | ||
|
|
b1c54532df | ||
|
|
38c67f16e8 | ||
|
|
24aefc52a1 | ||
|
|
ba8c205253 | ||
|
|
31193d99ba | ||
|
|
4bbe42d105 | ||
|
|
5bdc022627 | ||
|
|
41e354f1ee | ||
|
|
d1c76709b0 | ||
|
|
64774a8db0 | ||
|
|
51dd3abcae | ||
|
|
825b2c30a1 |
59
.circleci/config.yml
Normal file
59
.circleci/config.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
version: 2.1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test_suite:
|
||||||
|
environment:
|
||||||
|
- GOPATH: /home/circleci/go
|
||||||
|
docker:
|
||||||
|
- image: circleci/golang:1.9
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
g++ --version
|
||||||
|
cd tests/
|
||||||
|
g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check_toml_test.cpp -o check_toml_test
|
||||||
|
go get github.com/BurntSushi/toml-test
|
||||||
|
$GOPATH/bin/toml-test ./check_toml_test
|
||||||
|
output_result:
|
||||||
|
docker:
|
||||||
|
- image: circleci/buildpack-deps:bionic
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
g++ --version
|
||||||
|
cd tests/
|
||||||
|
g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check.cpp -o check
|
||||||
|
git clone https://github.com/BurntSushi/toml-test.git
|
||||||
|
cp check toml-test/tests/invalid
|
||||||
|
cp check toml-test/tests/valid
|
||||||
|
cd toml-test/tests/invalid
|
||||||
|
for f in $(ls ./*.toml);
|
||||||
|
do echo "==> ${f}";
|
||||||
|
cat ${f};
|
||||||
|
echo "---------------------------------------";
|
||||||
|
./check ${f} invalid;
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "=======================================";
|
||||||
|
done
|
||||||
|
cd ../valid
|
||||||
|
for f in $(ls ./*.toml);
|
||||||
|
do echo "==> ${f}";
|
||||||
|
cat ${f};
|
||||||
|
echo "---------------------------------------";
|
||||||
|
./check ${f} valid;
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "=======================================";
|
||||||
|
done
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2.1
|
||||||
|
test:
|
||||||
|
jobs:
|
||||||
|
- test_suite
|
||||||
|
- output_result
|
||||||
138
.travis.yml
138
.travis.yml
@@ -5,20 +5,62 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-5"
|
env: COMPILER="g++-5" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
packages:
|
packages:
|
||||||
- g++-5
|
- g++-5
|
||||||
- build-essential
|
- libboost-all-dev
|
||||||
- cmake
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-6" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-6
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-7" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-7
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8" CXX_STANDARD=17
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
- libboost-all-dev
|
- libboost-all-dev
|
||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-3.7"
|
env: COMPILER="clang++-3.7" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -26,17 +68,99 @@ matrix:
|
|||||||
- llvm-toolchain-precise-3.7
|
- llvm-toolchain-precise-3.7
|
||||||
packages:
|
packages:
|
||||||
- clang-3.7
|
- clang-3.7
|
||||||
- build-essential
|
- libboost-all-dev
|
||||||
- cmake
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-4.0" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-4.0
|
||||||
|
packages:
|
||||||
|
- clang-4.0
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-5.0" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-5.0
|
||||||
|
packages:
|
||||||
|
- clang-5.0
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-6.0" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-6.0
|
||||||
|
packages:
|
||||||
|
- clang-6.0
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-7" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-7
|
||||||
|
packages:
|
||||||
|
- clang-7
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=17
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
- libboost-all-dev
|
- libboost-all-dev
|
||||||
- os: osx
|
- os: osx
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
|
env: CXX_STANDARD=11
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
- |
|
||||||
|
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||||
|
mkdir -p cmake
|
||||||
|
travis_retry wget "https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.tar.gz"
|
||||||
|
tar xf cmake-3.11.2-Linux-x86_64.tar.gz -C cmake --strip-components=1
|
||||||
|
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
|
||||||
|
else
|
||||||
|
brew upgrade cmake
|
||||||
|
fi
|
||||||
|
- 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 ..
|
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD ..
|
||||||
- make
|
- make
|
||||||
- ctest --output-on-failure
|
- ctest --output-on-failure
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ project(toml11)
|
|||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
if(NOT DEFINED CMAKE_CXX_STANDARD)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
endif()
|
||||||
set(CXX_STANDARD_REQUIRED ON)
|
set(CXX_STANDARD_REQUIRED ON)
|
||||||
else()
|
else()
|
||||||
# Manually check for C++11 compiler flag.
|
# Manually check for C++11 compiler flag.
|
||||||
|
|||||||
59
PROPOSAL.md
59
PROPOSAL.md
@@ -1,59 +0,0 @@
|
|||||||
|
|
||||||
### encoding user's data
|
|
||||||
|
|
||||||
You can encode your data to toml format.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
const toml::value integer(1);
|
|
||||||
const toml::value array{3.1, 3.14, 3.141, 3.1415};
|
|
||||||
const toml::value table{{"answer", 42}, {"pi", 3.14}, {"string", "foobar"}};
|
|
||||||
|
|
||||||
std::cout << toml::format("integer", integer) << std::endl;
|
|
||||||
std::cout << toml::format("array", array) << std::endl;
|
|
||||||
std::cout << toml::format("table", table) << std::endl;
|
|
||||||
```
|
|
||||||
|
|
||||||
this program will output as below.
|
|
||||||
|
|
||||||
```toml
|
|
||||||
integer = 1
|
|
||||||
array = [3.1, 3.14, 3.141, 3.1415]
|
|
||||||
[table]
|
|
||||||
answer = 42
|
|
||||||
pi = 3.14
|
|
||||||
string = "foobar"
|
|
||||||
```
|
|
||||||
|
|
||||||
Without key name, you can make string formatted as toml.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
const std::string integer_ = toml::format(integer); // "1"
|
|
||||||
const std::string array_ = toml::format(array); // "[3.1, 3.14, 3.141, 3.1415]"
|
|
||||||
const std::string table_ = toml::format(table); // "answer = 42\npi=3.14\nstring=foobar"
|
|
||||||
```
|
|
||||||
|
|
||||||
### inlinize
|
|
||||||
|
|
||||||
You can make `toml::Table` inline.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
const toml::value table{{"answer", 42}, {"pi", 3.14}, {"string", "foobar"}};
|
|
||||||
// if the inline-table format length is less than 80, the table will be inlined
|
|
||||||
std::cout << toml::format("table", table, toml::make_inline(80)) << std::endl;
|
|
||||||
// In any case, the table will be inlined.
|
|
||||||
std::cout << toml::format("table", table, toml::forceinline) << std::endl;
|
|
||||||
```
|
|
||||||
|
|
||||||
```toml
|
|
||||||
table = {answer = 42, pi = 3.14, string = "foobar"}
|
|
||||||
```
|
|
||||||
|
|
||||||
And there are some stream manipulators for toml format.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
const toml::value table{{"answer", 42}, {"pi", 3.14}, {"string", "foobar"}};
|
|
||||||
// if the inline-table format length is less than 80, the table will be inlined
|
|
||||||
std::cout << toml::make_inline(80) << table << std::endl;
|
|
||||||
// In any case, the table will be inlined.
|
|
||||||
std::cout << toml::forceinline << table << std::endl;
|
|
||||||
```
|
|
||||||
@@ -20,13 +20,17 @@ set(TEST_NAMES
|
|||||||
test_parse_inline_table
|
test_parse_inline_table
|
||||||
test_parse_key
|
test_parse_key
|
||||||
test_parse_table_key
|
test_parse_table_key
|
||||||
|
test_literals
|
||||||
|
test_comments
|
||||||
test_get
|
test_get
|
||||||
test_get_related_func
|
test_get_related_func
|
||||||
test_to_toml
|
|
||||||
test_from_toml
|
test_from_toml
|
||||||
test_parse_file
|
test_parse_file
|
||||||
|
test_serialize_file
|
||||||
test_parse_unicode
|
test_parse_unicode
|
||||||
test_error_detection
|
test_error_detection
|
||||||
|
test_format_error
|
||||||
|
test_extended_conversions
|
||||||
)
|
)
|
||||||
|
|
||||||
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
|
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
|
||||||
@@ -96,3 +100,8 @@ foreach(TEST_NAME ${TEST_NAMES})
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endforeach(TEST_NAME)
|
endforeach(TEST_NAME)
|
||||||
|
|
||||||
|
# this test is to check it compiles. it will not run
|
||||||
|
add_executable(test_multiple_translation_unit
|
||||||
|
test_multiple_translation_unit_1.cpp
|
||||||
|
test_multiple_translation_unit_2.cpp)
|
||||||
|
|||||||
41
tests/check.cpp
Normal file
41
tests/check.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "toml.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if(argc != 3)
|
||||||
|
{
|
||||||
|
std::cerr << "usage: ./check [filename] [valid|invalid]" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string file_kind(argv[2]);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const auto data = toml::parse(argv[1]);
|
||||||
|
std::cout << std::setprecision(16) << std::setw(80) << data;
|
||||||
|
if(file_kind == "valid")
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& err)
|
||||||
|
{
|
||||||
|
std::cout << "what(): " << err.what() << std::endl;
|
||||||
|
if(file_kind == "invalid")
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 127;
|
||||||
|
}
|
||||||
142
tests/check_toml_test.cpp
Normal file
142
tests/check_toml_test.cpp
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#include "toml.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
struct json_serializer
|
||||||
|
{
|
||||||
|
void operator()(toml::boolean v)
|
||||||
|
{
|
||||||
|
std::cout << "{\"type\":\"bool\",\"value\":\"" << toml::value(v) << "\"}";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(toml::integer v)
|
||||||
|
{
|
||||||
|
std::cout << "{\"type\":\"integer\",\"value\":\"" << toml::value(v) << "\"}";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(toml::floating v)
|
||||||
|
{
|
||||||
|
std::cout << "{\"type\":\"float\",\"value\":\"" << toml::value(v) << "\"}";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(const toml::string& v)
|
||||||
|
{
|
||||||
|
// since toml11 automatically convert string to multiline string that is
|
||||||
|
// valid only in TOML, we need to format the string to make it valid in
|
||||||
|
// JSON.
|
||||||
|
std::cout << "{\"type\":\"string\",\"value\":\""
|
||||||
|
<< this->escape_string(v.str) << "\"}";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(const toml::local_time& v)
|
||||||
|
{
|
||||||
|
std::cout << "{\"type\":\"local_time\",\"value\":\"" << toml::value(v) << "\"}";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(const toml::local_date& v)
|
||||||
|
{
|
||||||
|
std::cout << "{\"type\":\"local_date\",\"value\":\"" << toml::value(v) << "\"}";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(const toml::local_datetime& v)
|
||||||
|
{
|
||||||
|
std::cout << "{\"type\":\"local_datetime\",\"value\":\"" << toml::value(v) << "\"}";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(const toml::offset_datetime& v)
|
||||||
|
{
|
||||||
|
std::cout << "{\"type\":\"datetime\",\"value\":\"" << toml::value(v) << "\"}";
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(const toml::array& v)
|
||||||
|
{
|
||||||
|
if(!v.empty() && v.front().is_table())
|
||||||
|
{
|
||||||
|
std::cout << '[';
|
||||||
|
bool is_first = true;
|
||||||
|
for(const auto& elem : v)
|
||||||
|
{
|
||||||
|
if(!is_first) {std::cout << ", ";}
|
||||||
|
is_first = false;
|
||||||
|
toml::visit(*this, elem);
|
||||||
|
}
|
||||||
|
std::cout << ']';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "{\"type\":\"array\",\"value\":[";
|
||||||
|
bool is_first = true;
|
||||||
|
for(const auto& elem : v)
|
||||||
|
{
|
||||||
|
if(!is_first) {std::cout << ", ";}
|
||||||
|
is_first = false;
|
||||||
|
toml::visit(*this, elem);
|
||||||
|
}
|
||||||
|
std::cout << "]}";
|
||||||
|
}
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void operator()(const toml::table& v)
|
||||||
|
{
|
||||||
|
std::cout << '{';
|
||||||
|
bool is_first = true;
|
||||||
|
for(const auto& elem : v)
|
||||||
|
{
|
||||||
|
if(!is_first) {std::cout << ", ";}
|
||||||
|
is_first = false;
|
||||||
|
std::cout << toml::format(toml::string(elem.first),
|
||||||
|
std::numeric_limits<std::size_t>::max());
|
||||||
|
std::cout << ':';
|
||||||
|
toml::visit(*this, elem.second);
|
||||||
|
}
|
||||||
|
std::cout << '}';
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string escape_string(const std::string& s) const
|
||||||
|
{
|
||||||
|
std::string retval;
|
||||||
|
for(const char c : s)
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '\\': {retval += "\\\\"; break;}
|
||||||
|
case '\"': {retval += "\\\""; break;}
|
||||||
|
case '\b': {retval += "\\b"; break;}
|
||||||
|
case '\t': {retval += "\\t"; break;}
|
||||||
|
case '\f': {retval += "\\f"; break;}
|
||||||
|
case '\n': {retval += "\\n"; break;}
|
||||||
|
case '\r': {retval += "\\r"; break;}
|
||||||
|
default : {retval += c; break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::vector<char> buf;
|
||||||
|
std::cin.peek();
|
||||||
|
while(!std::cin.eof())
|
||||||
|
{
|
||||||
|
buf.push_back(std::cin.get());
|
||||||
|
std::cin.peek();
|
||||||
|
}
|
||||||
|
std::string bufstr(buf.begin(), buf.end());
|
||||||
|
|
||||||
|
std::istringstream ss(bufstr);
|
||||||
|
|
||||||
|
const auto data = toml::parse(ss);
|
||||||
|
std::cout << std::setprecision(std::numeric_limits<double>::max_digits10);
|
||||||
|
toml::visit(json_serializer(), data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& err)
|
||||||
|
{
|
||||||
|
std::cout << "what(): " << err.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
125
tests/test_comments.cpp
Normal file
125
tests/test_comments.cpp
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_comments"
|
||||||
|
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#else
|
||||||
|
#define BOOST_TEST_NO_LIB
|
||||||
|
#include <boost/test/included/unit_test.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <toml.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_comment_before)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
# comment for a.
|
||||||
|
a = 42
|
||||||
|
# comment for b.
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), u8"# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), u8"# comment for b.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), "");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8"# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b.");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
# comment for a.
|
||||||
|
# another comment for a.
|
||||||
|
a = 42
|
||||||
|
# comment for b.
|
||||||
|
# also comment for b.
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), u8R"(# comment for a.
|
||||||
|
# another comment for a.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), u8R"(# comment for b.
|
||||||
|
# also comment for b.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8"");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a.
|
||||||
|
# another comment for a.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8R"(# comment for b.
|
||||||
|
# also comment for b.)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_comment_inline)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
a = 42 # comment for a.
|
||||||
|
b = "baz" # comment for b.
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8"# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"# comment for b.");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8"# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b.");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
a = [ # comment for a.
|
||||||
|
42,
|
||||||
|
] # this also.
|
||||||
|
b = [ # comment for b.
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
c = [
|
||||||
|
3.14, # this is not a comment for c, but 3.14.
|
||||||
|
] # comment for c.
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "c").comment_before(), "");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8R"(# comment for a.
|
||||||
|
# this also.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"# comment for b.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "c").comment_inline(), u8"# comment for c.");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a.
|
||||||
|
# this also.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "c").comment(), u8"# comment for c.");
|
||||||
|
|
||||||
|
const auto& c0 = toml::find<toml::array>(v, "c").at(0);
|
||||||
|
BOOST_CHECK_EQUAL(c0.comment(), u8"# this is not a comment for c, but 3.14.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_comment_both)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
# comment for a.
|
||||||
|
a = 42 # inline comment for a.
|
||||||
|
# comment for b.
|
||||||
|
b = "baz" # inline comment for b.
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), "# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), "# comment for b.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), "# inline comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), "# inline comment for b.");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a.
|
||||||
|
# inline comment for a.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8R"(# comment for b.
|
||||||
|
# inline comment for b.)");
|
||||||
|
}
|
||||||
|
}
|
||||||
116
tests/test_extended_conversions.cpp
Normal file
116
tests/test_extended_conversions.cpp
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_extended_conversions"
|
||||||
|
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#else
|
||||||
|
#define BOOST_TEST_NO_LIB
|
||||||
|
#include <boost/test/included/unit_test.hpp>
|
||||||
|
#endif
|
||||||
|
#include <toml.hpp>
|
||||||
|
|
||||||
|
namespace extlib
|
||||||
|
{
|
||||||
|
struct foo
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
|
struct bar
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
|
||||||
|
void from_toml(const toml::value& v)
|
||||||
|
{
|
||||||
|
this->a = toml::find<int>(v, "a");
|
||||||
|
this->b = toml::find<std::string>(v, "b");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
toml::table into_toml() const
|
||||||
|
{
|
||||||
|
return toml::table{{"a", this->a}, {"b", this->b}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // extlib
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
template<>
|
||||||
|
struct from<extlib::foo>
|
||||||
|
{
|
||||||
|
static extlib::foo from_toml(const toml::value& v)
|
||||||
|
{
|
||||||
|
return extlib::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct into<extlib::foo>
|
||||||
|
{
|
||||||
|
static toml::table into_toml(const extlib::foo& f)
|
||||||
|
{
|
||||||
|
return toml::table{{"a", f.a}, {"b", f.b}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // toml
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods)
|
||||||
|
{
|
||||||
|
const toml::value v{{"a", 42}, {"b", "baz"}};
|
||||||
|
|
||||||
|
const auto foo = toml::get<extlib::foo>(v);
|
||||||
|
BOOST_CHECK_EQUAL(foo.a, 42);
|
||||||
|
BOOST_CHECK_EQUAL(foo.b, "baz");
|
||||||
|
|
||||||
|
const toml::value v2(foo);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
|
||||||
|
{
|
||||||
|
const toml::value v{{"a", 42}, {"b", "baz"}};
|
||||||
|
|
||||||
|
const auto bar = toml::get<extlib::bar>(v);
|
||||||
|
BOOST_CHECK_EQUAL(bar.a, 42);
|
||||||
|
BOOST_CHECK_EQUAL(bar.b, "baz");
|
||||||
|
|
||||||
|
const toml::value v2(bar);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
||||||
|
{
|
||||||
|
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 foos = toml::get<std::vector<extlib::foo>>(v);
|
||||||
|
BOOST_CHECK_EQUAL(foos.size() , 4ul);
|
||||||
|
BOOST_CHECK_EQUAL(foos.at(0).a , 42);
|
||||||
|
BOOST_CHECK_EQUAL(foos.at(1).a , 43);
|
||||||
|
BOOST_CHECK_EQUAL(foos.at(2).a , 44);
|
||||||
|
BOOST_CHECK_EQUAL(foos.at(3).a , 45);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(foos.at(0).b , "baz");
|
||||||
|
BOOST_CHECK_EQUAL(foos.at(1).b , "qux");
|
||||||
|
BOOST_CHECK_EQUAL(foos.at(2).b , "quux");
|
||||||
|
BOOST_CHECK_EQUAL(foos.at(3).b , "foobar");
|
||||||
|
|
||||||
|
const auto bars = toml::get<std::vector<extlib::bar>>(v);
|
||||||
|
BOOST_CHECK_EQUAL(bars.size() , 4ul);
|
||||||
|
BOOST_CHECK_EQUAL(bars.at(0).a , 42);
|
||||||
|
BOOST_CHECK_EQUAL(bars.at(1).a , 43);
|
||||||
|
BOOST_CHECK_EQUAL(bars.at(2).a , 44);
|
||||||
|
BOOST_CHECK_EQUAL(bars.at(3).a , 45);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(bars.at(0).b , "baz");
|
||||||
|
BOOST_CHECK_EQUAL(bars.at(1).b , "qux");
|
||||||
|
BOOST_CHECK_EQUAL(bars.at(2).b , "quux");
|
||||||
|
BOOST_CHECK_EQUAL(bars.at(3).b , "foobar");
|
||||||
|
}
|
||||||
75
tests/test_format_error.cpp
Normal file
75
tests/test_format_error.cpp
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_value"
|
||||||
|
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#else
|
||||||
|
#define BOOST_TEST_NO_LIB
|
||||||
|
#include <boost/test/included/unit_test.hpp>
|
||||||
|
#endif
|
||||||
|
#include <toml.hpp>
|
||||||
|
|
||||||
|
// to check it successfully compiles. it does not check the formatted string.
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_1_value)
|
||||||
|
{
|
||||||
|
toml::value val(42);
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string pretty_error =
|
||||||
|
toml::format_error("[error] test error", val, "this is a value");
|
||||||
|
std::cout << pretty_error << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string pretty_error =
|
||||||
|
toml::format_error("[error] test error", val, "this is a value",
|
||||||
|
{"this is a hint"});
|
||||||
|
std::cout << pretty_error << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_2_values)
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
toml::value v2(3.14);
|
||||||
|
{
|
||||||
|
const std::string pretty_error =
|
||||||
|
toml::format_error("[error] test error with two values",
|
||||||
|
v1, "this is the answer",
|
||||||
|
v2, "this is the pi");
|
||||||
|
std::cout << pretty_error << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string pretty_error =
|
||||||
|
toml::format_error("[error] test error with two values",
|
||||||
|
v1, "this is the answer",
|
||||||
|
v2, "this is the pi",
|
||||||
|
{"hint"});
|
||||||
|
std::cout << pretty_error << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_3_values)
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
toml::value v2(3.14);
|
||||||
|
toml::value v3("foo");
|
||||||
|
{
|
||||||
|
const std::string pretty_error =
|
||||||
|
toml::format_error("[error] test error with two values",
|
||||||
|
v1, "this is the answer",
|
||||||
|
v2, "this is the pi",
|
||||||
|
v3, "this is a meta-syntactic variable");
|
||||||
|
std::cout << pretty_error << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string pretty_error =
|
||||||
|
toml::format_error("[error] test error with two values",
|
||||||
|
v1, "this is the answer",
|
||||||
|
v2, "this is the pi",
|
||||||
|
v3, "this is a meta-syntactic variable",
|
||||||
|
{"hint 1", "hint 2"});
|
||||||
|
std::cout << pretty_error << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_exact)
|
BOOST_AUTO_TEST_CASE(test_get_exact)
|
||||||
@@ -166,6 +169,17 @@ BOOST_AUTO_TEST_CASE(test_get_string_type)
|
|||||||
toml::get<std::string>(v) += "bar";
|
toml::get<std::string>(v) += "bar";
|
||||||
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v));
|
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
{
|
||||||
|
toml::value v("foo", toml::string_t::basic);
|
||||||
|
BOOST_CHECK_EQUAL("foo", toml::get<std::string_view>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v("foo", toml::string_t::literal);
|
||||||
|
BOOST_CHECK_EQUAL("foo", toml::get<std::string_view>(v));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_toml_array)
|
BOOST_AUTO_TEST_CASE(test_get_toml_array)
|
||||||
|
|||||||
@@ -45,21 +45,194 @@ BOOST_AUTO_TEST_CASE(test_find)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_or)
|
BOOST_AUTO_TEST_CASE(test_get_or)
|
||||||
{
|
{
|
||||||
{
|
// requires conversion int -> uint
|
||||||
toml::table v{{"num", 42}};
|
|
||||||
BOOST_CHECK_EQUAL(42, toml::get_or<int>(v, "num", 0));
|
|
||||||
BOOST_CHECK_EQUAL(0, toml::get_or<int>(v, "foo", 0));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
toml::value v = toml::table{{"num", 42}};
|
|
||||||
BOOST_CHECK_EQUAL(42, toml::get_or<int>(v, "num", 0));
|
|
||||||
BOOST_CHECK_EQUAL(0, toml::get_or<int>(v, "foo", 0));
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
toml::value v1(42);
|
toml::value v1(42);
|
||||||
toml::value v2(3.14);
|
toml::value v2(3.14);
|
||||||
BOOST_CHECK_EQUAL(42, toml::get_or<int>(v1, 0));
|
BOOST_CHECK_EQUAL(42u, toml::get_or(v1, 0u));
|
||||||
BOOST_CHECK_EQUAL(0, toml::get_or<int>(v2, 0));
|
BOOST_CHECK_EQUAL(0u, toml::get_or(v2, 0u));
|
||||||
|
}
|
||||||
|
|
||||||
|
// exact toml type
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
toml::value v2(3.14);
|
||||||
|
|
||||||
|
toml::integer opt(0);
|
||||||
|
BOOST_CHECK_EQUAL(42, toml::get_or(v1, opt));
|
||||||
|
BOOST_CHECK_EQUAL(0, toml::get_or(v2, opt));
|
||||||
|
|
||||||
|
toml::value v3("foobar");
|
||||||
|
toml::string s("bazqux");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::get_or(v3, s));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v1, s));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::string
|
||||||
|
{
|
||||||
|
toml::value v1("foobar");
|
||||||
|
toml::value v2(42);
|
||||||
|
|
||||||
|
std::string s1("bazqux");
|
||||||
|
const std::string s2("bazqux");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, s1));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, s1));
|
||||||
|
|
||||||
|
std::string& v1r = toml::get_or(v1, s1);
|
||||||
|
std::string& s1r = toml::get_or(v2, s1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", v1r);
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", s1r);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, s2));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, s2));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, std::move(s1)));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, std::move(s1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// string literal
|
||||||
|
{
|
||||||
|
toml::value v1("foobar");
|
||||||
|
toml::value v2(42);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, "bazqux"));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, "bazqux"));
|
||||||
|
|
||||||
|
const char* lit = "bazqux";
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, lit));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, lit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_find_or)
|
||||||
|
{
|
||||||
|
// ========================================================================
|
||||||
|
// pass toml::value
|
||||||
|
//
|
||||||
|
// requires conversion int -> uint
|
||||||
|
{
|
||||||
|
toml::table v{{"num", 42}};
|
||||||
|
BOOST_CHECK_EQUAL(42u, toml::find_or(v, "num", 0u));
|
||||||
|
BOOST_CHECK_EQUAL(0u, toml::find_or(v, "foo", 0u));
|
||||||
|
}
|
||||||
|
// exact toml type
|
||||||
|
{
|
||||||
|
toml::table v1{{"key", 42 }};
|
||||||
|
toml::table v2{{"key", 3.14}};
|
||||||
|
toml::table v3{{"not", "key"}};
|
||||||
|
|
||||||
|
toml::integer opt(0);
|
||||||
|
BOOST_CHECK_EQUAL(42, toml::find_or(v1, "key", opt));
|
||||||
|
BOOST_CHECK_EQUAL(0, toml::find_or(v2, "key", opt));
|
||||||
|
BOOST_CHECK_EQUAL(0, toml::find_or(v3, "key", opt));
|
||||||
|
|
||||||
|
toml::table v4{{"str", "foobar"}};
|
||||||
|
toml::string s("bazqux");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v4, "str", s));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v1, "str", s));
|
||||||
|
}
|
||||||
|
// std::string
|
||||||
|
{
|
||||||
|
toml::table v1{{"key", "foobar"}};
|
||||||
|
toml::table v2{{"key", 42}};
|
||||||
|
|
||||||
|
std::string s1("bazqux");
|
||||||
|
const std::string s2("bazqux");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s1));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s1));
|
||||||
|
|
||||||
|
std::string& v1r = toml::find_or(v1, "key", s1);
|
||||||
|
std::string& s1r = toml::find_or(v2, "key", s1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", v1r);
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", s1r);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s2));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s2));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(std::move(v1), "key", std::move(s1)));
|
||||||
|
s1 = "bazqux"; // restoring moved value
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(std::move(v2), "key", std::move(s1)));
|
||||||
|
}
|
||||||
|
// string literal
|
||||||
|
{
|
||||||
|
toml::table v1{{"key", "foobar"}};
|
||||||
|
toml::table v2{{"key",42}};
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", "bazqux"));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", "bazqux"));
|
||||||
|
|
||||||
|
const char* lit = "bazqux";
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", lit));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", lit));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// pass toml::value
|
||||||
|
//
|
||||||
|
// requires conversion int -> uint
|
||||||
|
{
|
||||||
|
toml::table v = toml::table{{"num", 42}};
|
||||||
|
BOOST_CHECK_EQUAL(42u, toml::find_or(v, "num", 0u));
|
||||||
|
BOOST_CHECK_EQUAL(0u, toml::find_or(v, "foo", 0u));
|
||||||
|
}
|
||||||
|
// exact toml type
|
||||||
|
{
|
||||||
|
toml::value v1 = toml::table{{"key", 42 }};
|
||||||
|
toml::value v2 = toml::table{{"key", 3.14}};
|
||||||
|
toml::value v3 = toml::table{{"not", "key"}};
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(42, toml::find_or(v1, "key", toml::integer(0)));
|
||||||
|
BOOST_CHECK_EQUAL( 0, toml::find_or(v2, "key", toml::integer(0)));
|
||||||
|
BOOST_CHECK_EQUAL( 0, toml::find_or(v3, "key", toml::integer(0)));
|
||||||
|
|
||||||
|
toml::value v4 = toml::table{{"str", "foobar"}};
|
||||||
|
toml::string s("bazqux");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v4, "str", s));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v1, "str", s));
|
||||||
|
}
|
||||||
|
// std::string
|
||||||
|
{
|
||||||
|
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||||
|
toml::value v2 = toml::table{{"key", 42}};
|
||||||
|
|
||||||
|
std::string s1("bazqux");
|
||||||
|
const std::string s2("bazqux");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s1));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s1));
|
||||||
|
|
||||||
|
std::string& v1r = toml::find_or(v1, "key", s1);
|
||||||
|
std::string& s1r = toml::find_or(v2, "key", s1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", v1r);
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", s1r);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s2));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s2));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(std::move(v1), "key", std::move(s1)));
|
||||||
|
s1 = "bazqux"; // restoring moved value
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(std::move(v2), "key", std::move(s1)));
|
||||||
|
}
|
||||||
|
// string literal
|
||||||
|
{
|
||||||
|
toml::value v1 = toml::table{{"key", "foobar"}};
|
||||||
|
toml::value v2 = toml::table{{"key",42}};
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", "bazqux"));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", "bazqux"));
|
||||||
|
|
||||||
|
const char* lit = "bazqux";
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", lit));
|
||||||
|
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", lit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ do { \
|
|||||||
BOOST_CHECK_EQUAL(static_cast<std::size_t>(std::distance( \
|
BOOST_CHECK_EQUAL(static_cast<std::size_t>(std::distance( \
|
||||||
loc.begin(), loc.iter())), region.size()); \
|
loc.begin(), loc.iter())), region.size()); \
|
||||||
} else { \
|
} else { \
|
||||||
std::cerr << "lexer " << lxr::pattern() << " failed with input `"; \
|
std::cerr << "lexer failed with input `"; \
|
||||||
std::cerr << token << "`. expected `" << expected << "`\n"; \
|
std::cerr << token << "`. expected `" << expected << "`\n"; \
|
||||||
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
|
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
|
||||||
} \
|
} \
|
||||||
|
|||||||
154
tests/test_literals.cpp
Normal file
154
tests/test_literals.cpp
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_literals"
|
||||||
|
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#else
|
||||||
|
#define BOOST_TEST_NO_LIB
|
||||||
|
#include <boost/test/included/unit_test.hpp>
|
||||||
|
#endif
|
||||||
|
#include <toml.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_file_as_literal)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::value r{{"a", 42}, {"b", "baz"}};
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
a = 42
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(r, v);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value r{
|
||||||
|
{"c", 3.14},
|
||||||
|
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
|
||||||
|
};
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
c = 3.14
|
||||||
|
[table]
|
||||||
|
a = 42
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(r, v);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value r{
|
||||||
|
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
|
||||||
|
};
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
[table]
|
||||||
|
a = 42
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(r, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_as_literal)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8"true"_toml;
|
||||||
|
const toml::value v2 = u8"false"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_boolean());
|
||||||
|
BOOST_CHECK(toml::get<bool>(v1));
|
||||||
|
BOOST_CHECK(!toml::get<bool>(v2));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8"123_456"_toml;
|
||||||
|
const toml::value v2 = u8"0b0010"_toml;
|
||||||
|
const toml::value v3 = u8"0xDEADBEEF"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v1.is_integer());
|
||||||
|
BOOST_CHECK(v2.is_integer());
|
||||||
|
BOOST_CHECK(v3.is_integer());
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v1), 123456);
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v2), 2);
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v3), 0xDEADBEEF);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8"3.1415"_toml;
|
||||||
|
const toml::value v2 = u8"6.02e+23"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v1.is_float());
|
||||||
|
BOOST_CHECK(v2.is_float());
|
||||||
|
BOOST_CHECK_CLOSE(toml::get<double>(v1), 3.1415, 0.00001);
|
||||||
|
BOOST_CHECK_CLOSE(toml::get<double>(v2), 6.02e23, 0.0001);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8R"("foo")"_toml;
|
||||||
|
const toml::value v2 = u8R"('foo')"_toml;
|
||||||
|
const toml::value v3 = u8R"("""foo""")"_toml;
|
||||||
|
const toml::value v4 = u8R"('''foo''')"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v1.is_string());
|
||||||
|
BOOST_CHECK(v2.is_string());
|
||||||
|
BOOST_CHECK(v3.is_string());
|
||||||
|
BOOST_CHECK(v4.is_string());
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<std::string>(v1), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<std::string>(v2), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<std::string>(v3), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<std::string>(v4), "foo");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8R"([1,2,3])"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v1.is_array());
|
||||||
|
BOOST_CHECK((toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3}));
|
||||||
|
|
||||||
|
const toml::value v2 = u8R"([1,])"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v2.is_array());
|
||||||
|
BOOST_CHECK((toml::get<std::vector<int>>(v2) == std::vector<int>{1}));
|
||||||
|
|
||||||
|
const toml::value v3 = u8R"([[1,]])"_toml;
|
||||||
|
BOOST_CHECK(v3.is_array());
|
||||||
|
BOOST_CHECK((toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1}));
|
||||||
|
|
||||||
|
const toml::value v4 = u8R"([[1],])"_toml;
|
||||||
|
BOOST_CHECK(v4.is_array());
|
||||||
|
BOOST_CHECK((toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1}));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8R"({a = 42})"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v1.is_table());
|
||||||
|
BOOST_CHECK((toml::get<std::map<std::string,int>>(v1) ==
|
||||||
|
std::map<std::string,int>{{"a", 42}}));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8"1979-05-27"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v1.is_local_date());
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<toml::local_date>(v1),
|
||||||
|
toml::local_date(1979, toml::month_t::May, 27));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8"12:00:00"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v1.is_local_time());
|
||||||
|
BOOST_CHECK(toml::get<std::chrono::hours>(v1) == std::chrono::hours(12));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = u8"1979-05-27T07:32:00"_toml;
|
||||||
|
BOOST_CHECK(v1.is_local_datetime());
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<toml::local_datetime>(v1),
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0)));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
|
||||||
|
BOOST_CHECK(v1.is_offset_datetime());
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<toml::offset_datetime>(v1),
|
||||||
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
11
tests/test_multiple_translation_unit_1.cpp
Normal file
11
tests/test_multiple_translation_unit_1.cpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include <toml.hpp>
|
||||||
|
|
||||||
|
int read_a(const toml::table&);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
const std::string content("a = 0");
|
||||||
|
std::istringstream iss(content);
|
||||||
|
const auto data = toml::parse(iss, "test_multiple_translation_unit.toml");
|
||||||
|
return read_a(data);
|
||||||
|
}
|
||||||
6
tests/test_multiple_translation_unit_2.cpp
Normal file
6
tests/test_multiple_translation_unit_2.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include <toml.hpp>
|
||||||
|
|
||||||
|
int read_a(const toml::table& t)
|
||||||
|
{
|
||||||
|
return toml::get<int>(t.at("a"));
|
||||||
|
}
|
||||||
@@ -13,23 +13,23 @@ using namespace detail;
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_bare_key)
|
BOOST_AUTO_TEST_CASE(test_bare_key)
|
||||||
{
|
{
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "barekey", std::vector<key>(1, "barekey"));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "barekey", std::vector<key>(1, "barekey"));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "bare-key", std::vector<key>(1, "bare-key"));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "bare-key", std::vector<key>(1, "bare-key"));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "bare_key", std::vector<key>(1, "bare_key"));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "bare_key", std::vector<key>(1, "bare_key"));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "1234", std::vector<key>(1, "1234"));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "1234", std::vector<key>(1, "1234"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_quoted_key)
|
BOOST_AUTO_TEST_CASE(test_quoted_key)
|
||||||
{
|
{
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "\"127.0.0.1\"", std::vector<key>(1, "127.0.0.1" ));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "\"127.0.0.1\"", std::vector<key>(1, "127.0.0.1" ));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "\"character encoding\"", std::vector<key>(1, "character encoding"));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "\"character encoding\"", std::vector<key>(1, "character encoding"));
|
||||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"", std::vector<key>(1, "\xCA\x8E\xC7\x9D\xCA\x9E"));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"", std::vector<key>(1, "\xCA\x8E\xC7\x9D\xCA\x9E"));
|
||||||
#else
|
#else
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "\"ʎǝʞ\"", std::vector<key>(1, "ʎǝʞ" ));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "\"ʎǝʞ\"", std::vector<key>(1, "ʎǝʞ" ));
|
||||||
#endif
|
#endif
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "'key2'", std::vector<key>(1, "key2" ));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "'key2'", std::vector<key>(1, "key2" ));
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "'quoted \"value\"'", std::vector<key>(1, "quoted \"value\"" ));
|
TOML11_TEST_PARSE_EQUAL(parse_key, "'quoted \"value\"'", std::vector<key>(1, "quoted \"value\"" ));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_dotted_key)
|
BOOST_AUTO_TEST_CASE(test_dotted_key)
|
||||||
@@ -38,13 +38,13 @@ BOOST_AUTO_TEST_CASE(test_dotted_key)
|
|||||||
std::vector<key> keys(2);
|
std::vector<key> keys(2);
|
||||||
keys[0] = "physical";
|
keys[0] = "physical";
|
||||||
keys[1] = "color";
|
keys[1] = "color";
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "physical.color", keys);
|
TOML11_TEST_PARSE_EQUAL(parse_key, "physical.color", keys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<key> keys(2);
|
std::vector<key> keys(2);
|
||||||
keys[0] = "physical";
|
keys[0] = "physical";
|
||||||
keys[1] = "shape";
|
keys[1] = "shape";
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "physical.shape", keys);
|
TOML11_TEST_PARSE_EQUAL(parse_key, "physical.shape", keys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<key> keys(4);
|
std::vector<key> keys(4);
|
||||||
@@ -52,12 +52,12 @@ BOOST_AUTO_TEST_CASE(test_dotted_key)
|
|||||||
keys[1] = "y";
|
keys[1] = "y";
|
||||||
keys[2] = "z";
|
keys[2] = "z";
|
||||||
keys[3] = "w";
|
keys[3] = "w";
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "x.y.z.w", keys);
|
TOML11_TEST_PARSE_EQUAL(parse_key, "x.y.z.w", keys);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::vector<key> keys(2);
|
std::vector<key> keys(2);
|
||||||
keys[0] = "site";
|
keys[0] = "site";
|
||||||
keys[1] = "google.com";
|
keys[1] = "google.com";
|
||||||
TOML11_TEST_PARSE_EQUAL_VALUE(parse_key, "site.\"google.com\"", keys);
|
TOML11_TEST_PARSE_EQUAL(parse_key, "site.\"google.com\"", keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
tests/test_serialize_file.cpp
Normal file
54
tests/test_serialize_file.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_serialize_file"
|
||||||
|
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#else
|
||||||
|
#define BOOST_TEST_NO_LIB
|
||||||
|
#include <boost/test/included/unit_test.hpp>
|
||||||
|
#endif
|
||||||
|
#include <toml.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_example)
|
||||||
|
{
|
||||||
|
const auto data = toml::parse("toml/tests/example.toml");
|
||||||
|
{
|
||||||
|
std::ofstream ofs("tmp1.toml");
|
||||||
|
ofs << std::setw(80) << data;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto serialized = toml::parse("tmp1.toml");
|
||||||
|
{
|
||||||
|
auto& owner = toml::get<toml::table>(serialized.at("owner"));
|
||||||
|
auto& bio = toml::get<std::string>(owner.at("bio"));
|
||||||
|
const auto CR = std::find(bio.begin(), bio.end(), '\r');
|
||||||
|
if(CR != bio.end())
|
||||||
|
{
|
||||||
|
bio.erase(CR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_CHECK(data == serialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_fruit)
|
||||||
|
{
|
||||||
|
const auto data = toml::parse("toml/tests/fruit.toml");
|
||||||
|
{
|
||||||
|
std::ofstream ofs("tmp2.toml");
|
||||||
|
ofs << std::setw(80) << data;
|
||||||
|
}
|
||||||
|
const auto serialized = toml::parse("tmp2.toml");
|
||||||
|
BOOST_CHECK(data == serialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_hard_example)
|
||||||
|
{
|
||||||
|
const auto data = toml::parse("toml/tests/hard_example.toml");
|
||||||
|
{
|
||||||
|
std::ofstream ofs("tmp3.toml");
|
||||||
|
ofs << std::setw(80) << data;
|
||||||
|
}
|
||||||
|
const auto serialized = toml::parse("tmp3.toml");
|
||||||
|
BOOST_CHECK(data == serialized);
|
||||||
|
}
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
#define BOOST_TEST_MODULE "test_to_toml"
|
|
||||||
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
|
||||||
#include <boost/test/unit_test.hpp>
|
|
||||||
#else
|
|
||||||
#define BOOST_TEST_NO_LIB
|
|
||||||
#include <boost/test/included/unit_test.hpp>
|
|
||||||
#endif
|
|
||||||
#include <toml.hpp>
|
|
||||||
#include <map>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml(true);
|
|
||||||
toml::value v2 = toml::to_toml(false);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Boolean);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
|
||||||
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
|
||||||
BOOST_CHECK(v2.is<toml::Boolean>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_integer)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml(-42);
|
|
||||||
toml::value v2 = toml::to_toml(42u);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Integer);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Integer);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Integer));
|
|
||||||
BOOST_CHECK(v2.is(toml::value_t::Integer));
|
|
||||||
BOOST_CHECK(v1.is<toml::Integer>());
|
|
||||||
BOOST_CHECK(v2.is<toml::Integer>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), -42);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), 42u);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_float)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml(3.14);
|
|
||||||
toml::value v2 = toml::to_toml(3.14f);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Float);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Float);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Float));
|
|
||||||
BOOST_CHECK(v2.is(toml::value_t::Float));
|
|
||||||
BOOST_CHECK(v1.is<toml::Float>());
|
|
||||||
BOOST_CHECK(v2.is<toml::Float>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Float>(), 3.14);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v2.cast<toml::value_t::Float>(), 3.14, 1e-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_string)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml(std::string("foo"));
|
|
||||||
toml::value v2 = toml::to_toml(std::string("foo"), toml::string_t::literal);
|
|
||||||
toml::value v3 = toml::to_toml("foo");
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::String);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::String);
|
|
||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::String);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::String));
|
|
||||||
BOOST_CHECK(v2.is(toml::value_t::String));
|
|
||||||
BOOST_CHECK(v3.is(toml::value_t::String));
|
|
||||||
BOOST_CHECK(v1.is<toml::String>());
|
|
||||||
BOOST_CHECK(v2.is<toml::String>());
|
|
||||||
BOOST_CHECK(v3.is<toml::String>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "foo");
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "foo");
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "foo");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_date)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml(toml::local_date(2018, toml::month_t::Jan, 31));
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDate);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::LocalDate));
|
|
||||||
BOOST_CHECK(v1.is<toml::LocalDate>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31));
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_time)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml(toml::local_time(12, 30, 45));
|
|
||||||
toml::value v2 = toml::to_toml(std::chrono::hours(12) + std::chrono::minutes(30) +
|
|
||||||
std::chrono::seconds(45));
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalTime);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::LocalTime);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::LocalTime));
|
|
||||||
BOOST_CHECK(v2.is(toml::value_t::LocalTime));
|
|
||||||
BOOST_CHECK(v1.is<toml::LocalTime>());
|
|
||||||
BOOST_CHECK(v2.is<toml::LocalTime>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
|
||||||
toml::local_time(12, 30, 45));
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalTime>(),
|
|
||||||
toml::local_time(12, 30, 45));
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
|
||||||
v2.cast<toml::value_t::LocalTime>());
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml(toml::local_datetime(
|
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31),
|
|
||||||
toml::local_time(12, 30, 45)
|
|
||||||
));
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDatetime);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::LocalDatetime));
|
|
||||||
BOOST_CHECK(v1.is<toml::LocalDatetime>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDatetime>(),
|
|
||||||
toml::local_datetime(
|
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31),
|
|
||||||
toml::local_time(12, 30, 45)));
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml(toml::offset_datetime(
|
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31),
|
|
||||||
toml::local_time(12, 30, 45),
|
|
||||||
toml::time_offset(9, 0)
|
|
||||||
));
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::OffsetDatetime);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::OffsetDatetime));
|
|
||||||
BOOST_CHECK(v1.is<toml::OffsetDatetime>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::OffsetDatetime>(),
|
|
||||||
toml::offset_datetime(
|
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31),
|
|
||||||
toml::local_time(12, 30, 45),
|
|
||||||
toml::time_offset(9, 0)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_array)
|
|
||||||
{
|
|
||||||
std::vector<int> v{1,2,3,4,5};
|
|
||||||
toml::value v1 = toml::to_toml(v);
|
|
||||||
toml::value v2 = toml::to_toml(6,7,8,9,0);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Array));
|
|
||||||
BOOST_CHECK(v1.is<toml::Array>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Array);
|
|
||||||
BOOST_CHECK(v2.is(toml::value_t::Array));
|
|
||||||
BOOST_CHECK(v2.is<toml::Array>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 1);
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 2);
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_table)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml({{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}});
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Table);
|
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Table));
|
|
||||||
BOOST_CHECK(v1.is<toml::Table>());
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Integer>(), 42);
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Float>(), 3.14);
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "qux");
|
|
||||||
}
|
|
||||||
@@ -9,6 +9,11 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_boolean)
|
BOOST_AUTO_TEST_CASE(test_value_boolean)
|
||||||
{
|
{
|
||||||
toml::value v1(true);
|
toml::value v1(true);
|
||||||
@@ -20,9 +25,13 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v2.is<toml::Boolean>());
|
BOOST_CHECK(v2.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_boolean());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), false);
|
||||||
|
|
||||||
v1 = false;
|
v1 = false;
|
||||||
v2 = true;
|
v2 = true;
|
||||||
@@ -33,9 +42,13 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v2.is<toml::Boolean>());
|
BOOST_CHECK(v2.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_boolean());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), false);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), true);
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
toml::value v4(v2);
|
toml::value v4(v2);
|
||||||
@@ -48,9 +61,13 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
BOOST_CHECK(v4.is(toml::value_t::Boolean));
|
BOOST_CHECK(v4.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v3.is<toml::Boolean>());
|
BOOST_CHECK(v3.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v4.is<toml::Boolean>());
|
BOOST_CHECK(v4.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v3.is_boolean());
|
||||||
|
BOOST_CHECK(v4.is_boolean());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), false);
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_boolean(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v4.as_boolean(), true);
|
||||||
|
|
||||||
toml::value v5(std::move(v1));
|
toml::value v5(std::move(v1));
|
||||||
toml::value v6(std::move(v2));
|
toml::value v6(std::move(v2));
|
||||||
@@ -61,9 +78,13 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
BOOST_CHECK(v6.is(toml::value_t::Boolean));
|
BOOST_CHECK(v6.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v5.is<toml::Boolean>());
|
BOOST_CHECK(v5.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v6.is<toml::Boolean>());
|
BOOST_CHECK(v6.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v3.is_boolean());
|
||||||
|
BOOST_CHECK(v4.is_boolean());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::Boolean>(), false);
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v5.as_boolean(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v6.as_boolean(), true);
|
||||||
|
|
||||||
v1 = 42;
|
v1 = 42;
|
||||||
v2 = 3.14;
|
v2 = 3.14;
|
||||||
@@ -74,9 +95,13 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Float));
|
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v1.is<toml::Integer>());
|
BOOST_CHECK(v1.is<toml::Integer>());
|
||||||
BOOST_CHECK(v2.is<toml::Float>());
|
BOOST_CHECK(v2.is<toml::Float>());
|
||||||
|
BOOST_CHECK(v1.is_integer());
|
||||||
|
BOOST_CHECK(v2.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 42);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 42);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Float>(), 3.14);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Float>(), 3.14);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_integer(), 42);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_float(), 3.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_integer)
|
BOOST_AUTO_TEST_CASE(test_value_integer)
|
||||||
@@ -90,9 +115,13 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Integer));
|
BOOST_CHECK(v2.is(toml::value_t::Integer));
|
||||||
BOOST_CHECK(v1.is<toml::Integer>());
|
BOOST_CHECK(v1.is<toml::Integer>());
|
||||||
BOOST_CHECK(v2.is<toml::Integer>());
|
BOOST_CHECK(v2.is<toml::Integer>());
|
||||||
|
BOOST_CHECK(v1.is_integer());
|
||||||
|
BOOST_CHECK(v2.is_integer());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), -42);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), -42);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), 42u);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), 42u);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_integer(), -42);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_integer(), 42u);
|
||||||
|
|
||||||
v1 = 54;
|
v1 = 54;
|
||||||
v2 = -54;
|
v2 = -54;
|
||||||
@@ -103,9 +132,13 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Integer));
|
BOOST_CHECK(v2.is(toml::value_t::Integer));
|
||||||
BOOST_CHECK(v1.is<toml::Integer>());
|
BOOST_CHECK(v1.is<toml::Integer>());
|
||||||
BOOST_CHECK(v2.is<toml::Integer>());
|
BOOST_CHECK(v2.is<toml::Integer>());
|
||||||
|
BOOST_CHECK(v1.is_integer());
|
||||||
|
BOOST_CHECK(v2.is_integer());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), -54);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), -54);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_integer(), -54);
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
toml::value v4(v2);
|
toml::value v4(v2);
|
||||||
@@ -118,9 +151,13 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
BOOST_CHECK(v4.is(toml::value_t::Integer));
|
BOOST_CHECK(v4.is(toml::value_t::Integer));
|
||||||
BOOST_CHECK(v3.is<toml::Integer>());
|
BOOST_CHECK(v3.is<toml::Integer>());
|
||||||
BOOST_CHECK(v4.is<toml::Integer>());
|
BOOST_CHECK(v4.is<toml::Integer>());
|
||||||
|
BOOST_CHECK(v3.is_integer());
|
||||||
|
BOOST_CHECK(v4.is_integer());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Integer>(), -54);
|
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Integer>(), -54);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v4.as_integer(), -54);
|
||||||
|
|
||||||
toml::value v5(std::move(v1));
|
toml::value v5(std::move(v1));
|
||||||
toml::value v6(std::move(v2));
|
toml::value v6(std::move(v2));
|
||||||
@@ -131,9 +168,13 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
BOOST_CHECK(v6.is(toml::value_t::Integer));
|
BOOST_CHECK(v6.is(toml::value_t::Integer));
|
||||||
BOOST_CHECK(v5.is<toml::Integer>());
|
BOOST_CHECK(v5.is<toml::Integer>());
|
||||||
BOOST_CHECK(v6.is<toml::Integer>());
|
BOOST_CHECK(v6.is<toml::Integer>());
|
||||||
|
BOOST_CHECK(v5.is_integer());
|
||||||
|
BOOST_CHECK(v6.is_integer());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Integer>(), -54);
|
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Integer>(), -54);
|
||||||
|
BOOST_CHECK_EQUAL(v5.as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v6.as_integer(), -54);
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
v2 = false;
|
v2 = false;
|
||||||
@@ -144,9 +185,13 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v2.is<toml::Boolean>());
|
BOOST_CHECK(v2.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_boolean());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_float)
|
BOOST_AUTO_TEST_CASE(test_value_float)
|
||||||
@@ -160,9 +205,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Float));
|
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v1.is<toml::Float>());
|
BOOST_CHECK(v1.is<toml::Float>());
|
||||||
BOOST_CHECK(v2.is<toml::Float>());
|
BOOST_CHECK(v2.is<toml::Float>());
|
||||||
|
BOOST_CHECK(v1.is_float());
|
||||||
|
BOOST_CHECK(v2.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL (v1.cast<toml::value_t::Float>(), 3.14);
|
BOOST_CHECK_EQUAL (v1.cast<toml::value_t::Float>(), 3.14);
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v2.cast<toml::value_t::Float>(), 3.14, 1e-2);
|
BOOST_CHECK_CLOSE_FRACTION(v2.cast<toml::value_t::Float>(), 3.14, 1e-2);
|
||||||
|
BOOST_CHECK_EQUAL (v1.as_float(), 3.14);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v2.as_float(), 3.14, 1e-2);
|
||||||
|
|
||||||
v1 = 2.718f;
|
v1 = 2.718f;
|
||||||
v2 = 2.718;
|
v2 = 2.718;
|
||||||
@@ -173,9 +222,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Float));
|
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v1.is<toml::Float>());
|
BOOST_CHECK(v1.is<toml::Float>());
|
||||||
BOOST_CHECK(v2.is<toml::Float>());
|
BOOST_CHECK(v2.is<toml::Float>());
|
||||||
|
BOOST_CHECK(v1.is_float());
|
||||||
|
BOOST_CHECK(v2.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v1.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
BOOST_CHECK_CLOSE_FRACTION(v1.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL (v2.cast<toml::value_t::Float>(), 2.718);
|
BOOST_CHECK_EQUAL (v2.cast<toml::value_t::Float>(), 2.718);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v1.as_float(), 2.718, 1e-3);
|
||||||
|
BOOST_CHECK_EQUAL (v2.as_float(), 2.718);
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
toml::value v4(v2);
|
toml::value v4(v2);
|
||||||
@@ -188,9 +241,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v4.is(toml::value_t::Float));
|
BOOST_CHECK(v4.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v3.is<toml::Float>());
|
BOOST_CHECK(v3.is<toml::Float>());
|
||||||
BOOST_CHECK(v4.is<toml::Float>());
|
BOOST_CHECK(v4.is<toml::Float>());
|
||||||
|
BOOST_CHECK(v3.is_float());
|
||||||
|
BOOST_CHECK(v4.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v3.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
BOOST_CHECK_CLOSE_FRACTION(v3.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL (v4.cast<toml::value_t::Float>(), 2.718);
|
BOOST_CHECK_EQUAL (v4.cast<toml::value_t::Float>(), 2.718);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v3.as_float(), 2.718, 1e-3);
|
||||||
|
BOOST_CHECK_EQUAL (v4.as_float(), 2.718);
|
||||||
|
|
||||||
toml::value v5(std::move(v1));
|
toml::value v5(std::move(v1));
|
||||||
toml::value v6(std::move(v2));
|
toml::value v6(std::move(v2));
|
||||||
@@ -201,9 +258,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v6.is(toml::value_t::Float));
|
BOOST_CHECK(v6.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v5.is<toml::Float>());
|
BOOST_CHECK(v5.is<toml::Float>());
|
||||||
BOOST_CHECK(v6.is<toml::Float>());
|
BOOST_CHECK(v6.is<toml::Float>());
|
||||||
|
BOOST_CHECK(v5.is_float());
|
||||||
|
BOOST_CHECK(v6.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v5.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
BOOST_CHECK_CLOSE_FRACTION(v5.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL (v6.cast<toml::value_t::Float>(), 2.718);
|
BOOST_CHECK_EQUAL (v6.cast<toml::value_t::Float>(), 2.718);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v5.as_float(), 2.718, 1e-3);
|
||||||
|
BOOST_CHECK_EQUAL (v6.as_float(), 2.718);
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
v2 = false;
|
v2 = false;
|
||||||
@@ -214,9 +275,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v2.is<toml::Boolean>());
|
BOOST_CHECK(v2.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_boolean());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_string)
|
BOOST_AUTO_TEST_CASE(test_value_string)
|
||||||
@@ -234,10 +299,17 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK(v1.is<toml::String>());
|
BOOST_CHECK(v1.is<toml::String>());
|
||||||
BOOST_CHECK(v2.is<toml::String>());
|
BOOST_CHECK(v2.is<toml::String>());
|
||||||
BOOST_CHECK(v3.is<toml::String>());
|
BOOST_CHECK(v3.is<toml::String>());
|
||||||
|
BOOST_CHECK(v1.is_string());
|
||||||
|
BOOST_CHECK(v2.is_string());
|
||||||
|
BOOST_CHECK(v3.is_string());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "foo");
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "foo");
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "foo");
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "foo");
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "foo");
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_string(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_string(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_string(), "foo");
|
||||||
|
|
||||||
|
|
||||||
v1 = "bar";
|
v1 = "bar";
|
||||||
v2 = "bar";
|
v2 = "bar";
|
||||||
@@ -249,13 +321,17 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK(v1.is(toml::value_t::String));
|
BOOST_CHECK(v1.is(toml::value_t::String));
|
||||||
BOOST_CHECK(v2.is(toml::value_t::String));
|
BOOST_CHECK(v2.is(toml::value_t::String));
|
||||||
BOOST_CHECK(v3.is(toml::value_t::String));
|
BOOST_CHECK(v3.is(toml::value_t::String));
|
||||||
BOOST_CHECK(v1.is<toml::String>());
|
BOOST_CHECK(v1.is_string());
|
||||||
BOOST_CHECK(v2.is<toml::String>());
|
BOOST_CHECK(v2.is_string());
|
||||||
BOOST_CHECK(v3.is<toml::String>());
|
BOOST_CHECK(v3.is_string());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "bar");
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "bar");
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_string(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_string(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_string(), "bar");
|
||||||
|
|
||||||
|
|
||||||
toml::value v4(v1);
|
toml::value v4(v1);
|
||||||
toml::value v5(v2);
|
toml::value v5(v2);
|
||||||
@@ -273,10 +349,17 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK(v4.is<toml::String>());
|
BOOST_CHECK(v4.is<toml::String>());
|
||||||
BOOST_CHECK(v5.is<toml::String>());
|
BOOST_CHECK(v5.is<toml::String>());
|
||||||
BOOST_CHECK(v6.is<toml::String>());
|
BOOST_CHECK(v6.is<toml::String>());
|
||||||
|
BOOST_CHECK(v4.is_string());
|
||||||
|
BOOST_CHECK(v5.is_string());
|
||||||
|
BOOST_CHECK(v6.is_string());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String>(), "bar");
|
||||||
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::String>(), "bar");
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::String>(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v4.as_string(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v5.as_string(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v6.as_string(), "bar");
|
||||||
|
|
||||||
|
|
||||||
v4.cast<toml::value_t::String>().str.at(2) = 'z';
|
v4.cast<toml::value_t::String>().str.at(2) = 'z';
|
||||||
v5.cast<toml::value_t::String>().str.at(2) = 'z';
|
v5.cast<toml::value_t::String>().str.at(2) = 'z';
|
||||||
@@ -291,10 +374,13 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK(v4.is<toml::String>());
|
BOOST_CHECK(v4.is<toml::String>());
|
||||||
BOOST_CHECK(v5.is<toml::String>());
|
BOOST_CHECK(v5.is<toml::String>());
|
||||||
BOOST_CHECK(v6.is<toml::String>());
|
BOOST_CHECK(v6.is<toml::String>());
|
||||||
|
BOOST_CHECK(v4.is_string());
|
||||||
|
BOOST_CHECK(v5.is_string());
|
||||||
|
BOOST_CHECK(v6.is_string());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String>(), "baz");
|
BOOST_CHECK_EQUAL(v4.as_string(), "baz");
|
||||||
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::String>(), "baz");
|
BOOST_CHECK_EQUAL(v5.as_string(), "baz");
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::String>(), "baz");
|
BOOST_CHECK_EQUAL(v6.as_string(), "baz");
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
v2 = true;
|
v2 = true;
|
||||||
@@ -309,10 +395,35 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v2.is<toml::Boolean>());
|
BOOST_CHECK(v2.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v3.is<toml::Boolean>());
|
BOOST_CHECK(v3.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_boolean());
|
||||||
|
BOOST_CHECK(v3.is_boolean());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_boolean(), true);
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
std::string_view sv = "foo";
|
||||||
|
|
||||||
|
toml::value v7(sv);
|
||||||
|
toml::value v8(sv, toml::string_t::literal);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v7.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK_EQUAL(v8.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK(v7.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v8.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v7.is<toml::String>());
|
||||||
|
BOOST_CHECK(v8.is<toml::String>());
|
||||||
|
BOOST_CHECK(v7.is_string());
|
||||||
|
BOOST_CHECK(v8.is_string());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v7.cast<toml::value_t::String>(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v8.cast<toml::value_t::String>(), "foo");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_date)
|
BOOST_AUTO_TEST_CASE(test_value_local_date)
|
||||||
@@ -322,18 +433,24 @@ BOOST_AUTO_TEST_CASE(test_value_local_date)
|
|||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDate);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDate);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::LocalDate));
|
BOOST_CHECK(v1.is(toml::value_t::LocalDate));
|
||||||
BOOST_CHECK(v1.is<toml::LocalDate>());
|
BOOST_CHECK(v1.is<toml::LocalDate>());
|
||||||
|
BOOST_CHECK(v1.is_local_date());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31));
|
toml::local_date(2018, toml::month_t::Jan, 31));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_date(),
|
||||||
|
toml::local_date(2018, toml::month_t::Jan, 31));
|
||||||
|
|
||||||
v1 = toml::local_date(2018, toml::month_t::Apr, 1);
|
v1 = toml::local_date(2018, toml::month_t::Apr, 1);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDate);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDate);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::LocalDate));
|
BOOST_CHECK(v1.is(toml::value_t::LocalDate));
|
||||||
BOOST_CHECK(v1.is<toml::LocalDate>());
|
BOOST_CHECK(v1.is<toml::LocalDate>());
|
||||||
|
BOOST_CHECK(v1.is_local_date());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1));
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_date(),
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
|
||||||
toml::value v2(v1);
|
toml::value v2(v1);
|
||||||
BOOST_CHECK(v2 == v1);
|
BOOST_CHECK(v2 == v1);
|
||||||
@@ -341,15 +458,20 @@ BOOST_AUTO_TEST_CASE(test_value_local_date)
|
|||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::LocalDate);
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::LocalDate);
|
||||||
BOOST_CHECK(v2.is(toml::value_t::LocalDate));
|
BOOST_CHECK(v2.is(toml::value_t::LocalDate));
|
||||||
BOOST_CHECK(v2.is<toml::LocalDate>());
|
BOOST_CHECK(v2.is<toml::LocalDate>());
|
||||||
|
BOOST_CHECK(v2.is_local_date());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalDate>(),
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalDate>(),
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1));
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_local_date(),
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_time)
|
BOOST_AUTO_TEST_CASE(test_value_local_time)
|
||||||
@@ -364,21 +486,34 @@ BOOST_AUTO_TEST_CASE(test_value_local_time)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::LocalTime));
|
BOOST_CHECK(v2.is(toml::value_t::LocalTime));
|
||||||
BOOST_CHECK(v1.is<toml::LocalTime>());
|
BOOST_CHECK(v1.is<toml::LocalTime>());
|
||||||
BOOST_CHECK(v2.is<toml::LocalTime>());
|
BOOST_CHECK(v2.is<toml::LocalTime>());
|
||||||
|
BOOST_CHECK(v1.is_local_time());
|
||||||
|
BOOST_CHECK(v2.is_local_time());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
||||||
toml::local_time(12, 30, 45));
|
toml::local_time(12, 30, 45));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_time(),
|
||||||
|
toml::local_time(12, 30, 45));
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalTime>(),
|
||||||
toml::local_time(12, 30, 45));
|
toml::local_time(12, 30, 45));
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_local_time(),
|
||||||
|
toml::local_time(12, 30, 45));
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
||||||
v2.cast<toml::value_t::LocalTime>());
|
v2.cast<toml::value_t::LocalTime>());
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_time(),
|
||||||
|
v2.as_local_time());
|
||||||
|
|
||||||
v1 = toml::local_time(1, 30, 0, /*ms*/ 100, /*us*/ 0);
|
v1 = toml::local_time(1, 30, 0, /*ms*/ 100, /*us*/ 0);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalTime);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalTime);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::LocalTime));
|
BOOST_CHECK(v1.is(toml::value_t::LocalTime));
|
||||||
BOOST_CHECK(v1.is<toml::LocalTime>());
|
BOOST_CHECK(v1.is<toml::LocalTime>());
|
||||||
|
BOOST_CHECK(v1.is_local_time());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
||||||
toml::local_time(1, 30, 0, 100, 0));
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_time(),
|
||||||
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
BOOST_CHECK(v3 == v1);
|
BOOST_CHECK(v3 == v1);
|
||||||
@@ -386,15 +521,20 @@ BOOST_AUTO_TEST_CASE(test_value_local_time)
|
|||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::LocalTime);
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::LocalTime);
|
||||||
BOOST_CHECK(v3.is(toml::value_t::LocalTime));
|
BOOST_CHECK(v3.is(toml::value_t::LocalTime));
|
||||||
BOOST_CHECK(v3.is<toml::LocalTime>());
|
BOOST_CHECK(v3.is<toml::LocalTime>());
|
||||||
|
BOOST_CHECK(v3.is_local_time());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::LocalTime>(),
|
||||||
toml::local_time(1, 30, 0, 100, 0));
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_local_time(),
|
||||||
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
||||||
@@ -407,11 +547,16 @@ BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
|||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDatetime);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDatetime);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::LocalDatetime));
|
BOOST_CHECK(v1.is(toml::value_t::LocalDatetime));
|
||||||
BOOST_CHECK(v1.is<toml::LocalDatetime>());
|
BOOST_CHECK(v1.is<toml::LocalDatetime>());
|
||||||
|
BOOST_CHECK(v1.is_local_datetime());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDatetime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDatetime>(),
|
||||||
toml::local_datetime(
|
toml::local_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31),
|
toml::local_date(2018, toml::month_t::Jan, 31),
|
||||||
toml::local_time(12, 30, 45)));
|
toml::local_time(12, 30, 45)));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_datetime(),
|
||||||
|
toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Jan, 31),
|
||||||
|
toml::local_time(12, 30, 45)));
|
||||||
|
|
||||||
v1 = toml::local_datetime(
|
v1 = toml::local_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
@@ -420,11 +565,16 @@ BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
|||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDatetime);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDatetime);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::LocalDatetime));
|
BOOST_CHECK(v1.is(toml::value_t::LocalDatetime));
|
||||||
BOOST_CHECK(v1.is<toml::LocalDatetime>());
|
BOOST_CHECK(v1.is<toml::LocalDatetime>());
|
||||||
|
BOOST_CHECK(v1.is_local_datetime());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDatetime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDatetime>(),
|
||||||
toml::local_datetime(
|
toml::local_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
toml::local_time(1, 15, 30)));
|
toml::local_time(1, 15, 30)));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_datetime(),
|
||||||
|
toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30)));
|
||||||
|
|
||||||
toml::value v2(v1);
|
toml::value v2(v1);
|
||||||
BOOST_CHECK(v2 == v1);
|
BOOST_CHECK(v2 == v1);
|
||||||
@@ -432,17 +582,25 @@ BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
|||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::LocalDatetime);
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::LocalDatetime);
|
||||||
BOOST_CHECK(v2.is(toml::value_t::LocalDatetime));
|
BOOST_CHECK(v2.is(toml::value_t::LocalDatetime));
|
||||||
BOOST_CHECK(v2.is<toml::LocalDatetime>());
|
BOOST_CHECK(v2.is<toml::LocalDatetime>());
|
||||||
|
BOOST_CHECK(v2.is_local_datetime());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalDatetime>(),
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalDatetime>(),
|
||||||
toml::local_datetime(
|
toml::local_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
toml::local_time(1, 15, 30)));
|
toml::local_time(1, 15, 30)));
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_local_datetime(),
|
||||||
|
toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30)));
|
||||||
|
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
||||||
@@ -456,6 +614,7 @@ BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
|||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::OffsetDatetime);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::OffsetDatetime);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::OffsetDatetime));
|
BOOST_CHECK(v1.is(toml::value_t::OffsetDatetime));
|
||||||
BOOST_CHECK(v1.is<toml::OffsetDatetime>());
|
BOOST_CHECK(v1.is<toml::OffsetDatetime>());
|
||||||
|
BOOST_CHECK(v1.is_offset_datetime());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::OffsetDatetime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::OffsetDatetime>(),
|
||||||
toml::offset_datetime(
|
toml::offset_datetime(
|
||||||
@@ -463,6 +622,12 @@ BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
|||||||
toml::local_time(12, 30, 45),
|
toml::local_time(12, 30, 45),
|
||||||
toml::time_offset(9, 0)
|
toml::time_offset(9, 0)
|
||||||
));
|
));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_offset_datetime(),
|
||||||
|
toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Jan, 31),
|
||||||
|
toml::local_time(12, 30, 45),
|
||||||
|
toml::time_offset(9, 0)
|
||||||
|
));
|
||||||
|
|
||||||
v1 = toml::offset_datetime(
|
v1 = toml::offset_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
@@ -472,12 +637,19 @@ BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
|||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::OffsetDatetime);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::OffsetDatetime);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::OffsetDatetime));
|
BOOST_CHECK(v1.is(toml::value_t::OffsetDatetime));
|
||||||
BOOST_CHECK(v1.is<toml::OffsetDatetime>());
|
BOOST_CHECK(v1.is<toml::OffsetDatetime>());
|
||||||
|
BOOST_CHECK(v1.is_offset_datetime());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::OffsetDatetime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::OffsetDatetime>(),
|
||||||
toml::offset_datetime(
|
toml::offset_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
toml::local_time(1, 15, 30),
|
toml::local_time(1, 15, 30),
|
||||||
toml::time_offset(9, 0)));
|
toml::time_offset(9, 0)));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_offset_datetime(),
|
||||||
|
toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30),
|
||||||
|
toml::time_offset(9, 0)));
|
||||||
|
|
||||||
|
|
||||||
toml::value v2(v1);
|
toml::value v2(v1);
|
||||||
BOOST_CHECK(v2 == v1);
|
BOOST_CHECK(v2 == v1);
|
||||||
@@ -485,17 +657,26 @@ BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
|||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::OffsetDatetime);
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::OffsetDatetime);
|
||||||
BOOST_CHECK(v2.is(toml::value_t::OffsetDatetime));
|
BOOST_CHECK(v2.is(toml::value_t::OffsetDatetime));
|
||||||
BOOST_CHECK(v2.is<toml::OffsetDatetime>());
|
BOOST_CHECK(v2.is<toml::OffsetDatetime>());
|
||||||
|
BOOST_CHECK(v2.is_offset_datetime());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::OffsetDatetime>(),
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::OffsetDatetime>(),
|
||||||
toml::offset_datetime(
|
toml::offset_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
toml::local_time(1, 15, 30),
|
toml::local_time(1, 15, 30),
|
||||||
toml::time_offset(9, 0)));
|
toml::time_offset(9, 0)));
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_offset_datetime(),
|
||||||
|
toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30),
|
||||||
|
toml::time_offset(9, 0)));
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_array)
|
BOOST_AUTO_TEST_CASE(test_value_array)
|
||||||
@@ -507,16 +688,24 @@ BOOST_AUTO_TEST_CASE(test_value_array)
|
|||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Array));
|
BOOST_CHECK(v1.is(toml::value_t::Array));
|
||||||
BOOST_CHECK(v1.is<toml::Array>());
|
BOOST_CHECK(v1.is<toml::Array>());
|
||||||
|
BOOST_CHECK(v1.is_array());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Array);
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Array);
|
||||||
BOOST_CHECK(v2.is(toml::value_t::Array));
|
BOOST_CHECK(v2.is(toml::value_t::Array));
|
||||||
BOOST_CHECK(v2.is<toml::Array>());
|
BOOST_CHECK(v2.is<toml::Array>());
|
||||||
|
BOOST_CHECK(v2.is_array());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 1);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 1);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 2);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 2);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(0).as_integer(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(1).as_integer(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(2).as_integer(), 3);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(3).as_integer(), 4);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(4).as_integer(), 5);
|
||||||
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
||||||
@@ -530,22 +719,36 @@ BOOST_AUTO_TEST_CASE(test_value_array)
|
|||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Array));
|
BOOST_CHECK(v1.is(toml::value_t::Array));
|
||||||
BOOST_CHECK(v1.is<toml::Array>());
|
BOOST_CHECK(v1.is<toml::Array>());
|
||||||
|
BOOST_CHECK(v1.is_array());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Array);
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Array);
|
||||||
BOOST_CHECK(v2.is(toml::value_t::Array));
|
BOOST_CHECK(v2.is(toml::value_t::Array));
|
||||||
BOOST_CHECK(v2.is<toml::Array>());
|
BOOST_CHECK(v2.is<toml::Array>());
|
||||||
|
BOOST_CHECK(v2.is_array());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(0).as_integer(), 6);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(1).as_integer(), 7);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(2).as_integer(), 8);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(3).as_integer(), 9);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(4).as_integer(), 0);
|
||||||
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 1);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 1);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 2);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 2);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(0).as_integer(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(1).as_integer(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(2).as_integer(), 3);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(3).as_integer(), 4);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(4).as_integer(), 5);
|
||||||
|
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
BOOST_CHECK(v3 == v1);
|
BOOST_CHECK(v3 == v1);
|
||||||
@@ -553,18 +756,27 @@ BOOST_AUTO_TEST_CASE(test_value_array)
|
|||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Array);
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Array);
|
||||||
BOOST_CHECK(v3.is(toml::value_t::Array));
|
BOOST_CHECK(v3.is(toml::value_t::Array));
|
||||||
BOOST_CHECK(v3.is<toml::Array>());
|
BOOST_CHECK(v3.is<toml::Array>());
|
||||||
|
BOOST_CHECK(v3.is_array());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(0).as_integer(), 6);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(1).as_integer(), 7);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(2).as_integer(), 8);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(3).as_integer(), 9);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(4).as_integer(), 0);
|
||||||
|
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_table)
|
BOOST_AUTO_TEST_CASE(test_value_table)
|
||||||
@@ -574,20 +786,30 @@ BOOST_AUTO_TEST_CASE(test_value_table)
|
|||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Table);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Table);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Table));
|
BOOST_CHECK(v1.is(toml::value_t::Table));
|
||||||
BOOST_CHECK(v1.is<toml::Table>());
|
BOOST_CHECK(v1.is<toml::Table>());
|
||||||
|
BOOST_CHECK(v1.is_table());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Integer>(), 42);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Integer>(), 42);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Float>(), 3.14);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Float>(), 3.14);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "qux");
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "qux");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("foo").as_integer(), 42);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_float(), 3.14);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "qux");
|
||||||
|
|
||||||
|
|
||||||
v1 = toml::table{{"foo", 2.71}, {"bar", 54}, {"baz", "quux"}};
|
v1 = toml::table{{"foo", 2.71}, {"bar", 54}, {"baz", "quux"}};
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Table);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Table);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Table));
|
BOOST_CHECK(v1.is(toml::value_t::Table));
|
||||||
BOOST_CHECK(v1.is<toml::Table>());
|
BOOST_CHECK(v1.is<toml::Table>());
|
||||||
|
BOOST_CHECK(v1.is_table());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Float>(), 2.71);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Float>(), 2.71);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "quux");
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "quux");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("foo").as_float(), 2.71);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "quux");
|
||||||
|
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
BOOST_CHECK(v3 == v1);
|
BOOST_CHECK(v3 == v1);
|
||||||
@@ -595,14 +817,28 @@ BOOST_AUTO_TEST_CASE(test_value_table)
|
|||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Table);
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Table);
|
||||||
BOOST_CHECK(v3.is(toml::value_t::Table));
|
BOOST_CHECK(v3.is(toml::value_t::Table));
|
||||||
BOOST_CHECK(v3.is<toml::Table>());
|
BOOST_CHECK(v3.is<toml::Table>());
|
||||||
|
BOOST_CHECK(v3.is_table());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Float>(), 2.71);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Float>(), 2.71);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "quux");
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "quux");
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_table().at("foo").as_float(), 2.71);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_table().at("bar").as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_table().at("baz").as_string().str, "quux");
|
||||||
|
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_empty)
|
||||||
|
{
|
||||||
|
toml::value v1;
|
||||||
|
BOOST_CHECK(v1.is_uninitialized());
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Empty));
|
||||||
}
|
}
|
||||||
|
|||||||
3
toml.hpp
3
toml.hpp
@@ -34,7 +34,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "toml/parser.hpp"
|
#include "toml/parser.hpp"
|
||||||
#include "toml/to_toml.hpp"
|
#include "toml/literal.hpp"
|
||||||
|
#include "toml/serializer.hpp"
|
||||||
#include "toml/from_toml.hpp"
|
#include "toml/from_toml.hpp"
|
||||||
#include "toml/get.hpp"
|
#include "toml/get.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <array>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
// they scans characters and returns region if it matches to the condition.
|
// they scans characters and returns region if it matches to the condition.
|
||||||
@@ -38,10 +41,12 @@ inline std::string show_char(const char c)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::array<char, 5> buf;
|
||||||
oss << std::hex << std::setfill('0') << std::setw(2) << "0x"
|
buf.fill('\0');
|
||||||
<< static_cast<int>(c);
|
const auto r = std::snprintf(
|
||||||
return oss.str();
|
buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
|
||||||
|
assert(r == buf.size() - 1);
|
||||||
|
return std::string(buf.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,26 +56,24 @@ struct character
|
|||||||
static constexpr char target = C;
|
static constexpr char target = C;
|
||||||
|
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
|
|
||||||
const char c = *(loc.iter());
|
const char c = *(loc.iter());
|
||||||
if(c != target)
|
if(c != target)
|
||||||
{
|
{
|
||||||
return err(concat_to_string("expected '", show_char(target),
|
return none();
|
||||||
"' but got '", show_char(c), "'."));
|
|
||||||
}
|
}
|
||||||
++(loc.iter()); // update location
|
loc.advance(); // update location
|
||||||
|
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region<Cont>(loc, first, loc.iter()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern() {return show_char(target);}
|
|
||||||
};
|
};
|
||||||
template<char C>
|
template<char C>
|
||||||
constexpr char character<C>::target;
|
constexpr char character<C>::target;
|
||||||
@@ -86,30 +89,24 @@ struct in_range
|
|||||||
static constexpr char lower = Low;
|
static constexpr char lower = Low;
|
||||||
|
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
|
|
||||||
const char c = *(loc.iter());
|
const char c = *(loc.iter());
|
||||||
if(c < lower || upper < c)
|
if(c < lower || upper < c)
|
||||||
{
|
{
|
||||||
return err(concat_to_string("expected character in range "
|
return none();
|
||||||
"[", show_char(lower), ", ", show_char(upper), "] but got ",
|
|
||||||
"'", show_char(c), "'."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++(loc.iter());
|
loc.advance();
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region<Cont>(loc, first, loc.iter()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
|
||||||
{
|
|
||||||
return concat_to_string("[",show_char(lower),"-",show_char(upper),"]");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
template<char L, char U> constexpr char in_range<L, U>::upper;
|
template<char L, char U> constexpr char in_range<L, U>::upper;
|
||||||
template<char L, char U> constexpr char in_range<L, U>::lower;
|
template<char L, char U> constexpr char in_range<L, U>::lower;
|
||||||
@@ -120,30 +117,24 @@ template<typename Combinator>
|
|||||||
struct exclude
|
struct exclude
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
auto first = loc.iter();
|
auto first = loc.iter();
|
||||||
|
|
||||||
auto rslt = Combinator::invoke(loc);
|
auto rslt = Combinator::invoke(loc);
|
||||||
if(rslt.is_ok())
|
if(rslt.is_ok())
|
||||||
{
|
{
|
||||||
loc.iter() = first; // rollback
|
loc.reset(first);
|
||||||
return err(concat_to_string(
|
return none();
|
||||||
"invalid pattern (", Combinator::pattern(), ") appeared ",
|
|
||||||
rslt.unwrap().str()));
|
|
||||||
}
|
}
|
||||||
loc.iter() = std::next(first);
|
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region<Cont>(loc, first, loc.iter()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
|
||||||
{
|
|
||||||
return concat_to_string("^(", Combinator::pattern(), ')');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// increment `iter`, if matches. otherwise, just return empty string.
|
// increment `iter`, if matches. otherwise, just return empty string.
|
||||||
@@ -151,7 +142,8 @@ template<typename Combinator>
|
|||||||
struct maybe
|
struct maybe
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -163,11 +155,6 @@ struct maybe
|
|||||||
}
|
}
|
||||||
return ok(region<Cont>(loc));
|
return ok(region<Cont>(loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
|
||||||
{
|
|
||||||
return concat_to_string('(', Combinator::pattern(), ")?");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ... Ts>
|
template<typename ... Ts>
|
||||||
@@ -177,7 +164,8 @@ template<typename Head, typename ... Tail>
|
|||||||
struct sequence<Head, Tail...>
|
struct sequence<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -186,31 +174,26 @@ struct sequence<Head, Tail...>
|
|||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.iter() = first;
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
|
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from the above function only, recursively.
|
// called from the above function only, recursively.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Cont, typename Iterator>
|
||||||
static result<region<Cont>, std::string>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.iter() = first;
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
reg += rslt.unwrap(); // concat regions
|
reg += rslt.unwrap(); // concat regions
|
||||||
return sequence<Tail...>::invoke(loc, std::move(reg), first);
|
return sequence<Tail...>::invoke(loc, std::move(reg), first);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
|
||||||
{
|
|
||||||
return concat_to_string(Head::pattern(), sequence<Tail...>::pattern());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Head>
|
template<typename Head>
|
||||||
@@ -218,19 +201,18 @@ struct sequence<Head>
|
|||||||
{
|
{
|
||||||
// would be called from sequence<T ...>::invoke only.
|
// would be called from sequence<T ...>::invoke only.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Cont, typename Iterator>
|
||||||
static result<region<Cont>, std::string>
|
static result<region<Cont>, none_t>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.iter() = first;
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
reg += rslt.unwrap(); // concat regions
|
reg += rslt.unwrap(); // concat regions
|
||||||
return ok(reg);
|
return ok(reg);
|
||||||
}
|
}
|
||||||
static std::string pattern() {return Head::pattern();}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ... Ts>
|
template<typename ... Ts>
|
||||||
@@ -240,7 +222,8 @@ template<typename Head, typename ... Tail>
|
|||||||
struct either<Head, Tail...>
|
struct either<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -249,26 +232,18 @@ struct either<Head, Tail...>
|
|||||||
if(rslt.is_ok()) {return rslt;}
|
if(rslt.is_ok()) {return rslt;}
|
||||||
return either<Tail...>::invoke(loc);
|
return either<Tail...>::invoke(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
|
||||||
{
|
|
||||||
return concat_to_string('(', Head::pattern(), ")|", either<Tail...>::pattern());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
template<typename Head>
|
template<typename Head>
|
||||||
struct either<Head>
|
struct either<Head>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
return Head::invoke(loc);
|
return Head::invoke(loc);
|
||||||
}
|
}
|
||||||
static std::string pattern()
|
|
||||||
{
|
|
||||||
return concat_to_string('(', Head::pattern(), ')');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename N>
|
template<typename T, typename N>
|
||||||
@@ -282,7 +257,8 @@ template<typename T, std::size_t N>
|
|||||||
struct repeat<T, exactly<N>>
|
struct repeat<T, exactly<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
@@ -291,24 +267,21 @@ struct repeat<T, exactly<N>>
|
|||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.iter() = first;
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
retval += rslt.unwrap();
|
retval += rslt.unwrap();
|
||||||
}
|
}
|
||||||
return ok(std::move(retval));
|
return ok(std::move(retval));
|
||||||
}
|
}
|
||||||
static std::string pattern()
|
|
||||||
{
|
|
||||||
return concat_to_string('(', T::pattern(), "){", N, '}');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, std::size_t N>
|
template<typename T, std::size_t N>
|
||||||
struct repeat<T, at_least<N>>
|
struct repeat<T, at_least<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
|
|
||||||
@@ -318,8 +291,8 @@ struct repeat<T, at_least<N>>
|
|||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.iter() = first;
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return none();
|
||||||
}
|
}
|
||||||
retval += rslt.unwrap();
|
retval += rslt.unwrap();
|
||||||
}
|
}
|
||||||
@@ -333,17 +306,14 @@ struct repeat<T, at_least<N>>
|
|||||||
retval += rslt.unwrap();
|
retval += rslt.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static std::string pattern()
|
|
||||||
{
|
|
||||||
return concat_to_string('(',T::pattern(), "){", N, ",}");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct repeat<T, unlimited>
|
struct repeat<T, unlimited>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, none_t>
|
||||||
|
invoke(location<Cont>& loc)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
while(true)
|
while(true)
|
||||||
@@ -356,7 +326,6 @@ struct repeat<T, unlimited>
|
|||||||
retval += rslt.unwrap();
|
retval += rslt.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static std::string pattern() {return concat_to_string('(', T::pattern(), ")*");}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_DATETIME
|
#ifndef TOML11_DATETIME_HPP
|
||||||
#define TOML11_DATETIME
|
#define TOML11_DATETIME_HPP
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -14,6 +14,38 @@
|
|||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// To avoid non-threadsafe std::localtime. In C11 (not C++11!), localtime_s is
|
||||||
|
// provided in the absolutely same purpose, but C++11 is actually not compatible
|
||||||
|
// with C11. We need to dispatch the function depending on the OS.
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// TODO: find more sophisticated way to handle this
|
||||||
|
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE
|
||||||
|
inline std::tm localtime_s(const std::time_t* src)
|
||||||
|
{
|
||||||
|
std::tm dst;
|
||||||
|
const auto result = ::localtime_r(src, &dst);
|
||||||
|
if (!result) { throw std::runtime_error("localtime_r failed."); }
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
#elif _MSC_VER
|
||||||
|
inline std::tm localtime_s(const std::time_t* src)
|
||||||
|
{
|
||||||
|
std::tm dst;
|
||||||
|
const auto result = ::localtime_s(&dst, src);
|
||||||
|
if (result) { throw std::runtime_error("localtime_s failed."); }
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
inline std::tm localtime_s(const std::time_t* src)
|
||||||
|
{
|
||||||
|
const auto result = std::localtime(src);
|
||||||
|
if (!result) { throw std::runtime_error("localtime failed."); }
|
||||||
|
return *result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // detail
|
||||||
|
|
||||||
enum class month_t : std::int8_t
|
enum class month_t : std::int8_t
|
||||||
{
|
{
|
||||||
Jan = 0,
|
Jan = 0,
|
||||||
@@ -51,9 +83,7 @@ struct local_date
|
|||||||
explicit local_date(const std::chrono::system_clock::time_point& tp)
|
explicit local_date(const std::chrono::system_clock::time_point& tp)
|
||||||
{
|
{
|
||||||
const auto t = std::chrono::system_clock::to_time_t(tp);
|
const auto t = std::chrono::system_clock::to_time_t(tp);
|
||||||
const auto tmp = std::localtime(&t); //XXX: not threadsafe!
|
const auto time = detail::localtime_s(&t);
|
||||||
assert(tmp); // if std::localtime fails, tmp is nullptr
|
|
||||||
const std::tm time = *tmp;
|
|
||||||
*this = local_date(time);
|
*this = local_date(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,17 +334,10 @@ operator<<(std::basic_ostream<charT, traits>& os, const time_offset& offset)
|
|||||||
os << 'Z';
|
os << 'Z';
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
if(static_cast<int>(offset.hour) * static_cast<int>(offset.minute) < 0)
|
int minute = static_cast<int>(offset.hour) * 60 + offset.minute;
|
||||||
{
|
if(minute < 0){os << '-'; minute = std::abs(minute);} else {os << '+';}
|
||||||
const int min = static_cast<int>(offset.hour) * 60 + offset.minute;
|
os << std::setfill('0') << std::setw(2) << minute / 60 << ':';
|
||||||
if(min < 0){os << '-';} else {os << '+';}
|
os << std::setfill('0') << std::setw(2) << minute % 60;
|
||||||
os << std::setfill('0') << std::setw(2) << min / 60 << ':';
|
|
||||||
os << std::setfill('0') << std::setw(2) << min % 60;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
if(offset.hour < 0){os << '-';} else {os << '+';}
|
|
||||||
os << std::setfill('0') << std::setw(2) << static_cast<int>(offset.hour) << ':';
|
|
||||||
os << std::setfill('0') << std::setw(2) << static_cast<int>(offset.minute);
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,23 +353,21 @@ struct local_datetime
|
|||||||
explicit local_datetime(const std::chrono::system_clock::time_point& tp)
|
explicit local_datetime(const std::chrono::system_clock::time_point& tp)
|
||||||
{
|
{
|
||||||
const auto t = std::chrono::system_clock::to_time_t(tp);
|
const auto t = std::chrono::system_clock::to_time_t(tp);
|
||||||
const auto tmp = std::localtime(&t); //XXX: not threadsafe!
|
std::tm ltime = detail::localtime_s(&t);
|
||||||
assert(tmp); // if std::localtime fails, tmp is nullptr
|
|
||||||
|
|
||||||
std::tm time = *tmp;
|
this->date = local_date(ltime);
|
||||||
this->date = local_date(time);
|
this->time = local_time(ltime);
|
||||||
this->time = local_time(time);
|
|
||||||
|
|
||||||
// std::tm lacks subsecond information, so diff between tp and tm
|
// std::tm lacks subsecond information, so diff between tp and tm
|
||||||
// can be used to get millisecond & microsecond information.
|
// can be used to get millisecond & microsecond information.
|
||||||
const auto t_diff = tp -
|
const auto t_diff = tp -
|
||||||
std::chrono::system_clock::from_time_t(std::mktime(&time));
|
std::chrono::system_clock::from_time_t(std::mktime(<ime));
|
||||||
this->time.millisecond = std::chrono::duration_cast<
|
this->time.millisecond = static_cast<std::uint16_t>(
|
||||||
std::chrono::milliseconds>(t_diff).count();
|
std::chrono::duration_cast<std::chrono::milliseconds>(t_diff).count());
|
||||||
this->time.microsecond = std::chrono::duration_cast<
|
this->time.microsecond = static_cast<std::uint16_t>(
|
||||||
std::chrono::microseconds>(t_diff).count();
|
std::chrono::duration_cast<std::chrono::microseconds>(t_diff).count());
|
||||||
this->time.nanosecond = std::chrono::duration_cast<
|
this->time.nanosecond = static_cast<std::uint16_t>(
|
||||||
std::chrono::nanoseconds >(t_diff).count();
|
std::chrono::duration_cast<std::chrono::nanoseconds >(t_diff).count());
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit local_datetime(const std::time_t t)
|
explicit local_datetime(const std::time_t t)
|
||||||
@@ -483,9 +504,7 @@ struct offset_datetime
|
|||||||
{
|
{
|
||||||
// get current timezone
|
// get current timezone
|
||||||
const auto tmp1 = std::time(nullptr);
|
const auto tmp1 = std::time(nullptr);
|
||||||
const auto tmp2 = std::localtime(&tmp1); // XXX not threadsafe!
|
const auto t = detail::localtime_s(&tmp1);
|
||||||
assert(tmp2);
|
|
||||||
std::tm t = *tmp2;
|
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_EXCEPTION
|
#ifndef TOML11_EXCEPTION_HPP
|
||||||
#define TOML11_EXCEPTION
|
#define TOML11_EXCEPTION_HPP
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|||||||
20
toml/from.hpp
Normal file
20
toml/from.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright Toru Niina 2019.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_FROM_HPP
|
||||||
|
#define TOML11_FROM_HPP
|
||||||
|
#include "traits.hpp"
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct from;
|
||||||
|
// {
|
||||||
|
// static T from_toml(const toml::value& v)
|
||||||
|
// {
|
||||||
|
// // User-defined conversions ...
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
} // toml
|
||||||
|
#endif // TOML11_FROM_HPP
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_FROM_TOML
|
#ifndef TOML11_FROM_TOML_HPP
|
||||||
#define TOML11_FROM_TOML
|
#define TOML11_FROM_TOML_HPP
|
||||||
#include "get.hpp"
|
#include "get.hpp"
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
@@ -51,7 +51,7 @@ struct from_toml_tie_impl
|
|||||||
template<typename ... Ts>
|
template<typename ... Ts>
|
||||||
struct from_toml_tie_impl<0, Ts...>
|
struct from_toml_tie_impl<0, Ts...>
|
||||||
{
|
{
|
||||||
static void invoke(std::tuple<Ts& ...> tie, const toml::value& v)
|
static void invoke(std::tuple<Ts& ...>, const toml::value&)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
388
toml/get.hpp
388
toml/get.hpp
@@ -1,7 +1,8 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_GET
|
#ifndef TOML11_GET_HPP
|
||||||
#define TOML11_GET
|
#define TOML11_GET_HPP
|
||||||
|
#include "from.hpp"
|
||||||
#include "result.hpp"
|
#include "result.hpp"
|
||||||
#include "value.hpp"
|
#include "value.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -107,12 +108,24 @@ inline std::string get(value&& v)
|
|||||||
return std::move(v.cast<value_t::String>().str);
|
return std::move(v.cast<value_t::String>().str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// std::string_view
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string_view>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline std::string_view get(const value& v)
|
||||||
|
{
|
||||||
|
return std::string_view(v.cast<value_t::String>().str);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// std::chrono::duration from toml::local_time.
|
// std::chrono::duration from toml::local_time.
|
||||||
|
|
||||||
template<typename T, typename std::enable_if<
|
template<typename T, typename std::enable_if<
|
||||||
detail::is_chrono_duration<T>::value, std::nullptr_t>::type = nullptr>
|
detail::is_chrono_duration<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
inline T get(value& v)
|
inline T get(const value& v)
|
||||||
{
|
{
|
||||||
return std::chrono::duration_cast<T>(
|
return std::chrono::duration_cast<T>(
|
||||||
std::chrono::nanoseconds(v.cast<value_t::LocalTime>()));
|
std::chrono::nanoseconds(v.cast<value_t::LocalTime>()));
|
||||||
@@ -124,7 +137,7 @@ inline T get(value& v)
|
|||||||
template<typename T, typename std::enable_if<
|
template<typename T, typename std::enable_if<
|
||||||
std::is_same<std::chrono::system_clock::time_point, T>::value,
|
std::is_same<std::chrono::system_clock::time_point, T>::value,
|
||||||
std::nullptr_t>::type = nullptr>
|
std::nullptr_t>::type = nullptr>
|
||||||
inline T get(value& v)
|
inline T get(const value& v)
|
||||||
{
|
{
|
||||||
switch(v.type())
|
switch(v.type())
|
||||||
{
|
{
|
||||||
@@ -173,6 +186,20 @@ template<typename T, typename std::enable_if<detail::conjunction<
|
|||||||
>::value, std::nullptr_t>::type = nullptr>
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
T get(const toml::value& v);
|
T get(const toml::value& v);
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
|
||||||
|
detail::has_from_toml_method<T>, // but has from_toml(toml::value) memfn
|
||||||
|
std::is_default_constructible<T> // and default constructible
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T get(const toml::value& v);
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // not a toml::value
|
||||||
|
>::value, std::nullptr_t>::type = nullptr,
|
||||||
|
std::size_t = sizeof(::toml::from<T>) // and has from<T> specialization
|
||||||
|
>
|
||||||
|
T get(const toml::value& v);
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// array-like types; most likely STL container, like std::vector, etc.
|
// array-like types; most likely STL container, like std::vector, etc.
|
||||||
|
|
||||||
@@ -210,8 +237,9 @@ T get(const value& v)
|
|||||||
{
|
{
|
||||||
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(),
|
"[erorr] 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."), {
|
||||||
detail::get_region(v), "here"));
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
||||||
[](const value& x){return ::toml::get<value_type>(x);});
|
[](const value& x){return ::toml::get<value_type>(x);});
|
||||||
@@ -233,7 +261,9 @@ T get(const value& v)
|
|||||||
{
|
{
|
||||||
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(),
|
"[erorr] toml::get specified std::pair but there are ", ar.size(),
|
||||||
" elements in toml array."), detail::get_region(v), "here"));
|
" elements in toml array."), {
|
||||||
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return std::make_pair(::toml::get<first_type >(ar.at(0)),
|
return std::make_pair(::toml::get<first_type >(ar.at(0)),
|
||||||
::toml::get<second_type>(ar.at(1)));
|
::toml::get<second_type>(ar.at(1)));
|
||||||
@@ -246,7 +276,7 @@ namespace detail
|
|||||||
{
|
{
|
||||||
|
|
||||||
template<typename T, std::size_t ...I>
|
template<typename T, std::size_t ...I>
|
||||||
T get_tuple_impl(const toml::Array& a, index_sequence<I...>)
|
T get_tuple_impl(const toml::array& a, index_sequence<I...>)
|
||||||
{
|
{
|
||||||
return std::make_tuple(
|
return std::make_tuple(
|
||||||
::toml::get<typename std::tuple_element<I, T>::type>(a.at(I))...);
|
::toml::get<typename std::tuple_element<I, T>::type>(a.at(I))...);
|
||||||
@@ -264,7 +294,9 @@ T get(const value& v)
|
|||||||
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 ",
|
"[erorr] 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."), detail::get_region(v), "here"));
|
" elements in toml array."), {
|
||||||
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return detail::get_tuple_impl<T>(ar,
|
return detail::get_tuple_impl<T>(ar,
|
||||||
detail::make_index_sequence<std::tuple_size<T>::value>{});
|
detail::make_index_sequence<std::tuple_size<T>::value>{});
|
||||||
@@ -292,6 +324,29 @@ T get(const toml::value& v)
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// user-defined, but compatible types.
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
|
||||||
|
detail::has_from_toml_method<T>, // but has from_toml(toml::value) memfn
|
||||||
|
std::is_default_constructible<T> // and default constructible
|
||||||
|
>::value, std::nullptr_t>::type>
|
||||||
|
T get(const toml::value& v)
|
||||||
|
{
|
||||||
|
T ud;
|
||||||
|
ud.from_toml(v);
|
||||||
|
return ud;
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // not a toml::value
|
||||||
|
>::value, std::nullptr_t>::type, std::size_t> // and has from<T>
|
||||||
|
T get(const toml::value& v)
|
||||||
|
{
|
||||||
|
return ::toml::from<T>::from_toml(v);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// find and get
|
// find and get
|
||||||
|
|
||||||
@@ -340,8 +395,9 @@ find(const toml::value& v, const toml::key& ky)
|
|||||||
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"), detail::get_region(v),
|
"[error] key \"", ky, "\" not found"), {
|
||||||
"in this table"));
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return ::toml::get<T>(tab.at(ky));
|
return ::toml::get<T>(tab.at(ky));
|
||||||
}
|
}
|
||||||
@@ -353,8 +409,9 @@ find(toml::value& v, const toml::key& ky)
|
|||||||
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"), detail::get_region(v),
|
"[error] key \"", ky, "\" not found"), {
|
||||||
"in this table"));
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return ::toml::get<T>(tab.at(ky));
|
return ::toml::get<T>(tab.at(ky));
|
||||||
}
|
}
|
||||||
@@ -366,21 +423,23 @@ find(toml::value&& v, const toml::key& ky)
|
|||||||
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"), detail::get_region(v),
|
"[error] key \"", ky, "\" not found"), {
|
||||||
"in this table"));
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return ::toml::get<T>(std::move(tab[ky]));
|
return ::toml::get<T>(std::move(tab[ky]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// get_or
|
// get_or(value, fallback)
|
||||||
|
|
||||||
template<typename T>
|
// ----------------------------------------------------------------------------
|
||||||
decltype(::toml::get<typename std::remove_cv<
|
// specialization for the exact toml types (return type becomes lvalue ref)
|
||||||
typename std::remove_reference<T>::type>::type>(
|
|
||||||
std::declval<const toml::value&>()))
|
template<typename T, typename std::enable_if<
|
||||||
get_or(const toml::value& v, T&& opt)
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T const& get_or(const toml::value& v, const T& opt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -389,14 +448,12 @@ get_or(const toml::value& v, T&& opt)
|
|||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return std::forward<T>(opt);
|
return opt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T, typename std::enable_if<
|
||||||
decltype(::toml::get<typename std::remove_cv<
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
typename std::remove_reference<T>::type>::type>(
|
T& get_or(toml::value& v, T& opt)
|
||||||
std::declval<toml::value&>()))
|
|
||||||
get_or(toml::value& v, T&& opt)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -405,75 +462,270 @@ get_or(toml::value& v, T&& opt)
|
|||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return std::forward<T>(opt);
|
return opt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T, typename std::enable_if<
|
||||||
decltype(::toml::get<typename std::remove_cv<
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
typename std::remove_reference<T>::type>::type>(
|
T&& get_or(toml::value&& v, T&& opt)
|
||||||
std::declval<toml::value&&>()))
|
|
||||||
get_or(toml::value&& v, T&& opt)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return get<typename std::remove_cv<
|
return get<typename std::remove_cv<
|
||||||
typename std::remove_reference<T>::type>::type>(std::move(v));
|
typename std::remove_reference<T>::type>::type>(v);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return std::forward<T>(opt);
|
return opt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// specialization for std::string (return type becomes lvalue ref)
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename std::enable_if<
|
||||||
auto get_or(const toml::table& tab, const toml::key& ky, T&& opt)
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
-> decltype(get_or(std::declval<value const&>(), std::forward<T>(opt)))
|
std::string const& get_or(const toml::value& v, const T& opt)
|
||||||
{
|
{
|
||||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
try
|
||||||
return ::toml::get_or(tab.at(ky), std::forward<T>(opt));
|
{
|
||||||
|
return get<std::string>(v);
|
||||||
}
|
}
|
||||||
template<typename T>
|
catch(...)
|
||||||
auto get_or(toml::table& tab, const toml::key& ky, T&& opt)
|
|
||||||
-> decltype(get_or(std::declval<value&>(), std::forward<T>(opt)))
|
|
||||||
{
|
{
|
||||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
return opt;
|
||||||
return ::toml::get_or(tab[ky], std::forward<T>(opt));
|
|
||||||
}
|
}
|
||||||
template<typename T>
|
}
|
||||||
auto get_or(toml::table&& tab, const toml::key& ky, T&& opt)
|
template<typename T, typename std::enable_if<
|
||||||
-> decltype(get_or(std::declval<value&&>(), std::forward<T>(opt)))
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string& get_or(toml::value& v, T& opt)
|
||||||
{
|
{
|
||||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
try
|
||||||
return ::toml::get_or(std::move(tab[ky]), std::forward<T>(opt));
|
{
|
||||||
|
return get<std::string>(v);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string get_or(toml::value&& v, T&& opt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return get<std::string>(v);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_string_literal<typename std::remove_reference<T>::type>::value,
|
||||||
|
std::nullptr_t>::type = nullptr>
|
||||||
|
std::string get_or(const toml::value& v, T&& opt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return get<std::string>(v);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return std::string(opt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
// ----------------------------------------------------------------------------
|
||||||
auto get_or(const toml::value& v, const toml::key& ky, T&& opt)
|
// others (require type conversion and return type cannot be lvalue reference)
|
||||||
-> decltype(get_or(std::declval<value const&>(), std::forward<T>(opt)))
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>,
|
||||||
|
detail::negation<std::is_same<T, std::string>>,
|
||||||
|
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T get_or(const toml::value& v, T&& opt)
|
||||||
{
|
{
|
||||||
if(v.type() != toml::value_t::Table){return std::forward<T>(opt);}
|
try
|
||||||
|
{
|
||||||
|
return get<typename std::remove_cv<
|
||||||
|
typename std::remove_reference<T>::type>::type>(v);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
// find_or(value, key, fallback)
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// exact types (return type can be a reference)
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T const& find_or(const toml::value& v, const toml::key& ky, const T& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
const auto& tab = toml::get<toml::table>(v);
|
const auto& tab = toml::get<toml::table>(v);
|
||||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
return ::toml::get_or(tab.at(ky), std::forward<T>(opt));
|
return get_or(tab.at(ky), opt);
|
||||||
}
|
}
|
||||||
template<typename T>
|
|
||||||
auto get_or(toml::value& v, const toml::key& ky, T&& opt)
|
template<typename T, typename std::enable_if<
|
||||||
-> decltype(get_or(std::declval<value&>(), std::forward<T>(opt)))
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T& find_or(toml::value& v, const toml::key& ky, T& opt)
|
||||||
{
|
{
|
||||||
if(v.type() != toml::value_t::Table){return std::forward<T>(opt);}
|
if(!v.is_table()) {return opt;}
|
||||||
auto& tab = toml::get<toml::table>(v);
|
auto& tab = toml::get<toml::table>(v);
|
||||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
return ::toml::get_or(tab[ky], std::forward<T>(opt));
|
return get_or(tab[ky], opt);
|
||||||
}
|
}
|
||||||
template<typename T>
|
|
||||||
auto get_or(toml::value&& v, const toml::key& ky, T&& opt)
|
template<typename T, typename std::enable_if<
|
||||||
-> decltype(get_or(std::declval<value&&>(), std::forward<T>(opt)))
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T&& find_or(toml::value&& v, const toml::key& ky, T&& opt)
|
||||||
{
|
{
|
||||||
if(v.type() != toml::value_t::Table){return std::forward<T>(opt);}
|
if(!v.is_table()) {return opt;}
|
||||||
auto tab = toml::get<toml::table>(std::move(v));
|
auto tab = toml::get<toml::table>(std::move(v));
|
||||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
return ::toml::get_or(std::move(tab[ky]), std::forward<T>(opt));
|
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// std::string (return type can be a reference)
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string const& find_or(const toml::value& v, const toml::key& ky, const T& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
const auto& tab = toml::get<toml::table>(v);
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(tab.at(ky), opt);
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string& find_or(toml::value& v, const toml::key& ky, T& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
auto& tab = toml::get<toml::table>(v);
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(tab[ky], opt);
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string find_or(toml::value&& v, const toml::key& ky, T&& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
auto tab = toml::get<toml::table>(std::move(v));
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// string literal (deduced as std::string)
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_string_literal<typename std::remove_reference<T>::type>::value,
|
||||||
|
std::nullptr_t>::type = nullptr>
|
||||||
|
std::string find_or(const toml::value& v, const toml::key& ky, T&& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
const auto& tab = toml::get<toml::table>(v);
|
||||||
|
if(tab.count(ky) == 0) {return std::string(opt);}
|
||||||
|
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// others (require type conversion and return type cannot be lvalue reference)
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>,
|
||||||
|
detail::negation<std::is_same<T, std::string>>,
|
||||||
|
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T find_or(const toml::value& v, const toml::key& ky, T&& opt)
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
const auto& tab = toml::get<toml::table>(v);
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
// find_or(table, key, opt)
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// exact types (return type can be a reference)
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T const& find_or(const toml::table& tab, const toml::key& ky, const T& opt)
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(tab.at(ky), opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T& find_or(toml::table& tab, const toml::key& ky, T& opt)
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(tab[ky], opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T&& find_or(toml::table&& tab, const toml::key& ky, T&& opt)
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// std::string (return type can be a reference)
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string const& find_or(const toml::table& tab, const toml::key& ky, const T& opt)
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(tab.at(ky), opt);
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string& find_or(toml::table& tab, const toml::key& ky, T& opt)
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(tab[ky], opt);
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string find_or(toml::table&& tab, const toml::key& ky, T&& opt)
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// string literal (deduced as std::string)
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_string_literal<typename std::remove_reference<T>::type>::value,
|
||||||
|
std::nullptr_t>::type = nullptr>
|
||||||
|
std::string find_or(const toml::table& tab, const toml::key& ky, T&& opt)
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0) {return std::string(opt);}
|
||||||
|
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// others (require type conversion and return type cannot be lvalue reference)
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>,
|
||||||
|
detail::negation<std::is_same<T, std::string>>,
|
||||||
|
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T find_or(const toml::table& tab, const toml::key& ky, T&& opt)
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
20
toml/into.hpp
Normal file
20
toml/into.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright Toru Niina 2019.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_INTO_HPP
|
||||||
|
#define TOML11_INTO_HPP
|
||||||
|
#include "traits.hpp"
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct into;
|
||||||
|
// {
|
||||||
|
// static toml::value into_toml(const T& user_defined_type)
|
||||||
|
// {
|
||||||
|
// // User-defined conversions ...
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
} // toml
|
||||||
|
#endif // TOML11_INTO_HPP
|
||||||
@@ -124,9 +124,9 @@ using lex_escape_unicode_short = sequence<character<'u'>,
|
|||||||
using lex_escape_unicode_long = sequence<character<'U'>,
|
using lex_escape_unicode_long = sequence<character<'U'>,
|
||||||
repeat<lex_hex_dig, exactly<8>>>;
|
repeat<lex_hex_dig, exactly<8>>>;
|
||||||
using lex_escape_seq_char = either<character<'"'>, character<'\\'>,
|
using lex_escape_seq_char = either<character<'"'>, character<'\\'>,
|
||||||
character<'/'>, character<'b'>,
|
character<'b'>, character<'f'>,
|
||||||
character<'f'>, character<'n'>,
|
character<'n'>, character<'r'>,
|
||||||
character<'r'>, character<'t'>,
|
character<'t'>,
|
||||||
lex_escape_unicode_short,
|
lex_escape_unicode_short,
|
||||||
lex_escape_unicode_long
|
lex_escape_unicode_long
|
||||||
>;
|
>;
|
||||||
|
|||||||
91
toml/literal.hpp
Normal file
91
toml/literal.hpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
// Copyright Toru Niina 2019.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_LITERAL_HPP
|
||||||
|
#define TOML11_LITERAL_HPP
|
||||||
|
#include "parser.hpp"
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
inline namespace literals
|
||||||
|
{
|
||||||
|
inline namespace toml_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
inline ::toml::value operator""_toml(const char* str, std::size_t len)
|
||||||
|
{
|
||||||
|
::toml::detail::location<std::vector<char>>
|
||||||
|
loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
|
||||||
|
/* contents = */ std::vector<char>(str, str + len));
|
||||||
|
|
||||||
|
// if there are some comments or empty lines, skip them.
|
||||||
|
using skip_line = ::toml::detail::repeat<toml::detail::sequence<
|
||||||
|
::toml::detail::maybe<::toml::detail::lex_ws>,
|
||||||
|
::toml::detail::maybe<::toml::detail::lex_comment>,
|
||||||
|
::toml::detail::lex_newline
|
||||||
|
>, ::toml::detail::at_least<1>>;
|
||||||
|
skip_line::invoke(loc);
|
||||||
|
|
||||||
|
// if there are some whitespaces before a value, skip them.
|
||||||
|
using skip_ws = ::toml::detail::repeat<
|
||||||
|
::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
|
||||||
|
skip_ws::invoke(loc);
|
||||||
|
|
||||||
|
// to distinguish arrays and tables, first check it is a table or not.
|
||||||
|
//
|
||||||
|
// "[1,2,3]"_toml; // this is an array
|
||||||
|
// "[table]"_toml; // a table that has an empty table named "table" inside.
|
||||||
|
// "[[1,2,3]]"_toml; // this is an array of arrays
|
||||||
|
// "[[table]]"_toml; // this is a table that has an array of tables inside.
|
||||||
|
//
|
||||||
|
// "[[1]]"_toml; // this can be both... (currently it becomes a table)
|
||||||
|
// "1 = [{}]"_toml; // this is a table that has an array of table named 1.
|
||||||
|
// "[[1,]]"_toml; // this is an array of arrays.
|
||||||
|
// "[[1],]"_toml; // this also.
|
||||||
|
|
||||||
|
const auto the_front = loc.iter();
|
||||||
|
|
||||||
|
const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
|
||||||
|
loc.reset(the_front);
|
||||||
|
|
||||||
|
const bool is_aots_key = ::toml::detail::lex_array_table::invoke(loc);
|
||||||
|
loc.reset(the_front);
|
||||||
|
|
||||||
|
// If it is neither a table-key or a array-of-table-key, it may be a value.
|
||||||
|
if(!is_table_key && !is_aots_key)
|
||||||
|
{
|
||||||
|
if(auto data = ::toml::detail::parse_value(loc))
|
||||||
|
{
|
||||||
|
return data.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that still it can be a table, because the literal might be something
|
||||||
|
// like the following.
|
||||||
|
// ```cpp
|
||||||
|
// R"( // c++11 raw string literals
|
||||||
|
// key = "value"
|
||||||
|
// int = 42
|
||||||
|
// )"_toml;
|
||||||
|
// ```
|
||||||
|
// It is a valid toml file.
|
||||||
|
// It should be parsed as if we parse a file with this content.
|
||||||
|
|
||||||
|
if(auto data = ::toml::detail::parse_toml_file(loc))
|
||||||
|
{
|
||||||
|
loc.reset(loc.begin()); // rollback to the top of the literal
|
||||||
|
// skip needless characters for error message
|
||||||
|
skip_line::invoke(loc); // skip the first several needless lines
|
||||||
|
skip_ws::invoke(loc); // skip the first several needless whitespaces
|
||||||
|
return ::toml::value(std::move(data.unwrap()),
|
||||||
|
::toml::detail::region<std::vector<char>>(std::move(loc)));
|
||||||
|
}
|
||||||
|
else // none of them.
|
||||||
|
{
|
||||||
|
throw ::toml::syntax_error(data.unwrap_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // toml_literals
|
||||||
|
} // literals
|
||||||
|
} // toml
|
||||||
|
#endif//TOML11_LITERAL_HPP
|
||||||
836
toml/parser.hpp
836
toml/parser.hpp
File diff suppressed because it is too large
Load Diff
445
toml/region.hpp
445
toml/region.hpp
@@ -1,7 +1,7 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_REGION_H
|
#ifndef TOML11_REGION_HPP
|
||||||
#define TOML11_REGION_H
|
#define TOML11_REGION_HPP
|
||||||
#include "exception.hpp"
|
#include "exception.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -15,7 +15,7 @@ namespace toml
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
// helper function to avoid std::string(0, 'c')
|
// helper function to avoid std::string(0, 'c') or std::string(iter, iter)
|
||||||
template<typename Iterator>
|
template<typename Iterator>
|
||||||
std::string make_string(Iterator first, Iterator last)
|
std::string make_string(Iterator first, Iterator last)
|
||||||
{
|
{
|
||||||
@@ -28,47 +28,7 @@ inline std::string make_string(std::size_t len, char c)
|
|||||||
return std::string(len, c);
|
return std::string(len, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// location in a container, normally in a file content.
|
// region_base is a base class of location and region that are defined below.
|
||||||
// shared_ptr points the resource that the iter points.
|
|
||||||
// it can be used not only for resource handling, but also error message.
|
|
||||||
template<typename Container>
|
|
||||||
struct location
|
|
||||||
{
|
|
||||||
static_assert(std::is_same<char, typename Container::value_type>::value,"");
|
|
||||||
using const_iterator = typename Container::const_iterator;
|
|
||||||
using source_ptr = std::shared_ptr<const Container>;
|
|
||||||
|
|
||||||
location(std::string name, Container cont)
|
|
||||||
: source_(std::make_shared<Container>(std::move(cont))),
|
|
||||||
source_name_(std::move(name)), iter_(source_->cbegin())
|
|
||||||
{}
|
|
||||||
location(const location&) = default;
|
|
||||||
location(location&&) = default;
|
|
||||||
location& operator=(const location&) = default;
|
|
||||||
location& operator=(location&&) = default;
|
|
||||||
~location() = default;
|
|
||||||
|
|
||||||
const_iterator& iter() noexcept {return iter_;}
|
|
||||||
const_iterator iter() const noexcept {return iter_;}
|
|
||||||
|
|
||||||
const_iterator begin() const noexcept {return source_->cbegin();}
|
|
||||||
const_iterator end() const noexcept {return source_->cend();}
|
|
||||||
|
|
||||||
source_ptr const& source() const& noexcept {return source_;}
|
|
||||||
source_ptr&& source() && noexcept {return std::move(source_);}
|
|
||||||
|
|
||||||
std::string const& name() const noexcept {return source_name_;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
source_ptr source_;
|
|
||||||
std::string source_name_;
|
|
||||||
const_iterator iter_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// region in a container, normally in a file content.
|
|
||||||
// shared_ptr points the resource that the iter points.
|
|
||||||
// combinators returns this.
|
|
||||||
// it will be used to generate better error messages.
|
// it will be used to generate better error messages.
|
||||||
struct region_base
|
struct region_base
|
||||||
{
|
{
|
||||||
@@ -86,19 +46,156 @@ struct region_base
|
|||||||
virtual std::string line() const {return std::string("unknown line");}
|
virtual std::string line() const {return std::string("unknown line");}
|
||||||
virtual std::string line_num() const {return std::string("?");}
|
virtual std::string line_num() const {return std::string("?");}
|
||||||
|
|
||||||
|
// length of the region
|
||||||
virtual std::size_t before() const noexcept {return 0;}
|
|
||||||
virtual std::size_t size() const noexcept {return 0;}
|
virtual std::size_t size() const noexcept {return 0;}
|
||||||
|
// number of characters in the line before the region
|
||||||
|
virtual std::size_t before() const noexcept {return 0;}
|
||||||
|
// number of characters in the line after the region
|
||||||
virtual std::size_t after() const noexcept {return 0;}
|
virtual std::size_t after() const noexcept {return 0;}
|
||||||
|
|
||||||
|
virtual std::string comment_before() const {return "";} // just before
|
||||||
|
virtual std::string comment_inline() const {return "";} // in the same line
|
||||||
|
virtual std::string comment() const {return "";} // concatenate
|
||||||
|
// ```toml
|
||||||
|
// # comment_before
|
||||||
|
// key = "value" # comment_inline
|
||||||
|
// ```
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// location represents a position in a container, which contains a file content.
|
||||||
|
// it can be considered as a region that contains only one character.
|
||||||
|
//
|
||||||
|
// it contains pointer to the file content and iterator that points the current
|
||||||
|
// location.
|
||||||
|
template<typename Container>
|
||||||
|
struct location final : public region_base
|
||||||
|
{
|
||||||
|
using const_iterator = typename Container::const_iterator;
|
||||||
|
using source_ptr = std::shared_ptr<const Container>;
|
||||||
|
|
||||||
|
static_assert(std::is_same<char, typename Container::value_type>::value,"");
|
||||||
|
static_assert(std::is_same<std::random_access_iterator_tag,
|
||||||
|
typename std::iterator_traits<const_iterator>::iterator_category>::value,
|
||||||
|
"container should be randomly accessible");
|
||||||
|
|
||||||
|
location(std::string name, Container cont)
|
||||||
|
: source_(std::make_shared<Container>(std::move(cont))), line_number_(1),
|
||||||
|
source_name_(std::move(name)), iter_(source_->cbegin())
|
||||||
|
{}
|
||||||
|
location(const location&) = default;
|
||||||
|
location(location&&) = default;
|
||||||
|
location& operator=(const location&) = default;
|
||||||
|
location& operator=(location&&) = default;
|
||||||
|
~location() = default;
|
||||||
|
|
||||||
|
bool is_ok() const noexcept override {return static_cast<bool>(source_);}
|
||||||
|
|
||||||
|
// this const prohibits codes like `++(loc.iter())`.
|
||||||
|
const const_iterator iter() const noexcept {return iter_;}
|
||||||
|
|
||||||
|
const_iterator begin() const noexcept {return source_->cbegin();}
|
||||||
|
const_iterator end() const noexcept {return source_->cend();}
|
||||||
|
|
||||||
|
// XXX `location::line_num()` used to be implemented using `std::count` to
|
||||||
|
// count a number of '\n'. But with a long toml file (typically, 10k lines),
|
||||||
|
// it becomes intolerably slow because each time it generates error messages,
|
||||||
|
// it counts '\n' from thousands of characters. To workaround it, I decided
|
||||||
|
// to introduce `location::line_number_` member variable and synchronize it
|
||||||
|
// to the location changes the point to look. So an overload of `iter()`
|
||||||
|
// which returns mutable reference is removed and `advance()`, `retrace()`
|
||||||
|
// and `reset()` is added.
|
||||||
|
void advance(std::size_t n = 1) noexcept
|
||||||
|
{
|
||||||
|
this->line_number_ += std::count(this->iter_, this->iter_ + n, '\n');
|
||||||
|
this->iter_ += n;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void retrace(std::size_t n = 1) noexcept
|
||||||
|
{
|
||||||
|
this->line_number_ -= std::count(this->iter_ - n, this->iter_, '\n');
|
||||||
|
this->iter_ -= n;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void reset(const_iterator rollback) noexcept
|
||||||
|
{
|
||||||
|
// since c++11, std::distance works in both ways for random-access
|
||||||
|
// iterators and returns a negative value if `first > last`.
|
||||||
|
if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
|
||||||
|
{
|
||||||
|
this->line_number_ -= std::count(rollback, this->iter_, '\n');
|
||||||
|
}
|
||||||
|
else // iter < rollback [[unlikely]]
|
||||||
|
{
|
||||||
|
this->line_number_ += std::count(this->iter_, rollback, '\n');
|
||||||
|
}
|
||||||
|
this->iter_ = rollback;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string str() const override {return make_string(1, *this->iter());}
|
||||||
|
std::string name() const override {return source_name_;}
|
||||||
|
|
||||||
|
std::string line_num() const override
|
||||||
|
{
|
||||||
|
return std::to_string(this->line_number_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line() const override
|
||||||
|
{
|
||||||
|
return make_string(this->line_begin(), this->line_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator line_begin() const noexcept
|
||||||
|
{
|
||||||
|
using reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
return std::find(reverse_iterator(this->iter()),
|
||||||
|
reverse_iterator(this->begin()), '\n').base();
|
||||||
|
}
|
||||||
|
const_iterator line_end() const noexcept
|
||||||
|
{
|
||||||
|
return std::find(this->iter(), this->end(), '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// location is always points a character. so the size is 1.
|
||||||
|
std::size_t size() const noexcept override
|
||||||
|
{
|
||||||
|
return 1u;
|
||||||
|
}
|
||||||
|
std::size_t before() const noexcept override
|
||||||
|
{
|
||||||
|
return std::distance(this->line_begin(), this->iter());
|
||||||
|
}
|
||||||
|
std::size_t after() const noexcept override
|
||||||
|
{
|
||||||
|
return std::distance(this->iter(), this->line_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
source_ptr const& source() const& noexcept {return source_;}
|
||||||
|
source_ptr&& source() && noexcept {return std::move(source_);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
source_ptr source_;
|
||||||
|
std::size_t line_number_;
|
||||||
|
std::string source_name_;
|
||||||
|
const_iterator iter_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// region represents a range in a container, which contains a file content.
|
||||||
|
//
|
||||||
|
// it contains pointer to the file content and iterator that points the first
|
||||||
|
// and last location.
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
struct region final : public region_base
|
struct region final : public region_base
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Container::value_type>::value,"");
|
|
||||||
using const_iterator = typename Container::const_iterator;
|
using const_iterator = typename Container::const_iterator;
|
||||||
using source_ptr = std::shared_ptr<const Container>;
|
using source_ptr = std::shared_ptr<const Container>;
|
||||||
|
|
||||||
|
static_assert(std::is_same<char, typename Container::value_type>::value,"");
|
||||||
|
static_assert(std::is_same<std::random_access_iterator_tag,
|
||||||
|
typename std::iterator_traits<const_iterator>::iterator_category>::value,
|
||||||
|
"container should be randomly accessible");
|
||||||
|
|
||||||
// delete default constructor. source_ never be null.
|
// delete default constructor. source_ never be null.
|
||||||
region() = delete;
|
region() = delete;
|
||||||
|
|
||||||
@@ -191,6 +288,92 @@ struct region final : public region_base
|
|||||||
|
|
||||||
std::string name() const override {return source_name_;}
|
std::string name() const override {return source_name_;}
|
||||||
|
|
||||||
|
std::string comment_before() const override
|
||||||
|
{
|
||||||
|
auto iter = this->line_begin(); // points the first element
|
||||||
|
std::vector<std::pair<decltype(iter), decltype(iter)>> comments;
|
||||||
|
while(iter != this->begin())
|
||||||
|
{
|
||||||
|
iter = std::prev(iter);
|
||||||
|
using rev_iter = std::reverse_iterator<decltype(iter)>;
|
||||||
|
auto line_before = std::find(rev_iter(iter), rev_iter(this->begin()),
|
||||||
|
'\n').base();
|
||||||
|
// range [line_before, iter) represents the previous line
|
||||||
|
|
||||||
|
auto comment_found = std::find(line_before, iter, '#');
|
||||||
|
if(iter != comment_found && std::all_of(line_before, comment_found,
|
||||||
|
[](const char c) noexcept -> bool {
|
||||||
|
return c == ' ' || c == '\t';
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
// the line before this range contains only a comment.
|
||||||
|
comments.push_back(std::make_pair(comment_found, iter));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iter = line_before;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string com;
|
||||||
|
for(auto i = comments.crbegin(), e = comments.crend(); i!=e; ++i)
|
||||||
|
{
|
||||||
|
if(i != comments.crbegin()) {com += '\n';}
|
||||||
|
com += std::string(i->first, i->second);
|
||||||
|
}
|
||||||
|
return com;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string comment_inline() const override
|
||||||
|
{
|
||||||
|
if(this->contain_newline())
|
||||||
|
{
|
||||||
|
std::string com;
|
||||||
|
// check both the first and the last line.
|
||||||
|
const auto first_line_end =
|
||||||
|
std::find(this->line_begin(), this->last(), '\n');
|
||||||
|
const auto first_comment_found =
|
||||||
|
std::find(this->line_begin(), first_line_end, '#');
|
||||||
|
|
||||||
|
if(first_comment_found != first_line_end)
|
||||||
|
{
|
||||||
|
com += std::string(first_comment_found, first_line_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto last_comment_found =
|
||||||
|
std::find(this->last(), this->line_end(), '#');
|
||||||
|
if(last_comment_found != this->line_end())
|
||||||
|
{
|
||||||
|
if(!com.empty()){com += '\n';}
|
||||||
|
com += std::string(last_comment_found, this->line_end());
|
||||||
|
}
|
||||||
|
return com;
|
||||||
|
}
|
||||||
|
const auto comment_found =
|
||||||
|
std::find(this->line_begin(), this->line_end(), '#');
|
||||||
|
return std::string(comment_found, this->line_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string comment() const override
|
||||||
|
{
|
||||||
|
std::string com_bef = this->comment_before();
|
||||||
|
std::string com_inl = this->comment_inline();
|
||||||
|
if(!com_bef.empty() && !com_inl.empty())
|
||||||
|
{
|
||||||
|
com_bef += '\n';
|
||||||
|
return com_bef + com_inl;
|
||||||
|
}
|
||||||
|
else if(com_bef.empty())
|
||||||
|
{
|
||||||
|
return com_inl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return com_bef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
source_ptr source_;
|
source_ptr source_;
|
||||||
@@ -200,96 +383,68 @@ 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 region_base& reg, const std::string& comment_for_underline,
|
std::vector<std::pair<region_base const*, std::string>> reg_com,
|
||||||
std::vector<std::string> helps = {})
|
std::vector<std::string> helps = {})
|
||||||
{
|
{
|
||||||
|
assert(!reg_com.empty());
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
const auto newline = "\r\n";
|
const auto newline = "\r\n";
|
||||||
#else
|
#else
|
||||||
const char newline = '\n';
|
const char newline = '\n';
|
||||||
#endif
|
#endif
|
||||||
const auto line = reg.line();
|
|
||||||
const auto line_number = reg.line_num();
|
|
||||||
|
|
||||||
std::string retval;
|
const auto line_num_width = std::max_element(reg_com.begin(), reg_com.end(),
|
||||||
retval += message;
|
[](std::pair<region_base const*, std::string> const& lhs,
|
||||||
retval += newline;
|
std::pair<region_base const*, std::string> const& rhs)
|
||||||
retval += " --> ";
|
|
||||||
retval += reg.name();
|
|
||||||
retval += newline;
|
|
||||||
retval += ' ';
|
|
||||||
retval += line_number;
|
|
||||||
retval += " | ";
|
|
||||||
retval += line;
|
|
||||||
retval += newline;
|
|
||||||
retval += make_string(line_number.size() + 1, ' ');
|
|
||||||
retval += " | ";
|
|
||||||
retval += make_string(reg.before(), ' ');
|
|
||||||
retval += make_string(reg.size(), '~');
|
|
||||||
retval += ' ';
|
|
||||||
retval += comment_for_underline;
|
|
||||||
if(helps.size() != 0)
|
|
||||||
{
|
{
|
||||||
retval += newline;
|
return lhs.first->line_num().size() < rhs.first->line_num().size();
|
||||||
retval += make_string(line_number.size() + 1, ' ');
|
|
||||||
retval += " | ";
|
|
||||||
for(const auto help : helps)
|
|
||||||
{
|
|
||||||
retval += newline;
|
|
||||||
retval += "Hint: ";
|
|
||||||
retval += help;
|
|
||||||
}
|
}
|
||||||
}
|
)->first->line_num().size();
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
// to show a better error message.
|
|
||||||
inline std::string format_underline(const std::string& message,
|
|
||||||
const region_base& reg1, const std::string& comment_for_underline1,
|
|
||||||
const region_base& reg2, const std::string& comment_for_underline2,
|
|
||||||
std::vector<std::string> helps = {})
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
const auto newline = "\r\n";
|
|
||||||
#else
|
|
||||||
const char newline = '\n';
|
|
||||||
#endif
|
|
||||||
const auto line1 = reg1.line();
|
|
||||||
const auto line_number1 = reg1.line_num();
|
|
||||||
const auto line2 = reg2.line();
|
|
||||||
const auto line_number2 = reg2.line_num();
|
|
||||||
const auto line_num_width =
|
|
||||||
std::max(line_number1.size(), line_number2.size());
|
|
||||||
|
|
||||||
std::ostringstream retval;
|
std::ostringstream retval;
|
||||||
retval << message << newline;
|
retval << message << newline;
|
||||||
retval << " --> " << reg1.name() << newline;
|
|
||||||
// ---------------------------------------
|
for(std::size_t i=0; i<reg_com.size(); ++i)
|
||||||
retval << ' ' << std::setw(line_num_width) << line_number1;
|
|
||||||
retval << " | " << line1 << newline;
|
|
||||||
retval << make_string(line_num_width + 1, ' ');
|
|
||||||
retval << " | ";
|
|
||||||
retval << make_string(reg1.before(), ' ');
|
|
||||||
retval << make_string(reg1.size(), '~');
|
|
||||||
retval << ' ';
|
|
||||||
retval << comment_for_underline1 << newline;
|
|
||||||
// ---------------------------------------
|
|
||||||
if(reg2.name() != reg1.name())
|
|
||||||
{
|
{
|
||||||
retval << " --> " << reg2.name() << newline;
|
if(i!=0 && reg_com.at(i-1).first->name() == reg_com.at(i).first->name())
|
||||||
|
{
|
||||||
|
retval << newline << " ..." << newline;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
retval << " ..." << newline;
|
if(i != 0) {retval << newline;}
|
||||||
|
retval << " --> " << reg_com.at(i).first->name() << newline;
|
||||||
}
|
}
|
||||||
retval << ' ' << std::setw(line_num_width) << line_number2;
|
|
||||||
retval << " | " << line2 << newline;
|
const region_base* const reg = reg_com.at(i).first;
|
||||||
|
const std::string& comment = reg_com.at(i).second;
|
||||||
|
|
||||||
|
|
||||||
|
retval << ' ' << std::setw(line_num_width) << reg->line_num();
|
||||||
|
retval << " | " << reg->line() << newline;
|
||||||
retval << make_string(line_num_width + 1, ' ');
|
retval << make_string(line_num_width + 1, ' ');
|
||||||
retval << " | ";
|
retval << " | " << make_string(reg->before(), ' ');
|
||||||
retval << make_string(reg2.before(), ' ');
|
|
||||||
retval << make_string(reg2.size(), '~');
|
if(reg->size() == 1)
|
||||||
|
{
|
||||||
|
// invalid
|
||||||
|
// ^------
|
||||||
|
retval << '^';
|
||||||
|
retval << make_string(reg->after(), '-');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// invalid
|
||||||
|
// ~~~~~~~
|
||||||
|
const auto underline_len = std::min(reg->size(), reg->line().size());
|
||||||
|
retval << make_string(underline_len, '~');
|
||||||
|
}
|
||||||
|
|
||||||
retval << ' ';
|
retval << ' ';
|
||||||
retval << comment_for_underline2;
|
retval << comment;
|
||||||
|
}
|
||||||
|
|
||||||
if(helps.size() != 0)
|
if(helps.size() != 0)
|
||||||
{
|
{
|
||||||
retval << newline;
|
retval << newline;
|
||||||
@@ -305,62 +460,6 @@ inline std::string format_underline(const std::string& message,
|
|||||||
return retval.str();
|
return retval.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// to show a better error message.
|
|
||||||
template<typename Container>
|
|
||||||
std::string
|
|
||||||
format_underline(const std::string& message, const location<Container>& loc,
|
|
||||||
const std::string& comment_for_underline,
|
|
||||||
std::vector<std::string> helps = {})
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
const auto newline = "\r\n";
|
|
||||||
#else
|
|
||||||
const char newline = '\n';
|
|
||||||
#endif
|
|
||||||
using const_iterator = typename location<Container>::const_iterator;
|
|
||||||
using reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
||||||
const auto line_begin = std::find(reverse_iterator(loc.iter()),
|
|
||||||
reverse_iterator(loc.begin()),
|
|
||||||
'\n').base();
|
|
||||||
const auto line_end = std::find(loc.iter(), loc.end(), '\n');
|
|
||||||
|
|
||||||
const auto line_number = std::to_string(
|
|
||||||
1 + std::count(loc.begin(), loc.iter(), '\n'));
|
|
||||||
|
|
||||||
std::string retval;
|
|
||||||
retval += message;
|
|
||||||
retval += newline;
|
|
||||||
retval += " --> ";
|
|
||||||
retval += loc.name();
|
|
||||||
retval += newline;
|
|
||||||
retval += ' ';
|
|
||||||
retval += line_number;
|
|
||||||
retval += " | ";
|
|
||||||
retval += make_string(line_begin, line_end);
|
|
||||||
retval += newline;
|
|
||||||
retval += make_string(line_number.size() + 1, ' ');
|
|
||||||
retval += " | ";
|
|
||||||
retval += make_string(std::distance(line_begin, loc.iter()),' ');
|
|
||||||
retval += '^';
|
|
||||||
retval += make_string(std::distance(loc.iter(), line_end), '-');
|
|
||||||
retval += ' ';
|
|
||||||
retval += comment_for_underline;
|
|
||||||
if(helps.size() != 0)
|
|
||||||
{
|
|
||||||
retval += newline;
|
|
||||||
retval += make_string(line_number.size() + 1, ' ');
|
|
||||||
retval += " | ";
|
|
||||||
for(const auto help : helps)
|
|
||||||
{
|
|
||||||
retval += newline;
|
|
||||||
retval += "Hint: ";
|
|
||||||
retval += help;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // toml
|
} // toml
|
||||||
#endif// TOML11_REGION_H
|
#endif// TOML11_REGION_H
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_RESULT_H
|
#ifndef TOML11_RESULT_HPP
|
||||||
#define TOML11_RESULT_H
|
#define TOML11_RESULT_HPP
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -113,21 +113,25 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
|
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
result(const failure_type& f): is_ok_(false)
|
result(const failure_type& f): is_ok_(false)
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
result(success_type&& s): is_ok_(true)
|
result(success_type&& s): is_ok_(true)
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
result(failure_type&& f): is_ok_(false)
|
result(failure_type&& f): is_ok_(false)
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
@@ -135,24 +139,28 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
|
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
result(const failure<U>& f): is_ok_(false)
|
result(const failure<U>& f): is_ok_(false)
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
result(success<U>&& s): is_ok_(true)
|
result(success<U>&& s): is_ok_(true)
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
result(failure<U>&& f): is_ok_(false)
|
result(failure<U>&& f): is_ok_(false)
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
result& operator=(const success_type& s)
|
result& operator=(const success_type& s)
|
||||||
@@ -161,6 +169,7 @@ struct result
|
|||||||
this->is_ok_ = true;
|
this->is_ok_ = true;
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
|
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
result& operator=(const failure_type& f)
|
result& operator=(const failure_type& f)
|
||||||
@@ -169,6 +178,7 @@ struct result
|
|||||||
this->is_ok_ = false;
|
this->is_ok_ = false;
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
result& operator=(success_type&& s)
|
result& operator=(success_type&& s)
|
||||||
@@ -177,6 +187,7 @@ struct result
|
|||||||
this->is_ok_ = true;
|
this->is_ok_ = true;
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
result& operator=(failure_type&& f)
|
result& operator=(failure_type&& f)
|
||||||
@@ -185,6 +196,7 @@ struct result
|
|||||||
this->is_ok_ = false;
|
this->is_ok_ = false;
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,6 +207,7 @@ struct result
|
|||||||
this->is_ok_ = true;
|
this->is_ok_ = true;
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
|
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
@@ -204,6 +217,7 @@ struct result
|
|||||||
this->is_ok_ = false;
|
this->is_ok_ = false;
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
@@ -213,6 +227,7 @@ struct result
|
|||||||
this->is_ok_ = true;
|
this->is_ok_ = true;
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename U>
|
template<typename U>
|
||||||
@@ -222,6 +237,7 @@ struct result
|
|||||||
this->is_ok_ = false;
|
this->is_ok_ = false;
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,11 +249,13 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result(result&& other): is_ok_(other.is_ok())
|
result(result&& other): is_ok_(other.is_ok())
|
||||||
@@ -246,11 +264,13 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,11 +281,13 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename U, typename F>
|
template<typename U, typename F>
|
||||||
@@ -275,11 +297,13 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,11 +314,13 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
is_ok_ = other.is_ok();
|
is_ok_ = other.is_ok();
|
||||||
return *this;
|
return *this;
|
||||||
@@ -306,11 +332,13 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
is_ok_ = other.is_ok();
|
is_ok_ = other.is_ok();
|
||||||
return *this;
|
return *this;
|
||||||
@@ -324,11 +352,13 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
is_ok_ = other.is_ok();
|
is_ok_ = other.is_ok();
|
||||||
return *this;
|
return *this;
|
||||||
@@ -341,11 +371,13 @@ struct result
|
|||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||||
assert(tmp == std::addressof(this->succ));
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||||
assert(tmp == std::addressof(this->fail));
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
is_ok_ = other.is_ok();
|
is_ok_ = other.is_ok();
|
||||||
return *this;
|
return *this;
|
||||||
@@ -660,5 +692,26 @@ void swap(result<T, E>& lhs, result<T, E>& rhs)
|
|||||||
// return lhs.is_ok() ? lhs : rhs;
|
// return lhs.is_ok() ? lhs : rhs;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// re-use result<T, E> as a optional<T> with none_t
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct none_t {};
|
||||||
|
inline bool operator==(const none_t&, const none_t&) noexcept {return true;}
|
||||||
|
inline bool operator!=(const none_t&, const none_t&) noexcept {return false;}
|
||||||
|
inline bool operator< (const none_t&, const none_t&) noexcept {return false;}
|
||||||
|
inline bool operator<=(const none_t&, const none_t&) noexcept {return true;}
|
||||||
|
inline bool operator> (const none_t&, const none_t&) noexcept {return false;}
|
||||||
|
inline bool operator>=(const none_t&, const none_t&) noexcept {return true;}
|
||||||
|
template<typename charT, typename traitsT>
|
||||||
|
std::basic_ostream<charT, traitsT>&
|
||||||
|
operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&)
|
||||||
|
{
|
||||||
|
os << "none";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};}
|
||||||
|
} // detail
|
||||||
} // toml11
|
} // toml11
|
||||||
#endif// TOML11_RESULT_H
|
#endif// TOML11_RESULT_H
|
||||||
|
|||||||
526
toml/serializer.hpp
Normal file
526
toml/serializer.hpp
Normal file
@@ -0,0 +1,526 @@
|
|||||||
|
// Copyright Toru Niina 2019.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_SERIALIZER_HPP
|
||||||
|
#define TOML11_SERIALIZER_HPP
|
||||||
|
#include "value.hpp"
|
||||||
|
#include "lexer.hpp"
|
||||||
|
#include <limits>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
|
||||||
|
struct serializer
|
||||||
|
{
|
||||||
|
serializer(const std::size_t w = 80,
|
||||||
|
const int float_prec = std::numeric_limits<toml::floating>::max_digits10,
|
||||||
|
const bool can_be_inlined = false,
|
||||||
|
std::vector<toml::key> ks = {})
|
||||||
|
: can_be_inlined_(can_be_inlined), float_prec_(float_prec), width_(w),
|
||||||
|
keys_(std::move(ks))
|
||||||
|
{}
|
||||||
|
~serializer() = default;
|
||||||
|
|
||||||
|
std::string operator()(const toml::boolean& b) const
|
||||||
|
{
|
||||||
|
return b ? "true" : "false";
|
||||||
|
}
|
||||||
|
std::string operator()(const integer i) const
|
||||||
|
{
|
||||||
|
return std::to_string(i);
|
||||||
|
}
|
||||||
|
std::string operator()(const toml::floating f) const
|
||||||
|
{
|
||||||
|
const auto fmt = "%.*g";
|
||||||
|
const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f);
|
||||||
|
std::vector<char> buf(bsz + 1, '\0'); // +1 for null character(\0)
|
||||||
|
std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f);
|
||||||
|
|
||||||
|
std::string token(buf.begin(), std::prev(buf.end()));
|
||||||
|
if(token.back() == '.') // 1. => 1.0
|
||||||
|
{
|
||||||
|
token += '0';
|
||||||
|
}
|
||||||
|
const auto e = std::find_if(token.cbegin(), token.cend(),
|
||||||
|
[](const char c) -> bool {
|
||||||
|
return c == 'E' || c == 'e';
|
||||||
|
});
|
||||||
|
if(e == token.cend())
|
||||||
|
{
|
||||||
|
return token; // there is no exponent part. just return it.
|
||||||
|
}
|
||||||
|
|
||||||
|
// zero-prefix in an exponent is not allowed in TOML.
|
||||||
|
// remove it if it exists.
|
||||||
|
bool sign_exists = false;
|
||||||
|
std::size_t zero_prefix = 0;
|
||||||
|
for(auto iter = std::next(e), iend = token.cend(); iter != iend; ++iter)
|
||||||
|
{
|
||||||
|
if(*iter == '+' || *iter == '-'){sign_exists = true; continue;}
|
||||||
|
if(*iter == '0'){zero_prefix += 1;}
|
||||||
|
else {break;}
|
||||||
|
}
|
||||||
|
if(zero_prefix != 0)
|
||||||
|
{
|
||||||
|
const auto offset = std::distance(token.cbegin(), e) +
|
||||||
|
(sign_exists ? 2 : 1);
|
||||||
|
token.erase(offset, zero_prefix);
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
std::string operator()(const string& s) const
|
||||||
|
{
|
||||||
|
if(s.kind == string_t::basic)
|
||||||
|
{
|
||||||
|
if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
|
||||||
|
{
|
||||||
|
// if linefeed is contained, make it multiline-string.
|
||||||
|
const std::string open("\"\"\"\n");
|
||||||
|
const std::string close("\\\n\"\"\"");
|
||||||
|
return open + this->escape_ml_basic_string(s.str) + close;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no linefeed. try to make it oneline-string.
|
||||||
|
std::string oneline = this->escape_basic_string(s.str);
|
||||||
|
if(oneline.size() + 2 < width_ || width_ < 2)
|
||||||
|
{
|
||||||
|
const std::string quote("\"");
|
||||||
|
return quote + oneline + quote;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the line is too long compared to the specified width.
|
||||||
|
// split it into multiple lines.
|
||||||
|
std::string token("\"\"\"\n");
|
||||||
|
while(!oneline.empty())
|
||||||
|
{
|
||||||
|
if(oneline.size() < width_)
|
||||||
|
{
|
||||||
|
token += oneline;
|
||||||
|
oneline.clear();
|
||||||
|
}
|
||||||
|
else if(oneline.at(width_-2) == '\\')
|
||||||
|
{
|
||||||
|
token += oneline.substr(0, width_-2);
|
||||||
|
token += "\\\n";
|
||||||
|
oneline.erase(0, width_-2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
token += oneline.substr(0, width_-1);
|
||||||
|
token += "\\\n";
|
||||||
|
oneline.erase(0, width_-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return token + std::string("\\\n\"\"\"");
|
||||||
|
}
|
||||||
|
else // the string `s` is literal-string.
|
||||||
|
{
|
||||||
|
if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
|
||||||
|
std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
|
||||||
|
{
|
||||||
|
const std::string open("'''\n");
|
||||||
|
const std::string close("'''");
|
||||||
|
return open + s.str + close;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::string quote("'");
|
||||||
|
return quote + s.str + quote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const local_date& d) const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << d;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
std::string operator()(const local_time& t) const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << t;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
std::string operator()(const local_datetime& dt) const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << dt;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
std::string operator()(const offset_datetime& odt) const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << odt;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const array& v) const
|
||||||
|
{
|
||||||
|
if(!v.empty() && v.front().is_table())// v is an array of tables
|
||||||
|
{
|
||||||
|
// if it's not inlined, we need to add `[[table.key]]`.
|
||||||
|
// but if it can be inlined, we need `table.key = [...]`.
|
||||||
|
if(this->can_be_inlined_)
|
||||||
|
{
|
||||||
|
std::string token;
|
||||||
|
if(!keys_.empty())
|
||||||
|
{
|
||||||
|
token += this->serialize_key(keys_.back());
|
||||||
|
token += " = ";
|
||||||
|
}
|
||||||
|
bool width_exceeds = false;
|
||||||
|
token += "[\n";
|
||||||
|
for(const auto& item : v)
|
||||||
|
{
|
||||||
|
const auto t =
|
||||||
|
this->make_inline_table(item.cast<value_t::Table>());
|
||||||
|
|
||||||
|
if(t.size() + 1 > width_ || // +1 for the last comma {...},
|
||||||
|
std::find(t.cbegin(), t.cend(), '\n') != t.cend())
|
||||||
|
{
|
||||||
|
width_exceeds = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
token += t;
|
||||||
|
token += ",\n";
|
||||||
|
}
|
||||||
|
if(!width_exceeds)
|
||||||
|
{
|
||||||
|
token += "]\n";
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
// if width_exceeds, serialize it as [[array.of.tables]].
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string token;
|
||||||
|
for(const auto& item : v)
|
||||||
|
{
|
||||||
|
token += "[[";
|
||||||
|
token += this->serialize_dotted_key(keys_);
|
||||||
|
token += "]]\n";
|
||||||
|
token += this->make_multiline_table(item.cast<value_t::Table>());
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
if(v.empty())
|
||||||
|
{
|
||||||
|
return std::string("[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// not an array of tables. normal array. first, try to make it inline.
|
||||||
|
{
|
||||||
|
const auto inl = this->make_inline_array(v);
|
||||||
|
if(inl.size() < this->width_ &&
|
||||||
|
std::find(inl.cbegin(), inl.cend(), '\n') == inl.cend())
|
||||||
|
{
|
||||||
|
return inl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the length exceeds this->width_, print multiline array
|
||||||
|
std::string token;
|
||||||
|
std::string current_line;
|
||||||
|
token += "[\n";
|
||||||
|
for(const auto& item : v)
|
||||||
|
{
|
||||||
|
auto next_elem = toml::visit(*this, item);
|
||||||
|
// newline between array-value and comma is not allowed
|
||||||
|
if(next_elem.back() == '\n'){next_elem.pop_back();}
|
||||||
|
|
||||||
|
if(current_line.size() + next_elem.size() + 1 < this->width_)
|
||||||
|
{
|
||||||
|
current_line += next_elem;
|
||||||
|
current_line += ',';
|
||||||
|
}
|
||||||
|
else if(current_line.empty())
|
||||||
|
{
|
||||||
|
// the next elem cannot be within the width.
|
||||||
|
token += next_elem;
|
||||||
|
token += ",\n";
|
||||||
|
// keep current line empty
|
||||||
|
}
|
||||||
|
else // current_line has some tokens and it exceeds width
|
||||||
|
{
|
||||||
|
assert(current_line.back() == ',');
|
||||||
|
token += current_line;
|
||||||
|
token += '\n';
|
||||||
|
current_line = next_elem;
|
||||||
|
current_line += ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!current_line.empty())
|
||||||
|
{
|
||||||
|
if(current_line.back() != '\n') {current_line += '\n';}
|
||||||
|
token += current_line;
|
||||||
|
}
|
||||||
|
token += "]\n";
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const table& v) const
|
||||||
|
{
|
||||||
|
if(this->can_be_inlined_)
|
||||||
|
{
|
||||||
|
std::string token;
|
||||||
|
if(!this->keys_.empty())
|
||||||
|
{
|
||||||
|
token += this->serialize_key(this->keys_.back());
|
||||||
|
token += " = ";
|
||||||
|
}
|
||||||
|
token += this->make_inline_table(v);
|
||||||
|
if(token.size() < this->width_)
|
||||||
|
{
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string token;
|
||||||
|
if(!keys_.empty())
|
||||||
|
{
|
||||||
|
token += '[';
|
||||||
|
token += this->serialize_dotted_key(keys_);
|
||||||
|
token += "]\n";
|
||||||
|
}
|
||||||
|
token += this->make_multiline_table(v);
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::string serialize_key(const toml::key& key) const
|
||||||
|
{
|
||||||
|
detail::location<toml::key> loc(key, key);
|
||||||
|
detail::lex_unquoted_key::invoke(loc);
|
||||||
|
if(loc.iter() == loc.end())
|
||||||
|
{
|
||||||
|
return key; // all the tokens are consumed. the key is unquoted-key.
|
||||||
|
}
|
||||||
|
std::string token("\"");
|
||||||
|
token += this->escape_basic_string(key);
|
||||||
|
token += "\"";
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string serialize_dotted_key(const std::vector<toml::key>& keys) const
|
||||||
|
{
|
||||||
|
std::string token;
|
||||||
|
if(keys.empty()){return token;}
|
||||||
|
|
||||||
|
for(const auto& k : keys)
|
||||||
|
{
|
||||||
|
token += this->serialize_key(k);
|
||||||
|
token += '.';
|
||||||
|
}
|
||||||
|
token.erase(token.size() - 1, 1); // remove trailing `.`
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string escape_basic_string(const std::string& s) const
|
||||||
|
{
|
||||||
|
//XXX assuming `s` is a valid utf-8 sequence.
|
||||||
|
std::string retval;
|
||||||
|
for(const char c : s)
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '\\': {retval += "\\\\"; break;}
|
||||||
|
case '\"': {retval += "\\\""; break;}
|
||||||
|
case '\b': {retval += "\\b"; break;}
|
||||||
|
case '\t': {retval += "\\t"; break;}
|
||||||
|
case '\f': {retval += "\\f"; break;}
|
||||||
|
case '\n': {retval += "\\n"; break;}
|
||||||
|
case '\r': {retval += "\\r"; break;}
|
||||||
|
default : {retval += c; break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string escape_ml_basic_string(const std::string& s) const
|
||||||
|
{
|
||||||
|
std::string retval;
|
||||||
|
for(auto i=s.cbegin(), e=s.cend(); i!=e; ++i)
|
||||||
|
{
|
||||||
|
switch(*i)
|
||||||
|
{
|
||||||
|
case '\\': {retval += "\\\\"; break;}
|
||||||
|
case '\"': {retval += "\\\""; break;}
|
||||||
|
case '\b': {retval += "\\b"; break;}
|
||||||
|
case '\t': {retval += "\\t"; break;}
|
||||||
|
case '\f': {retval += "\\f"; break;}
|
||||||
|
case '\n': {retval += "\n"; break;}
|
||||||
|
case '\r':
|
||||||
|
{
|
||||||
|
if(std::next(i) != e && *std::next(i) == '\n')
|
||||||
|
{
|
||||||
|
retval += "\r\n";
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retval += "\\r";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {retval += *i; break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string make_inline_array(const array& v) const
|
||||||
|
{
|
||||||
|
std::string token;
|
||||||
|
token += '[';
|
||||||
|
bool is_first = true;
|
||||||
|
for(const auto& item : v)
|
||||||
|
{
|
||||||
|
if(is_first) {is_first = false;} else {token += ',';}
|
||||||
|
token += visit(serializer(std::numeric_limits<std::size_t>::max(),
|
||||||
|
this->float_prec_, true), item);
|
||||||
|
}
|
||||||
|
token += ']';
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string make_inline_table(const table& v) const
|
||||||
|
{
|
||||||
|
assert(this->can_be_inlined_);
|
||||||
|
std::string token;
|
||||||
|
token += '{';
|
||||||
|
bool is_first = true;
|
||||||
|
for(const auto& kv : v)
|
||||||
|
{
|
||||||
|
// in inline tables, trailing comma is not allowed (toml-lang #569).
|
||||||
|
if(is_first) {is_first = false;} else {token += ',';}
|
||||||
|
token += this->serialize_key(kv.first);
|
||||||
|
token += '=';
|
||||||
|
token += visit(serializer(std::numeric_limits<std::size_t>::max(),
|
||||||
|
this->float_prec_, true), kv.second);
|
||||||
|
}
|
||||||
|
token += '}';
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string make_multiline_table(const table& v) const
|
||||||
|
{
|
||||||
|
std::string token;
|
||||||
|
|
||||||
|
// print non-table stuff first. because after printing [foo.bar], the
|
||||||
|
// remaining non-table values will be assigned into [foo.bar], not [foo]
|
||||||
|
for(const auto kv : v)
|
||||||
|
{
|
||||||
|
if(kv.second.is_table() || is_array_of_tables(kv.second))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto key_and_sep = this->serialize_key(kv.first) + " = ";
|
||||||
|
const auto residual_width = (this->width_ > key_and_sep.size()) ?
|
||||||
|
this->width_ - key_and_sep.size() : 0;
|
||||||
|
token += key_and_sep;
|
||||||
|
token += visit(serializer(residual_width, this->float_prec_, true),
|
||||||
|
kv.second);
|
||||||
|
if(token.back() != '\n')
|
||||||
|
{
|
||||||
|
token += '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// normal tables / array of tables
|
||||||
|
|
||||||
|
// after multiline table appeared, the other tables cannot be inline
|
||||||
|
// because the table would be assigned into the table.
|
||||||
|
// [foo]
|
||||||
|
// ...
|
||||||
|
// bar = {...} # <- bar will be a member of [foo].
|
||||||
|
bool multiline_table_printed = false;
|
||||||
|
for(const auto& kv : v)
|
||||||
|
{
|
||||||
|
if(!kv.second.is_table() && !is_array_of_tables(kv.second))
|
||||||
|
{
|
||||||
|
continue; // other stuff are already serialized. skip them.
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<toml::key> ks(this->keys_);
|
||||||
|
ks.push_back(kv.first);
|
||||||
|
|
||||||
|
auto tmp = visit(serializer(
|
||||||
|
this->width_, this->float_prec_, !multiline_table_printed, ks),
|
||||||
|
kv.second);
|
||||||
|
|
||||||
|
if((!multiline_table_printed) &&
|
||||||
|
std::find(tmp.cbegin(), tmp.cend(), '\n') != tmp.cend())
|
||||||
|
{
|
||||||
|
multiline_table_printed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// still inline tables only.
|
||||||
|
tmp += '\n';
|
||||||
|
}
|
||||||
|
token += tmp;
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_array_of_tables(const value& v) const
|
||||||
|
{
|
||||||
|
if(!v.is_array()) {return false;}
|
||||||
|
const auto& a = v.as_array();
|
||||||
|
return !a.empty() && a.front().is_table();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool can_be_inlined_;
|
||||||
|
int float_prec_;
|
||||||
|
std::size_t width_;
|
||||||
|
std::vector<toml::key> keys_;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::string
|
||||||
|
format(const value& v, std::size_t w = 80,
|
||||||
|
int fprec = std::numeric_limits<toml::floating>::max_digits10,
|
||||||
|
bool force_inline = false)
|
||||||
|
{
|
||||||
|
// if value is a table, it is considered to be a root object.
|
||||||
|
// the root object can't be an inline table. so pass false. otherwise, true.
|
||||||
|
return visit(serializer(w, fprec, (!v.is_table()) || force_inline), v);
|
||||||
|
}
|
||||||
|
inline std::string
|
||||||
|
format(const table& t, std::size_t w = 80,
|
||||||
|
int fprec = std::numeric_limits<toml::floating>::max_digits10,
|
||||||
|
bool force_inline = false)
|
||||||
|
{
|
||||||
|
return serializer(w, fprec, force_inline)(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, const value& v)
|
||||||
|
{
|
||||||
|
// get status of std::setw().
|
||||||
|
const std::size_t w = os.width();
|
||||||
|
const int fprec = os.precision();
|
||||||
|
os.width(0);
|
||||||
|
// the root object can't be an inline table. so pass `false`.
|
||||||
|
os << visit(serializer(w, fprec, false), v);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, const table& v)
|
||||||
|
{
|
||||||
|
// get status of std::setw().
|
||||||
|
const std::size_t w = os.width();
|
||||||
|
const int fprec = os.precision();
|
||||||
|
os.width(0);
|
||||||
|
// the root object can't be an inline table. so pass `false`.
|
||||||
|
os << serializer(w, fprec, false)(v);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // toml
|
||||||
|
#endif// TOML11_SERIALIZER_HPP
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_STRING_H
|
#ifndef TOML11_STRING_HPP
|
||||||
#define TOML11_STRING_H
|
#define TOML11_STRING_HPP
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#if __has_include(<string_view>)
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
@@ -40,6 +45,17 @@ 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);}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
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& operator=(std::string_view s)
|
||||||
|
{kind = string_t::basic; str = s; return *this;}
|
||||||
|
|
||||||
|
explicit operator std::string_view() const noexcept
|
||||||
|
{return std::string_view(str);}
|
||||||
|
#endif
|
||||||
|
|
||||||
string_t kind;
|
string_t kind;
|
||||||
std::string str;
|
std::string str;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
// Copyright Toru Niina 2017.
|
|
||||||
// Distributed under the MIT License.
|
|
||||||
#ifndef TOML11_TO_TOML
|
|
||||||
#define TOML11_TO_TOML
|
|
||||||
#include "value.hpp"
|
|
||||||
|
|
||||||
namespace toml
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline value to_toml(T&& x)
|
|
||||||
{
|
|
||||||
return value(std::forward<T>(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline value to_toml(T&& x, string_t kind)
|
|
||||||
{
|
|
||||||
return value(std::forward<T>(x), kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline value to_toml(local_date d, local_time t)
|
|
||||||
{
|
|
||||||
return value(local_datetime(d, t));
|
|
||||||
}
|
|
||||||
inline value to_toml(local_date d, local_time t, time_offset ofs)
|
|
||||||
{
|
|
||||||
return value(offset_datetime(d, t, ofs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ... Ts>
|
|
||||||
inline value to_toml(Ts&& ... xs)
|
|
||||||
{
|
|
||||||
return value(toml::array{toml::value(std::forward<Ts>(xs)) ... });
|
|
||||||
}
|
|
||||||
|
|
||||||
inline value to_toml(std::initializer_list<std::pair<std::string, toml::value>> xs)
|
|
||||||
{
|
|
||||||
return value(toml::table(xs.begin(), xs.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // toml
|
|
||||||
#endif // TOML11_TO_TOML
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_TRAITS
|
#ifndef TOML11_TRAITS_HPP
|
||||||
#define TOML11_TRAITS
|
#define TOML11_TRAITS_HPP
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class value; // forward decl
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -45,6 +48,22 @@ struct has_resize_method_impl
|
|||||||
template<typename T> static std::false_type check(...);
|
template<typename T> static std::false_type check(...);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct has_from_toml_method_impl
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
static std::true_type check(
|
||||||
|
decltype(std::declval<T>().from_toml(std::declval<::toml::value>()))*);
|
||||||
|
template<typename T>
|
||||||
|
static std::false_type check(...);
|
||||||
|
};
|
||||||
|
struct has_into_toml_method_impl
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
static std::true_type check(decltype(std::declval<T>().into_toml())*);
|
||||||
|
template<typename T>
|
||||||
|
static std::false_type check(...);
|
||||||
|
};
|
||||||
|
|
||||||
/// Intel C++ compiler can not use decltype in parent class declaration, here
|
/// Intel C++ compiler can not use decltype in parent class declaration, here
|
||||||
/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076
|
/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076
|
||||||
#ifdef __INTEL_COMPILER
|
#ifdef __INTEL_COMPILER
|
||||||
@@ -62,6 +81,14 @@ struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
|
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct has_from_toml_method
|
||||||
|
: decltype(has_from_toml_method_impl::check<T>(nullptr)){};
|
||||||
|
template<typename T>
|
||||||
|
struct has_into_toml_method
|
||||||
|
: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
|
||||||
|
|
||||||
#ifdef __INTEL_COMPILER
|
#ifdef __INTEL_COMPILER
|
||||||
#undef decltype(...)
|
#undef decltype(...)
|
||||||
#endif
|
#endif
|
||||||
@@ -142,6 +169,21 @@ using return_type_of_t = typename std::result_of<F(Args...)>::type;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// is_string_literal
|
||||||
|
//
|
||||||
|
// to use this, pass `typename remove_reference<T>::type` to T.
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_string_literal:
|
||||||
|
disjunction<
|
||||||
|
std::is_same<const char*, T>,
|
||||||
|
conjunction<
|
||||||
|
std::is_array<T>,
|
||||||
|
std::is_same<const char, typename std::remove_extent<T>::type>
|
||||||
|
>
|
||||||
|
>{};
|
||||||
|
|
||||||
}// detail
|
}// detail
|
||||||
}//toml
|
}//toml
|
||||||
#endif // TOML_TRAITS
|
#endif // TOML_TRAITS
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_TYPES_H
|
#ifndef TOML11_TYPES_HPP
|
||||||
#define TOML11_TYPES_H
|
#define TOML11_TYPES_HPP
|
||||||
#include "datetime.hpp"
|
#include "datetime.hpp"
|
||||||
#include "string.hpp"
|
#include "string.hpp"
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#if __has_include(<string_view>)
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
@@ -127,29 +132,29 @@ template<> struct toml_default_type<value_t::Empty > {typedef void
|
|||||||
template<> struct toml_default_type<value_t::Unknown > {typedef void type;};
|
template<> struct toml_default_type<value_t::Unknown > {typedef void type;};
|
||||||
|
|
||||||
template<typename T> struct toml_value_t {static constexpr value_t value = value_t::Unknown ;};
|
template<typename T> struct toml_value_t {static constexpr value_t value = value_t::Unknown ;};
|
||||||
template<> struct toml_value_t<Boolean >{static constexpr value_t value = value_t::Boolean ;};
|
template<> struct toml_value_t<boolean >{static constexpr value_t value = value_t::Boolean ;};
|
||||||
template<> struct toml_value_t<Integer >{static constexpr value_t value = value_t::Integer ;};
|
template<> struct toml_value_t<integer >{static constexpr value_t value = value_t::Integer ;};
|
||||||
template<> struct toml_value_t<Float >{static constexpr value_t value = value_t::Float ;};
|
template<> struct toml_value_t<floating >{static constexpr value_t value = value_t::Float ;};
|
||||||
template<> struct toml_value_t<String >{static constexpr value_t value = value_t::String ;};
|
template<> struct toml_value_t<string >{static constexpr value_t value = value_t::String ;};
|
||||||
template<> struct toml_value_t<OffsetDatetime>{static constexpr value_t value = value_t::OffsetDatetime;};
|
template<> struct toml_value_t<offset_datetime>{static constexpr value_t value = value_t::OffsetDatetime;};
|
||||||
template<> struct toml_value_t<LocalDatetime >{static constexpr value_t value = value_t::LocalDatetime ;};
|
template<> struct toml_value_t<local_datetime >{static constexpr value_t value = value_t::LocalDatetime ;};
|
||||||
template<> struct toml_value_t<LocalDate >{static constexpr value_t value = value_t::LocalDate ;};
|
template<> struct toml_value_t<local_date >{static constexpr value_t value = value_t::LocalDate ;};
|
||||||
template<> struct toml_value_t<LocalTime >{static constexpr value_t value = value_t::LocalTime ;};
|
template<> struct toml_value_t<local_time >{static constexpr value_t value = value_t::LocalTime ;};
|
||||||
template<> struct toml_value_t<Array >{static constexpr value_t value = value_t::Array ;};
|
template<> struct toml_value_t<array >{static constexpr value_t value = value_t::Array ;};
|
||||||
template<> struct toml_value_t<Table >{static constexpr value_t value = value_t::Table ;};
|
template<> struct toml_value_t<table >{static constexpr value_t value = value_t::Table ;};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_exact_toml_type : disjunction<
|
struct is_exact_toml_type : disjunction<
|
||||||
std::is_same<T, Boolean >,
|
std::is_same<T, boolean >,
|
||||||
std::is_same<T, Integer >,
|
std::is_same<T, integer >,
|
||||||
std::is_same<T, Float >,
|
std::is_same<T, floating >,
|
||||||
std::is_same<T, String >,
|
std::is_same<T, string >,
|
||||||
std::is_same<T, offset_datetime>,
|
std::is_same<T, offset_datetime>,
|
||||||
std::is_same<T, local_datetime >,
|
std::is_same<T, local_datetime >,
|
||||||
std::is_same<T, local_date >,
|
std::is_same<T, local_date >,
|
||||||
std::is_same<T, local_time >,
|
std::is_same<T, local_time >,
|
||||||
std::is_same<T, Array >,
|
std::is_same<T, array >,
|
||||||
std::is_same<T, Table >
|
std::is_same<T, table >
|
||||||
>{};
|
>{};
|
||||||
template<typename T> struct is_exact_toml_type<T&> : is_exact_toml_type<T>{};
|
template<typename T> struct is_exact_toml_type<T&> : is_exact_toml_type<T>{};
|
||||||
template<typename T> struct is_exact_toml_type<T const&> : is_exact_toml_type<T>{};
|
template<typename T> struct is_exact_toml_type<T const&> : is_exact_toml_type<T>{};
|
||||||
@@ -172,6 +177,9 @@ template<typename T>
|
|||||||
struct is_container : conjunction<
|
struct is_container : conjunction<
|
||||||
negation<is_map<T>>,
|
negation<is_map<T>>,
|
||||||
negation<std::is_same<T, std::string>>,
|
negation<std::is_same<T, std::string>>,
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
negation<std::is_same<T, std::string_view>>,
|
||||||
|
#endif
|
||||||
has_iterator<T>,
|
has_iterator<T>,
|
||||||
has_value_type<T>
|
has_value_type<T>
|
||||||
>{};
|
>{};
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_UTILITY
|
#ifndef TOML11_UTILITY_HPP
|
||||||
#define TOML11_UTILITY
|
#define TOML11_UTILITY_HPP
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
# define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]]
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# define TOML11_MARK_AS_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define TOML11_MARK_AS_DEPRECATED(msg) __declspec(deprecated(msg))
|
||||||
|
#else
|
||||||
|
# define TOML11_MARK_AS_DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -29,8 +39,9 @@ inline void resize_impl(T& container, std::size_t N, std::true_type)
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline void resize_impl(T& container, std::size_t N, std::false_type)
|
inline void resize_impl(T& container, std::size_t N, std::false_type)
|
||||||
{
|
{
|
||||||
if(container.size() >= N) return;
|
if(container.size() >= N) {return;}
|
||||||
else throw std::invalid_argument("not resizable type");
|
|
||||||
|
throw std::invalid_argument("not resizable type");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
@@ -38,8 +49,9 @@ inline void resize_impl(T& container, std::size_t N, std::false_type)
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline void resize(T& container, std::size_t N)
|
inline void resize(T& container, std::size_t N)
|
||||||
{
|
{
|
||||||
if(container.size() == N) return;
|
if(container.size() == N) {return;}
|
||||||
else return detail::resize_impl(container, N, detail::has_resize_method<T>());
|
|
||||||
|
return detail::resize_impl(container, N, detail::has_resize_method<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
@@ -67,13 +79,11 @@ std::string concat_to_string(Ts&& ... args)
|
|||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
T from_string(const std::string& str, U&& opt)
|
T from_string(const std::string& str, U&& opt)
|
||||||
{
|
{
|
||||||
T v(std::forward<U>(opt));
|
T v(static_cast<T>(std::forward<U>(opt)));
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> v;
|
iss >> v;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}// toml
|
}// toml
|
||||||
#endif // TOML11_UTILITY
|
#endif // TOML11_UTILITY
|
||||||
|
|||||||
542
toml/value.hpp
542
toml/value.hpp
@@ -1,8 +1,9 @@
|
|||||||
// Copyright Toru Niina 2017.
|
// Copyright Toru Niina 2017.
|
||||||
// Distributed under the MIT License.
|
// Distributed under the MIT License.
|
||||||
#ifndef TOML11_VALUE
|
#ifndef TOML11_VALUE_HPP
|
||||||
#define TOML11_VALUE
|
#define TOML11_VALUE_HPP
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
|
#include "into.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "exception.hpp"
|
#include "exception.hpp"
|
||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
@@ -13,6 +14,9 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
@@ -21,8 +25,8 @@ namespace detail
|
|||||||
{
|
{
|
||||||
// to show error messages. not recommended for users.
|
// to show error messages. not recommended for users.
|
||||||
region_base const& get_region(const value&);
|
region_base const& get_region(const value&);
|
||||||
// ditto.
|
template<typename Region>
|
||||||
void assign_keeping_region(value&, value);
|
void change_region(value&, Region&&);
|
||||||
}// detail
|
}// detail
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -44,6 +48,7 @@ class value
|
|||||||
{
|
{
|
||||||
const auto tmp = ::new(std::addressof(dst)) T(std::forward<U>(v));
|
const auto tmp = ::new(std::addressof(dst)) T(std::forward<U>(v));
|
||||||
assert(tmp == std::addressof(dst));
|
assert(tmp == std::addressof(dst));
|
||||||
|
(void)tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
using region_base = detail::region_base;
|
using region_base = detail::region_base;
|
||||||
@@ -292,6 +297,29 @@ class value
|
|||||||
assigner(this->string_, toml::string(std::string(s), kind));
|
assigner(this->string_, toml::string(std::string(s), kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
value(std::string_view s)
|
||||||
|
: type_(value_t::String),
|
||||||
|
region_info_(std::make_shared<region_base>(region_base{}))
|
||||||
|
{
|
||||||
|
assigner(this->string_, toml::string(s));
|
||||||
|
}
|
||||||
|
value& operator=(std::string_view s)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->type_ = value_t::String;
|
||||||
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
||||||
|
assigner(this->string_, toml::string(s));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
value(std::string_view s, string_t kind)
|
||||||
|
: type_(value_t::String),
|
||||||
|
region_info_(std::make_shared<region_base>(region_base{}))
|
||||||
|
{
|
||||||
|
assigner(this->string_, toml::string(s, kind));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// local date ===========================================================
|
// local date ===========================================================
|
||||||
|
|
||||||
value(const local_date& ld)
|
value(const local_date& ld)
|
||||||
@@ -473,7 +501,7 @@ class value
|
|||||||
region_info_(std::make_shared<region_base>(region_base{}))
|
region_info_(std::make_shared<region_base>(region_base{}))
|
||||||
{
|
{
|
||||||
array ary; ary.reserve(list.size());
|
array ary; ary.reserve(list.size());
|
||||||
for(auto& elem : list) {ary.emplace_back(std::move(elem));}
|
for(const auto& elem : list) {ary.emplace_back(elem);}
|
||||||
assigner(this->array_, std::move(ary));
|
assigner(this->array_, std::move(ary));
|
||||||
}
|
}
|
||||||
template<typename T, typename std::enable_if<detail::is_container<T>::value,
|
template<typename T, typename std::enable_if<detail::is_container<T>::value,
|
||||||
@@ -485,7 +513,7 @@ class value
|
|||||||
this->region_info_ = std::make_shared<region_base>(region_base{});
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
||||||
|
|
||||||
array ary; ary.reserve(list.size());
|
array ary; ary.reserve(list.size());
|
||||||
for(auto& elem : list) {ary.emplace_back(std::move(elem));}
|
for(const auto& elem : list) {ary.emplace_back(elem);}
|
||||||
assigner(this->array_, std::move(ary));
|
assigner(this->array_, std::move(ary));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -533,10 +561,70 @@ class value
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// user-defined =========================================================
|
||||||
|
|
||||||
|
// convert using into_toml() method -------------------------------------
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
|
||||||
|
detail::has_into_toml_method<T> // but has `into_toml` method
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
value(const T& ud): value(ud.into_toml()) {}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
|
||||||
|
detail::has_into_toml_method<T> // but has `into_toml` method
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
value& operator=(const T& ud)
|
||||||
|
{
|
||||||
|
*this = ud.into_toml();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert using into<T> struct -----------------------------------------
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>::value,
|
||||||
|
std::nullptr_t>::type = nullptr,
|
||||||
|
std::size_t S = sizeof(::toml::into<T>)>
|
||||||
|
value(const T& ud): value(::toml::into<T>::into_toml(ud)) {}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>>::value,
|
||||||
|
std::nullptr_t>::type = nullptr,
|
||||||
|
std::size_t S = sizeof(::toml::into<T>)>
|
||||||
|
value& operator=(const T& ud)
|
||||||
|
{
|
||||||
|
*this = ::toml::into<T>::into_toml(ud);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for internal use ------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename T, typename Container, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
value(std::pair<T, detail::region<Container>> parse_result)
|
||||||
|
: value(std::move(parse_result.first), std::move(parse_result.second))
|
||||||
|
{}
|
||||||
|
|
||||||
|
// type checking and casting ============================================
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool is() const noexcept {return value_traits<T>::type_index == this->type_;}
|
bool is() const noexcept {return value_traits<T>::type_index == this->type_;}
|
||||||
bool is(value_t t) const noexcept {return t == this->type_;}
|
bool is(value_t t) const noexcept {return t == this->type_;}
|
||||||
|
|
||||||
|
bool is_uninitialized() const noexcept {return this->is(value_t::Empty );}
|
||||||
|
bool is_boolean() const noexcept {return this->is(value_t::Boolean );}
|
||||||
|
bool is_integer() const noexcept {return this->is(value_t::Integer );}
|
||||||
|
bool is_float() const noexcept {return this->is(value_t::Float );}
|
||||||
|
bool is_string() const noexcept {return this->is(value_t::String );}
|
||||||
|
bool is_offset_datetime() const noexcept {return this->is(value_t::OffsetDatetime);}
|
||||||
|
bool is_local_datetime() const noexcept {return this->is(value_t::LocalDatetime );}
|
||||||
|
bool is_local_date() const noexcept {return this->is(value_t::LocalDate );}
|
||||||
|
bool is_local_time() const noexcept {return this->is(value_t::LocalTime );}
|
||||||
|
bool is_array() const noexcept {return this->is(value_t::Array );}
|
||||||
|
bool is_table() const noexcept {return this->is(value_t::Table );}
|
||||||
|
|
||||||
value_t type() const {return type_;}
|
value_t type() const {return type_;}
|
||||||
|
|
||||||
template<value_t T>
|
template<value_t T>
|
||||||
@@ -546,6 +634,52 @@ class value
|
|||||||
template<value_t T>
|
template<value_t T>
|
||||||
typename detail::toml_default_type<T>::type&& cast() &&;
|
typename detail::toml_default_type<T>::type&& cast() &&;
|
||||||
|
|
||||||
|
boolean const& as_boolean() const& noexcept {return this->boolean_;}
|
||||||
|
integer const& as_integer() const& noexcept {return this->integer_;}
|
||||||
|
floating const& as_float() const& noexcept {return this->floating_;}
|
||||||
|
string const& as_string() const& noexcept {return this->string_;}
|
||||||
|
offset_datetime const& as_offset_datetime() const& noexcept {return this->offset_datetime_;}
|
||||||
|
local_datetime const& as_local_datetime() const& noexcept {return this->local_datetime_;}
|
||||||
|
local_date const& as_local_date() const& noexcept {return this->local_date_;}
|
||||||
|
local_time const& as_local_time() const& noexcept {return this->local_time_;}
|
||||||
|
array const& as_array() const& noexcept {return this->array_.value();}
|
||||||
|
table const& as_table() const& noexcept {return this->table_.value();}
|
||||||
|
|
||||||
|
boolean & as_boolean() & noexcept {return this->boolean_;}
|
||||||
|
integer & as_integer() & noexcept {return this->integer_;}
|
||||||
|
floating & as_float() & noexcept {return this->floating_;}
|
||||||
|
string & as_string() & noexcept {return this->string_;}
|
||||||
|
offset_datetime& as_offset_datetime() & noexcept {return this->offset_datetime_;}
|
||||||
|
local_datetime & as_local_datetime() & noexcept {return this->local_datetime_;}
|
||||||
|
local_date & as_local_date() & noexcept {return this->local_date_;}
|
||||||
|
local_time & as_local_time() & noexcept {return this->local_time_;}
|
||||||
|
array & as_array() & noexcept {return this->array_.value();}
|
||||||
|
table & as_table() & noexcept {return this->table_.value();}
|
||||||
|
|
||||||
|
boolean && as_boolean() && noexcept {return std::move(this->boolean_);}
|
||||||
|
integer && as_integer() && noexcept {return std::move(this->integer_);}
|
||||||
|
floating && as_float() && noexcept {return std::move(this->floating_);}
|
||||||
|
string && as_string() && noexcept {return std::move(this->string_);}
|
||||||
|
offset_datetime&& as_offset_datetime() && noexcept {return std::move(this->offset_datetime_);}
|
||||||
|
local_datetime && as_local_datetime() && noexcept {return std::move(this->local_datetime_);}
|
||||||
|
local_date && as_local_date() && noexcept {return std::move(this->local_date_);}
|
||||||
|
local_time && as_local_time() && noexcept {return std::move(this->local_time_);}
|
||||||
|
array && as_array() && noexcept {return std::move(this->array_.value());}
|
||||||
|
table && as_table() && noexcept {return std::move(this->table_.value());}
|
||||||
|
|
||||||
|
std::string comment() const
|
||||||
|
{
|
||||||
|
return this->region_info_->comment();
|
||||||
|
}
|
||||||
|
std::string comment_before() const
|
||||||
|
{
|
||||||
|
return this->region_info_->comment_before();
|
||||||
|
}
|
||||||
|
std::string comment_inline() const
|
||||||
|
{
|
||||||
|
return this->region_info_->comment_inline();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void cleanup() noexcept
|
void cleanup() noexcept
|
||||||
@@ -562,11 +696,8 @@ class value
|
|||||||
// for error messages
|
// for error messages
|
||||||
friend region_base const& detail::get_region(const value&);
|
friend region_base const& detail::get_region(const value&);
|
||||||
|
|
||||||
// to see why it's here, see detail::insert_nested_key.
|
template<typename Region>
|
||||||
friend void detail::assign_keeping_region(value&, value);
|
friend void detail::change_region(value&, Region&&);
|
||||||
|
|
||||||
template<value_t T>
|
|
||||||
struct switch_cast;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -599,129 +730,130 @@ inline region_base const& get_region(const value& v)
|
|||||||
{
|
{
|
||||||
return *(v.region_info_);
|
return *(v.region_info_);
|
||||||
}
|
}
|
||||||
// If we keep region information after assigning another toml::* types, the
|
|
||||||
// error message become different from the actual value contained.
|
template<typename Region>
|
||||||
// To avoid this kind of confusing phenomena, the default assigners clear the
|
void change_region(value& v, Region&& reg)
|
||||||
// old region_info_. But this functionality is actually needed deep inside of
|
|
||||||
// parser, so if you want to see the usecase, see toml::detail::insert_nested_key
|
|
||||||
// defined in toml/parser.hpp.
|
|
||||||
inline void assign_keeping_region(value& v, value other)
|
|
||||||
{
|
{
|
||||||
v.cleanup(); // this keeps region info
|
using region_type = typename std::remove_reference<
|
||||||
// keep region_info_ intact
|
typename std::remove_cv<Region>::type
|
||||||
v.type_ = other.type();
|
>::type;
|
||||||
switch(v.type())
|
|
||||||
{
|
std::shared_ptr<region_base> new_reg =
|
||||||
case value_t::Boolean : ::toml::value::assigner(v.boolean_ , other.boolean_ ); break;
|
std::make_shared<region_type>(std::forward<region_type>(reg));
|
||||||
case value_t::Integer : ::toml::value::assigner(v.integer_ , other.integer_ ); break;
|
v.region_info_ = new_reg;
|
||||||
case value_t::Float : ::toml::value::assigner(v.floating_ , other.floating_ ); break;
|
|
||||||
case value_t::String : ::toml::value::assigner(v.string_ , other.string_ ); break;
|
|
||||||
case value_t::OffsetDatetime: ::toml::value::assigner(v.offset_datetime_, other.offset_datetime_); break;
|
|
||||||
case value_t::LocalDatetime : ::toml::value::assigner(v.local_datetime_ , other.local_datetime_ ); break;
|
|
||||||
case value_t::LocalDate : ::toml::value::assigner(v.local_date_ , other.local_date_ ); break;
|
|
||||||
case value_t::LocalTime : ::toml::value::assigner(v.local_time_ , other.local_time_ ); break;
|
|
||||||
case value_t::Array : ::toml::value::assigner(v.array_ , other.array_ ); break;
|
|
||||||
case value_t::Table : ::toml::value::assigner(v.table_ , other.table_ ); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<value_t Expected>
|
||||||
|
[[noreturn]] inline void throw_bad_cast(value_t actual, const ::toml::value& v)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(concat_to_string(
|
||||||
|
"[error] toml::value bad_cast to ", Expected), {
|
||||||
|
{std::addressof(get_region(v)),
|
||||||
|
concat_to_string("the actual type is ", actual)}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<value_t T>
|
||||||
|
struct switch_cast;
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::Boolean>
|
||||||
|
{
|
||||||
|
static ::toml::boolean& invoke(value& v) {return v.as_boolean();}
|
||||||
|
static ::toml::boolean const& invoke(value const& v) {return v.as_boolean();}
|
||||||
|
static ::toml::boolean&& invoke(value&& v) {return std::move(v).as_boolean();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::Integer>
|
||||||
|
{
|
||||||
|
static ::toml::integer& invoke(value& v) {return v.as_integer();}
|
||||||
|
static ::toml::integer const& invoke(value const& v) {return v.as_integer();}
|
||||||
|
static ::toml::integer&& invoke(value&& v) {return std::move(v).as_integer();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::Float>
|
||||||
|
{
|
||||||
|
static ::toml::floating& invoke(value& v) {return v.as_float();}
|
||||||
|
static ::toml::floating const& invoke(value const& v) {return v.as_float();}
|
||||||
|
static ::toml::floating&& invoke(value&& v) {return std::move(v).as_float();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::String>
|
||||||
|
{
|
||||||
|
static ::toml::string& invoke(value& v) {return v.as_string();}
|
||||||
|
static ::toml::string const& invoke(value const& v) {return v.as_string();}
|
||||||
|
static ::toml::string&& invoke(value&& v) {return std::move(v).as_string();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::OffsetDatetime>
|
||||||
|
{
|
||||||
|
static ::toml::offset_datetime& invoke(value& v) {return v.as_offset_datetime();}
|
||||||
|
static ::toml::offset_datetime const& invoke(value const& v) {return v.as_offset_datetime();}
|
||||||
|
static ::toml::offset_datetime&& invoke(value&& v) {return std::move(v).as_offset_datetime();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::LocalDatetime>
|
||||||
|
{
|
||||||
|
static ::toml::local_datetime& invoke(value& v) {return v.as_local_datetime();}
|
||||||
|
static ::toml::local_datetime const& invoke(value const& v) {return v.as_local_datetime();}
|
||||||
|
static ::toml::local_datetime&& invoke(value&& v) {return std::move(v).as_local_datetime();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::LocalDate>
|
||||||
|
{
|
||||||
|
static ::toml::local_date& invoke(value& v) {return v.as_local_date();}
|
||||||
|
static ::toml::local_date const& invoke(value const& v) {return v.as_local_date();}
|
||||||
|
static ::toml::local_date&& invoke(value&& v) {return std::move(v).as_local_date();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::LocalTime>
|
||||||
|
{
|
||||||
|
static ::toml::local_time& invoke(value& v) {return v.as_local_time();}
|
||||||
|
static ::toml::local_time const& invoke(value const& v) {return v.as_local_time();}
|
||||||
|
static ::toml::local_time&& invoke(value&& v) {return std::move(v).as_local_time();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::Array>
|
||||||
|
{
|
||||||
|
static ::toml::array& invoke(value& v) {return v.as_array();}
|
||||||
|
static ::toml::array const& invoke(value const& v) {return v.as_array();}
|
||||||
|
static ::toml::array&& invoke(value&& v) {return std::move(v).as_array();}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct switch_cast<value_t::Table>
|
||||||
|
{
|
||||||
|
static ::toml::table& invoke(value& v) {return v.as_table();}
|
||||||
|
static ::toml::table const& invoke(value const& v) {return v.as_table();}
|
||||||
|
static ::toml::table&& invoke(value&& v) {return std::move(v).as_table();}
|
||||||
|
};
|
||||||
}// detail
|
}// detail
|
||||||
|
|
||||||
|
|
||||||
template<> struct value::switch_cast<value_t::Boolean>
|
|
||||||
{
|
|
||||||
static Boolean& invoke(value& v) {return v.boolean_;}
|
|
||||||
static Boolean const& invoke(value const& v) {return v.boolean_;}
|
|
||||||
static Boolean&& invoke(value&& v) {return std::move(v.boolean_);}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::Integer>
|
|
||||||
{
|
|
||||||
static Integer& invoke(value& v) {return v.integer_;}
|
|
||||||
static Integer const& invoke(value const& v) {return v.integer_;}
|
|
||||||
static Integer&& invoke(value&& v) {return std::move(v.integer_);}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::Float>
|
|
||||||
{
|
|
||||||
static Float& invoke(value& v) {return v.floating_;}
|
|
||||||
static Float const& invoke(value const& v) {return v.floating_;}
|
|
||||||
static Float&& invoke(value&& v) {return std::move(v.floating_);}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::String>
|
|
||||||
{
|
|
||||||
static String& invoke(value& v) {return v.string_;}
|
|
||||||
static String const& invoke(value const& v) {return v.string_;}
|
|
||||||
static String&& invoke(value&& v) {return std::move(v.string_);}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::OffsetDatetime>
|
|
||||||
{
|
|
||||||
static OffsetDatetime& invoke(value& v) {return v.offset_datetime_;}
|
|
||||||
static OffsetDatetime const& invoke(value const& v) {return v.offset_datetime_;}
|
|
||||||
static OffsetDatetime&& invoke(value&& v) {return std::move(v.offset_datetime_);}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::LocalDatetime>
|
|
||||||
{
|
|
||||||
static LocalDatetime& invoke(value& v) {return v.local_datetime_;}
|
|
||||||
static LocalDatetime const& invoke(value const& v) {return v.local_datetime_;}
|
|
||||||
static LocalDatetime&& invoke(value&& v) {return std::move(v.local_datetime_);}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::LocalDate>
|
|
||||||
{
|
|
||||||
static LocalDate& invoke(value& v) {return v.local_date_;}
|
|
||||||
static LocalDate const& invoke(value const& v) {return v.local_date_;}
|
|
||||||
static LocalDate&& invoke(value&& v) {return std::move(v.local_date_);}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::LocalTime>
|
|
||||||
{
|
|
||||||
static LocalTime& invoke(value& v) {return v.local_time_;}
|
|
||||||
static LocalTime const& invoke(value const& v) {return v.local_time_;}
|
|
||||||
static LocalTime&& invoke(value&& v) {return std::move(v.local_time_);}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::Array>
|
|
||||||
{
|
|
||||||
static Array& invoke(value& v) {return v.array_.value();}
|
|
||||||
static Array const& invoke(value const& v) {return v.array_.value();}
|
|
||||||
static Array&& invoke(value&& v) {return std::move(v.array_.value());}
|
|
||||||
};
|
|
||||||
template<> struct value::switch_cast<value_t::Table>
|
|
||||||
{
|
|
||||||
static Table& invoke(value& v) {return v.table_.value();}
|
|
||||||
static Table const& invoke(value const& v) {return v.table_.value();}
|
|
||||||
static Table&& invoke(value&& v) {return std::move(v.table_.value());}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<value_t T>
|
template<value_t T>
|
||||||
typename detail::toml_default_type<T>::type& value::cast() &
|
typename detail::toml_default_type<T>::type& value::cast() &
|
||||||
{
|
{
|
||||||
if(T != this->type_)
|
if(T != this->type_)
|
||||||
{
|
{
|
||||||
throw type_error(format_underline(concat_to_string(
|
detail::throw_bad_cast<T>(this->type_, *this);
|
||||||
"[error] toml::value bad_cast to ", T), *region_info_,
|
|
||||||
concat_to_string("the actual type is ", this->type_)));
|
|
||||||
}
|
}
|
||||||
return switch_cast<T>::invoke(*this);
|
return detail::switch_cast<T>::invoke(*this);
|
||||||
}
|
}
|
||||||
template<value_t T>
|
template<value_t T>
|
||||||
typename detail::toml_default_type<T>::type const& value::cast() const&
|
typename detail::toml_default_type<T>::type const& value::cast() const&
|
||||||
{
|
{
|
||||||
if(T != this->type_)
|
if(T != this->type_)
|
||||||
{
|
{
|
||||||
throw type_error(format_underline(concat_to_string(
|
detail::throw_bad_cast<T>(this->type_, *this);
|
||||||
"[error] toml::value bad_cast to ", T), *region_info_,
|
|
||||||
concat_to_string("the actual type is ", this->type_)));
|
|
||||||
}
|
}
|
||||||
return switch_cast<T>::invoke(*this);
|
return detail::switch_cast<T>::invoke(*this);
|
||||||
}
|
}
|
||||||
template<value_t T>
|
template<value_t T>
|
||||||
typename detail::toml_default_type<T>::type&& value::cast() &&
|
typename detail::toml_default_type<T>::type&& value::cast() &&
|
||||||
{
|
{
|
||||||
if(T != this->type_)
|
if(T != this->type_)
|
||||||
{
|
{
|
||||||
throw type_error(format_underline(concat_to_string(
|
detail::throw_bad_cast<T>(this->type_, *this);
|
||||||
"[error] toml::value bad_cast to ", T), *region_info_,
|
|
||||||
concat_to_string("the actual type is ", this->type_)));
|
|
||||||
}
|
}
|
||||||
return switch_cast<T>::invoke(std::move(*this));
|
return detail::switch_cast<T>::invoke(std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const toml::value& lhs, const toml::value& rhs)
|
inline bool operator==(const toml::value& lhs, const toml::value& rhs)
|
||||||
@@ -730,28 +862,48 @@ inline bool operator==(const toml::value& lhs, const toml::value& rhs)
|
|||||||
switch(lhs.type())
|
switch(lhs.type())
|
||||||
{
|
{
|
||||||
case value_t::Boolean :
|
case value_t::Boolean :
|
||||||
return lhs.cast<value_t::Boolean >() == rhs.cast<value_t::Boolean >();
|
{
|
||||||
|
return lhs.as_boolean() == rhs.as_boolean();
|
||||||
|
}
|
||||||
case value_t::Integer :
|
case value_t::Integer :
|
||||||
return lhs.cast<value_t::Integer >() == rhs.cast<value_t::Integer >();
|
{
|
||||||
|
return lhs.as_integer() == rhs.as_integer();
|
||||||
|
}
|
||||||
case value_t::Float :
|
case value_t::Float :
|
||||||
return lhs.cast<value_t::Float >() == rhs.cast<value_t::Float >();
|
{
|
||||||
|
return lhs.as_float() == rhs.as_float();
|
||||||
|
}
|
||||||
case value_t::String :
|
case value_t::String :
|
||||||
return lhs.cast<value_t::String >() == rhs.cast<value_t::String >();
|
{
|
||||||
|
return lhs.as_string() == rhs.as_string();
|
||||||
|
}
|
||||||
case value_t::OffsetDatetime:
|
case value_t::OffsetDatetime:
|
||||||
return lhs.cast<value_t::OffsetDatetime>() == rhs.cast<value_t::OffsetDatetime>();
|
{
|
||||||
|
return lhs.as_offset_datetime() == rhs.as_offset_datetime();
|
||||||
|
}
|
||||||
case value_t::LocalDatetime:
|
case value_t::LocalDatetime:
|
||||||
return lhs.cast<value_t::LocalDatetime>() == rhs.cast<value_t::LocalDatetime>();
|
{
|
||||||
|
return lhs.as_local_datetime() == rhs.as_local_datetime();
|
||||||
|
}
|
||||||
case value_t::LocalDate:
|
case value_t::LocalDate:
|
||||||
return lhs.cast<value_t::LocalDate>() == rhs.cast<value_t::LocalDate>();
|
{
|
||||||
|
return lhs.as_local_date() == rhs.as_local_date();
|
||||||
|
}
|
||||||
case value_t::LocalTime:
|
case value_t::LocalTime:
|
||||||
return lhs.cast<value_t::LocalTime>() == rhs.cast<value_t::LocalTime>();
|
{
|
||||||
|
return lhs.as_local_time() == rhs.as_local_time();
|
||||||
|
}
|
||||||
case value_t::Array :
|
case value_t::Array :
|
||||||
return lhs.cast<value_t::Array >() == rhs.cast<value_t::Array >();
|
{
|
||||||
|
return lhs.as_array() == rhs.as_array();
|
||||||
|
}
|
||||||
case value_t::Table :
|
case value_t::Table :
|
||||||
return lhs.cast<value_t::Table >() == rhs.cast<value_t::Table >();
|
{
|
||||||
case value_t::Empty : return true;
|
return lhs.as_table() == rhs.as_table();
|
||||||
case value_t::Unknown : return false;
|
}
|
||||||
default: return false;
|
case value_t::Empty : {return true; }
|
||||||
|
case value_t::Unknown : {return false;}
|
||||||
|
default: {return false;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline bool operator<(const toml::value& lhs, const toml::value& rhs)
|
inline bool operator<(const toml::value& lhs, const toml::value& rhs)
|
||||||
@@ -760,28 +912,48 @@ inline bool operator<(const toml::value& lhs, const toml::value& rhs)
|
|||||||
switch(lhs.type())
|
switch(lhs.type())
|
||||||
{
|
{
|
||||||
case value_t::Boolean :
|
case value_t::Boolean :
|
||||||
return lhs.cast<value_t::Boolean >() < rhs.cast<value_t::Boolean >();
|
{
|
||||||
|
return lhs.as_boolean() < rhs.as_boolean();
|
||||||
|
}
|
||||||
case value_t::Integer :
|
case value_t::Integer :
|
||||||
return lhs.cast<value_t::Integer >() < rhs.cast<value_t::Integer >();
|
{
|
||||||
|
return lhs.as_integer() < rhs.as_integer();
|
||||||
|
}
|
||||||
case value_t::Float :
|
case value_t::Float :
|
||||||
return lhs.cast<value_t::Float >() < rhs.cast<value_t::Float >();
|
{
|
||||||
|
return lhs.as_float() < rhs.as_float();
|
||||||
|
}
|
||||||
case value_t::String :
|
case value_t::String :
|
||||||
return lhs.cast<value_t::String >() < rhs.cast<value_t::String >();
|
{
|
||||||
|
return lhs.as_string() < rhs.as_string();
|
||||||
|
}
|
||||||
case value_t::OffsetDatetime:
|
case value_t::OffsetDatetime:
|
||||||
return lhs.cast<value_t::OffsetDatetime>() < rhs.cast<value_t::OffsetDatetime>();
|
{
|
||||||
|
return lhs.as_offset_datetime() < rhs.as_offset_datetime();
|
||||||
|
}
|
||||||
case value_t::LocalDatetime:
|
case value_t::LocalDatetime:
|
||||||
return lhs.cast<value_t::LocalDatetime>() < rhs.cast<value_t::LocalDatetime>();
|
{
|
||||||
|
return lhs.as_local_datetime() < rhs.as_local_datetime();
|
||||||
|
}
|
||||||
case value_t::LocalDate:
|
case value_t::LocalDate:
|
||||||
return lhs.cast<value_t::LocalDate>() < rhs.cast<value_t::LocalDate>();
|
{
|
||||||
|
return lhs.as_local_date() < rhs.as_local_date();
|
||||||
|
}
|
||||||
case value_t::LocalTime:
|
case value_t::LocalTime:
|
||||||
return lhs.cast<value_t::LocalTime>() < rhs.cast<value_t::LocalTime>();
|
{
|
||||||
|
return lhs.as_local_time() < rhs.as_local_time();
|
||||||
|
}
|
||||||
case value_t::Array :
|
case value_t::Array :
|
||||||
return lhs.cast<value_t::Array >() < rhs.cast<value_t::Array >();
|
{
|
||||||
|
return lhs.as_array() < rhs.as_array();
|
||||||
|
}
|
||||||
case value_t::Table :
|
case value_t::Table :
|
||||||
return lhs.cast<value_t::Table >() < rhs.cast<value_t::Table >();
|
{
|
||||||
case value_t::Empty : return false;
|
return lhs.as_table() < rhs.as_table();
|
||||||
case value_t::Unknown : return false;
|
}
|
||||||
default: return false;
|
case value_t::Empty : {return false;}
|
||||||
|
case value_t::Unknown : {return false;}
|
||||||
|
default: {return false;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,8 +978,10 @@ inline std::string format_error(const std::string& err_msg,
|
|||||||
const toml::value& v, const std::string& comment,
|
const toml::value& v, const std::string& comment,
|
||||||
std::vector<std::string> hints = {})
|
std::vector<std::string> hints = {})
|
||||||
{
|
{
|
||||||
return detail::format_underline(err_msg, detail::get_region(v), comment,
|
return detail::format_underline(err_msg,
|
||||||
std::move(hints));
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
||||||
|
{std::addressof(detail::get_region(v)), comment}
|
||||||
|
}, std::move(hints));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string format_error(const std::string& err_msg,
|
inline std::string format_error(const std::string& err_msg,
|
||||||
@@ -815,9 +989,97 @@ inline std::string format_error(const std::string& err_msg,
|
|||||||
const toml::value& v2, const std::string& comment2,
|
const toml::value& v2, const std::string& comment2,
|
||||||
std::vector<std::string> hints = {})
|
std::vector<std::string> hints = {})
|
||||||
{
|
{
|
||||||
return detail::format_underline(err_msg, detail::get_region(v1), comment1,
|
return detail::format_underline(err_msg,
|
||||||
detail::get_region(v2), comment2,
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
||||||
std::move(hints));
|
{std::addressof(detail::get_region(v1)), comment1},
|
||||||
|
{std::addressof(detail::get_region(v2)), comment2}
|
||||||
|
}, std::move(hints));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string format_error(const std::string& err_msg,
|
||||||
|
const toml::value& v1, const std::string& comment1,
|
||||||
|
const toml::value& v2, const std::string& comment2,
|
||||||
|
const toml::value& v3, const std::string& comment3,
|
||||||
|
std::vector<std::string> hints = {})
|
||||||
|
{
|
||||||
|
return detail::format_underline(err_msg,
|
||||||
|
std::vector<std::pair<detail::region_base const*, std::string>>{
|
||||||
|
{std::addressof(detail::get_region(v1)), comment1},
|
||||||
|
{std::addressof(detail::get_region(v2)), comment2},
|
||||||
|
{std::addressof(detail::get_region(v3)), comment3}
|
||||||
|
}, std::move(hints));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Visitor>
|
||||||
|
detail::return_type_of_t<Visitor, const toml::boolean&>
|
||||||
|
visit(Visitor&& visitor, const toml::value& v)
|
||||||
|
{
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case value_t::Boolean : {return visitor(v.as_boolean ());}
|
||||||
|
case value_t::Integer : {return visitor(v.as_integer ());}
|
||||||
|
case value_t::Float : {return visitor(v.as_float ());}
|
||||||
|
case value_t::String : {return visitor(v.as_string ());}
|
||||||
|
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
|
||||||
|
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
|
||||||
|
case value_t::LocalDate : {return visitor(v.as_local_date ());}
|
||||||
|
case value_t::LocalTime : {return visitor(v.as_local_time ());}
|
||||||
|
case value_t::Array : {return visitor(v.as_array ());}
|
||||||
|
case value_t::Table : {return visitor(v.as_table ());}
|
||||||
|
case value_t::Empty : break;
|
||||||
|
case value_t::Unknown : break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(format_error("[error] toml::visit: toml::value "
|
||||||
|
"does not have any valid value.", v, "here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Visitor>
|
||||||
|
detail::return_type_of_t<Visitor, toml::boolean&>
|
||||||
|
visit(Visitor&& visitor, toml::value& v)
|
||||||
|
{
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case value_t::Boolean : {return visitor(v.as_boolean ());}
|
||||||
|
case value_t::Integer : {return visitor(v.as_integer ());}
|
||||||
|
case value_t::Float : {return visitor(v.as_float ());}
|
||||||
|
case value_t::String : {return visitor(v.as_string ());}
|
||||||
|
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
|
||||||
|
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
|
||||||
|
case value_t::LocalDate : {return visitor(v.as_local_date ());}
|
||||||
|
case value_t::LocalTime : {return visitor(v.as_local_time ());}
|
||||||
|
case value_t::Array : {return visitor(v.as_array ());}
|
||||||
|
case value_t::Table : {return visitor(v.as_table ());}
|
||||||
|
case value_t::Empty : break;
|
||||||
|
case value_t::Unknown : break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(format_error("[error] toml::visit: toml::value "
|
||||||
|
"does not have any valid value.", v, "here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Visitor>
|
||||||
|
detail::return_type_of_t<Visitor, toml::boolean&&>
|
||||||
|
visit(Visitor&& visitor, toml::value&& v)
|
||||||
|
{
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case value_t::Boolean : {return visitor(std::move(v.as_boolean ()));}
|
||||||
|
case value_t::Integer : {return visitor(std::move(v.as_integer ()));}
|
||||||
|
case value_t::Float : {return visitor(std::move(v.as_float ()));}
|
||||||
|
case value_t::String : {return visitor(std::move(v.as_string ()));}
|
||||||
|
case value_t::OffsetDatetime: {return visitor(std::move(v.as_offset_datetime()));}
|
||||||
|
case value_t::LocalDatetime : {return visitor(std::move(v.as_local_datetime ()));}
|
||||||
|
case value_t::LocalDate : {return visitor(std::move(v.as_local_date ()));}
|
||||||
|
case value_t::LocalTime : {return visitor(std::move(v.as_local_time ()));}
|
||||||
|
case value_t::Array : {return visitor(std::move(v.as_array ()));}
|
||||||
|
case value_t::Table : {return visitor(std::move(v.as_table ()));}
|
||||||
|
case value_t::Empty : break;
|
||||||
|
case value_t::Unknown : break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(format_error("[error] toml::visit: toml::value "
|
||||||
|
"does not have any valid value.", v, "here"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}// toml
|
}// toml
|
||||||
|
|||||||
Reference in New Issue
Block a user