mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
330 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
c4aecc8e4b | ||
|
|
60c81d06a0 | ||
|
|
46569da231 | ||
|
|
5e20a8ff16 | ||
|
|
dd9319245e | ||
|
|
4bbe42d105 | ||
|
|
5bdc022627 | ||
|
|
41e354f1ee | ||
|
|
d1c76709b0 | ||
|
|
64774a8db0 | ||
|
|
53f6b8268b | ||
|
|
32dcc35918 | ||
|
|
8c3854b28b | ||
|
|
75af9c79df | ||
|
|
1dfe32acd8 | ||
|
|
5dfdbe4bff | ||
|
|
4584eeb57a | ||
|
|
aa67069387 | ||
|
|
ee3424ad51 | ||
|
|
17def14ab6 | ||
|
|
51dd3abcae | ||
|
|
825b2c30a1 | ||
|
|
b5b8830c29 | ||
|
|
87a5c844c2 | ||
|
|
11c7ee4501 | ||
|
|
d24a188d4c | ||
|
|
29876221f8 | ||
|
|
7c03c446fe | ||
|
|
cfdd4d4a90 | ||
|
|
5546b3389d | ||
|
|
9c95992dad | ||
|
|
edb48b2872 | ||
|
|
c63ac7e435 | ||
|
|
fec49aaaa3 | ||
|
|
617187969c | ||
|
|
e3217cd572 | ||
|
|
4d02f399a2 | ||
|
|
24723226f1 | ||
|
|
7b3684b54e | ||
|
|
13c1f9c259 | ||
|
|
6df75ad28e | ||
|
|
74fc70cfee | ||
|
|
91ac2debce | ||
|
|
0de89a9f19 | ||
|
|
130609bf5f | ||
|
|
ab41e7acb9 | ||
|
|
c15bc8df4a | ||
|
|
19524dbc4b | ||
|
|
c2e733a65d | ||
|
|
0c08b9e940 | ||
|
|
06197605ba | ||
|
|
5c24cfd325 | ||
|
|
abb6ae517d | ||
|
|
fd21d5dd95 | ||
|
|
57de57a1de | ||
|
|
e86777d19c | ||
|
|
e79069cc47 | ||
|
|
f60e93c36f | ||
|
|
e5c29c2870 | ||
|
|
acc7b7870f | ||
|
|
06f04af375 | ||
|
|
5125287ac7 | ||
|
|
56287803e7 | ||
|
|
95d73a290f | ||
|
|
26e0d87d3b | ||
|
|
fb6d51954a | ||
|
|
4d7cfc9d1d | ||
|
|
514f3c773f | ||
|
|
77b237c53a | ||
|
|
27a80b1214 | ||
|
|
f62bcb3077 | ||
|
|
be1a310ae5 | ||
|
|
affa159c82 | ||
|
|
901c299c40 | ||
|
|
2080b30110 | ||
|
|
c15cb15c4c | ||
|
|
d370ae7d0d | ||
|
|
83b588a8c8 | ||
|
|
5bfbbe35a6 | ||
|
|
c69969733f | ||
|
|
47cd6f5a41 | ||
|
|
a19c9b4a39 | ||
|
|
f64430af92 | ||
|
|
8e154cdd74 | ||
|
|
65cfa9d06b | ||
|
|
cfd82c95f0 | ||
|
|
18a22eb3c4 | ||
|
|
03be08a2e6 | ||
|
|
27ad4e2d8f | ||
|
|
0924164f51 | ||
|
|
d4a4865217 | ||
|
|
1bc66f6c28 | ||
|
|
b015e1ac5b | ||
|
|
5aae0b17c8 | ||
|
|
0f83ee6039 | ||
|
|
879b7d3bff | ||
|
|
c33ad31981 | ||
|
|
5d29509d98 | ||
|
|
717e03cd4a | ||
|
|
5a20d55dd0 | ||
|
|
dc060ba840 | ||
|
|
fcbfbd3a26 | ||
|
|
0c9b785969 | ||
|
|
bcaf5baf88 | ||
|
|
5dea88001e | ||
|
|
b63dc1f370 | ||
|
|
d3e88b3082 | ||
|
|
a1a81089c5 | ||
|
|
765ab97d8b | ||
|
|
9f8e86524a | ||
|
|
4d64c0d8af | ||
|
|
e810c3d35e | ||
|
|
fc3471434f | ||
|
|
be8600abfa | ||
|
|
e79e6150f2 | ||
|
|
fc6a15440d | ||
|
|
d7bba10fa3 | ||
|
|
247bcb0714 | ||
|
|
3055645323 | ||
|
|
0253f49101 | ||
|
|
27b9334f10 | ||
|
|
38135940e9 | ||
|
|
d75a977066 | ||
|
|
75c136924b | ||
|
|
0759e757ae | ||
|
|
4e57c5f5df | ||
|
|
ff83a6a477 | ||
|
|
3f991c4759 | ||
|
|
bf2158ae98 | ||
|
|
ff19c9f492 | ||
|
|
28ba2713ee | ||
|
|
129ea81f66 | ||
|
|
8dfe187d59 | ||
|
|
8078c719fe | ||
|
|
8e18aa9b16 | ||
|
|
ed155a5040 | ||
|
|
cf03a08632 | ||
|
|
34c3d33936 | ||
|
|
c04b75b2e3 | ||
|
|
e24039f4ef | ||
|
|
dc8ccdc458 | ||
|
|
2696e4e6ba | ||
|
|
d1d5ca6bf8 | ||
|
|
80eafd1424 | ||
|
|
9fadf71a10 | ||
|
|
ac3025d92f | ||
|
|
b0e7efa1e0 | ||
|
|
84676eab0b | ||
|
|
2b3a4d49a5 | ||
|
|
f834e0d142 | ||
|
|
a1aa780a60 | ||
|
|
48f3b73b91 | ||
|
|
04854f9d21 | ||
|
|
8388664fc6 | ||
|
|
bb215836dc | ||
|
|
2b2a05148e | ||
|
|
66807d19d1 | ||
|
|
861444a02b | ||
|
|
25789d1450 | ||
|
|
1e28cb2d13 | ||
|
|
ae564bd814 | ||
|
|
366f72bbdd | ||
|
|
3ef33c1637 | ||
|
|
e05d0bdb84 | ||
|
|
5dbbc1fb1a | ||
|
|
b3b5682cc0 | ||
|
|
df314da751 | ||
|
|
3d1783e12a | ||
|
|
f8aa604959 | ||
|
|
e3f6805629 | ||
|
|
1dddc6e26c | ||
|
|
5e052237ba | ||
|
|
a995bd515b | ||
|
|
00619c1c85 | ||
|
|
532457345c | ||
|
|
f9a018b5ea | ||
|
|
aa05858de3 | ||
|
|
2b3c8887d6 | ||
|
|
932a0646ce | ||
|
|
c3a2cd8c1e | ||
|
|
c0ce5a2d7d | ||
|
|
c3e1f68ef6 | ||
|
|
1a2fa6d53a | ||
|
|
17f3d96766 | ||
|
|
1f564ec047 | ||
|
|
679e282e23 | ||
|
|
59588e3a10 | ||
|
|
f83a8b450e | ||
|
|
8bf97d8a00 | ||
|
|
2ee8ffab21 | ||
|
|
9c1bfbd5eb | ||
|
|
c38b9b7dc7 | ||
|
|
4791088106 | ||
|
|
b53d11ce79 | ||
|
|
00c3c2f773 | ||
|
|
6c0a12148b | ||
|
|
a32ccd82f3 | ||
|
|
f326334147 | ||
|
|
b1a55b1331 | ||
|
|
170b0d6b3f | ||
|
|
433636a06f | ||
|
|
9555817901 | ||
|
|
e54deacf1a | ||
|
|
b6f53cae7a | ||
|
|
f953a9cf23 | ||
|
|
117549bf70 | ||
|
|
4287160254 |
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
|
||||||
97
.travis.yml
97
.travis.yml
@@ -12,8 +12,39 @@ matrix:
|
|||||||
- 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"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-6
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-7"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-7
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
- libboost-all-dev
|
- libboost-all-dev
|
||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
@@ -26,8 +57,66 @@ 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"
|
||||||
|
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"
|
||||||
|
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"
|
||||||
|
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"
|
||||||
|
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"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
- libboost-all-dev
|
- libboost-all-dev
|
||||||
- os: osx
|
- os: osx
|
||||||
language: cpp
|
language: cpp
|
||||||
|
|||||||
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;
|
|
||||||
```
|
|
||||||
@@ -1,17 +1,35 @@
|
|||||||
set(TEST_NAMES
|
set(TEST_NAMES
|
||||||
test_traits
|
|
||||||
test_utility
|
|
||||||
test_value
|
|
||||||
test_to_toml
|
|
||||||
test_from_toml
|
|
||||||
test_get
|
|
||||||
test_get_or
|
|
||||||
test_value_operator
|
|
||||||
test_datetime
|
test_datetime
|
||||||
test_acceptor
|
test_utility
|
||||||
test_parser
|
test_result
|
||||||
|
test_traits
|
||||||
|
test_value
|
||||||
|
test_lex_boolean
|
||||||
|
test_lex_integer
|
||||||
|
test_lex_floating
|
||||||
|
test_lex_datetime
|
||||||
|
test_lex_string
|
||||||
|
test_lex_key_comment
|
||||||
|
test_parse_boolean
|
||||||
|
test_parse_integer
|
||||||
|
test_parse_floating
|
||||||
|
test_parse_string
|
||||||
|
test_parse_datetime
|
||||||
|
test_parse_array
|
||||||
|
test_parse_table
|
||||||
|
test_parse_inline_table
|
||||||
|
test_parse_key
|
||||||
|
test_parse_table_key
|
||||||
|
test_literals
|
||||||
|
test_get
|
||||||
|
test_get_related_func
|
||||||
|
test_from_toml
|
||||||
test_parse_file
|
test_parse_file
|
||||||
|
test_serialize_file
|
||||||
test_parse_unicode
|
test_parse_unicode
|
||||||
|
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)
|
||||||
@@ -81,3 +99,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,592 +0,0 @@
|
|||||||
#define BOOST_TEST_MODULE "test_acceptor"
|
|
||||||
#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/acceptor.hpp>
|
|
||||||
#include <locale>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_conditions)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
const std::string tmp(" ");
|
|
||||||
const std::string dummy("dummy");
|
|
||||||
BOOST_CHECK(toml::is_space<char>::invoke(tmp.begin(), tmp.end()) == tmp.end());
|
|
||||||
BOOST_CHECK(toml::is_space<char>::invoke(dummy.begin(), dummy.end()) == dummy.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string tmp("\t");
|
|
||||||
const std::string dummy("dummy");
|
|
||||||
BOOST_CHECK(toml::is_tab<char>::invoke(tmp.begin(), tmp.end()) == tmp.end());
|
|
||||||
BOOST_CHECK(toml::is_tab<char>::invoke(dummy.begin(), dummy.end()) == dummy.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
for(int i=0; i<10; ++i)
|
|
||||||
{
|
|
||||||
const std::string tmp = std::to_string(i);
|
|
||||||
const std::string dummy("dummy");
|
|
||||||
BOOST_CHECK(toml::is_number<char>::invoke(tmp.begin(), tmp.end()) == tmp.end());
|
|
||||||
BOOST_CHECK(toml::is_number<char>::invoke(dummy.begin(), dummy.end()) == dummy.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
for(char c='a'; c <= 'z'; ++c)
|
|
||||||
{
|
|
||||||
const std::string tmp(1, c);
|
|
||||||
const std::string dummy(1, std::toupper(c));
|
|
||||||
BOOST_CHECK(toml::is_lowercase<char>::invoke(tmp.begin(), tmp.end()) == tmp.end());
|
|
||||||
BOOST_CHECK(toml::is_lowercase<char>::invoke(dummy.begin(), dummy.end()) == dummy.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
for(char c='A'; c <= 'Z'; ++c)
|
|
||||||
{
|
|
||||||
const std::string tmp(1, c);
|
|
||||||
const std::string dummy(1, std::tolower(c));
|
|
||||||
BOOST_CHECK(toml::is_uppercase<char>::invoke(tmp.begin(), tmp.end()) == tmp.end());
|
|
||||||
BOOST_CHECK(toml::is_uppercase<char>::invoke(dummy.begin(), dummy.end()) == dummy.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string tmp(" ");
|
|
||||||
const std::string dummy("a");
|
|
||||||
BOOST_CHECK(toml::is_whitespace<char>::invoke(tmp.begin(), tmp.end()) == tmp.end());
|
|
||||||
BOOST_CHECK(toml::is_whitespace<char>::invoke(dummy.begin(), dummy.end()) == dummy.begin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string tmp("\t");
|
|
||||||
const std::string dummy("a");
|
|
||||||
BOOST_CHECK(toml::is_whitespace<char>::invoke(tmp.begin(), tmp.end()) == tmp.end());
|
|
||||||
BOOST_CHECK(toml::is_whitespace<char>::invoke(dummy.begin(), dummy.end()) == dummy.begin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string tmp("hoge1-piyo2_fuga3");
|
|
||||||
const std::string dummy(" \t");
|
|
||||||
BOOST_CHECK(toml::is_barekey<char>::invoke(tmp.begin(), tmp.end()) != tmp.begin());
|
|
||||||
BOOST_CHECK(toml::is_barekey<char>::invoke(dummy.begin(), dummy.end()) == dummy.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_basic_inline_string)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_basic_inline_string<char>;
|
|
||||||
{
|
|
||||||
const std::string simple("\"hoge1-piyo2_fuga3\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simple.cbegin(), simple.cend()) == simple.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string quote("\"hoge1-\\\"piyo2\\\"_fuga3\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quote.cbegin(), quote.cend()) == quote.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string escape("\"I'm a string. \\\"You can quote me\\\". Name\\tJos\\u00E9\\nLocation\\tSF.\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(escape.cbegin(), escape.cend()) == escape.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string empty("\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(empty.cbegin(), empty.cend()) == empty.cend());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string newline("\"newline\r\nhoge\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(newline.cbegin(), newline.cend()) == newline.cbegin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string invalid_escape("\"foo\\abar\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(invalid_escape.cbegin(), invalid_escape.cend()) == invalid_escape.cbegin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string invalid_character("\"foo\10bar\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(invalid_character.cbegin(), invalid_character.cend()) == invalid_character.cbegin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string multi("\"\"\"multiline\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(multi.cbegin(), multi.cend()) == multi.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_basic_multiline_string)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_basic_multiline_string<char>;
|
|
||||||
{
|
|
||||||
const std::string simple("\"\"\"foobar\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simple.cbegin(), simple.cend()) == simple.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string quote("\"\"\"hoge1-\"piyo2\"_fuga3\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quote.cbegin(), quote.cend()) == quote.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string newline("\"\"\"hoge1-\npiyo2_\r\nfuga3\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(newline.cbegin(), newline.cend()) == newline.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string escape("\"\"\"I'm a string. \"You can quote me\". Name\\tJos\\u00E9\\nLocation\\tSF.\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(escape.cbegin(), escape.cend()) == escape.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string empty("\"\"\"\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(empty.cbegin(), empty.cend()) == empty.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string ending_backslash("\"\"\"hoge\\\n piyo\\\n\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(ending_backslash.cbegin(), ending_backslash.cend()) == ending_backslash.cend());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string invalid_escape("\"\"\"foo\\abar\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(invalid_escape.cbegin(), invalid_escape.cend()) == invalid_escape.cbegin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string invalid_character("\"\"\"foo\10bar\"\"\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(invalid_character.cbegin(), invalid_character.cend()) == invalid_character.cbegin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string single("\"singleline\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(single.cbegin(), single.cend()) == single.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_literal_inline_string)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_literal_inline_string<char>;
|
|
||||||
{
|
|
||||||
const std::string simple("'foobar'");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simple.cbegin(), simple.cend()) == simple.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string nonescape("'C:\\Users\\nodejs\\templates'");
|
|
||||||
BOOST_CHECK(is_valid::invoke(nonescape.cbegin(), nonescape.cend()) == nonescape.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string empty("''");
|
|
||||||
BOOST_CHECK(is_valid::invoke(empty.cbegin(), empty.cend()) == empty.cend());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string quote("'hoge1-'piyo2'_fuga3'");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quote.cbegin(), quote.cend()) == quote.cbegin() + 8);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string newline("'hoge1-\npiyo2_\r\nfuga3'");
|
|
||||||
BOOST_CHECK(is_valid::invoke(newline.cbegin(), newline.cend()) == newline.cbegin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string invalid_character("'foo\10bar'");
|
|
||||||
BOOST_CHECK(is_valid::invoke(invalid_character.cbegin(), invalid_character.cend()) == invalid_character.cbegin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string multi("'''multiline'''");
|
|
||||||
BOOST_CHECK(is_valid::invoke(multi.cbegin(), multi.cend()) == multi.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_literal_multiline_string)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_literal_multiline_string<char>;
|
|
||||||
{
|
|
||||||
const std::string simple("'''foobar'''");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simple.cbegin(), simple.cend()) == simple.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string quote("'''hoge1-'piyo2'_fuga3'''");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quote.cbegin(), quote.cend()) == quote.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string nonescape("'''C:\\Users\\nodejs\\templates'''");
|
|
||||||
BOOST_CHECK(is_valid::invoke(nonescape.cbegin(), nonescape.cend()) == nonescape.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string newline("'''hoge1-\npiyo2_\r\nfuga3'''");
|
|
||||||
BOOST_CHECK(is_valid::invoke(newline.cbegin(), newline.cend()) == newline.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string empty("''''''");
|
|
||||||
BOOST_CHECK(is_valid::invoke(empty.cbegin(), empty.cend()) == empty.cend());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string invalid_character("'''foo\10bar'''");
|
|
||||||
BOOST_CHECK(is_valid::invoke(invalid_character.cbegin(), invalid_character.cend()) == invalid_character.cbegin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string single("'singleline'");
|
|
||||||
BOOST_CHECK(is_valid::invoke(single.cbegin(), single.cend()) == single.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_integer)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_integer<char>;
|
|
||||||
{
|
|
||||||
const std::string simple("1");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simple.cbegin(), simple.cend()) == simple.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string psign("+1234");
|
|
||||||
BOOST_CHECK(is_valid::invoke(psign.cbegin(), psign.cend()) == psign.cend());
|
|
||||||
const std::string nsign("-1234");
|
|
||||||
BOOST_CHECK(is_valid::invoke(nsign.cbegin(), nsign.cend()) == nsign.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string zero("0");
|
|
||||||
BOOST_CHECK(is_valid::invoke(zero.cbegin(), zero.cend()) == zero.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string us("1_2_3_4_5");
|
|
||||||
BOOST_CHECK(is_valid::invoke(us.cbegin(), us.cend()) == us.cend());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string f("12.34");
|
|
||||||
BOOST_CHECK(is_valid::invoke(f.cbegin(), f.cend()) == f.cbegin()+2);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string f("12e34");
|
|
||||||
BOOST_CHECK(is_valid::invoke(f.cbegin(), f.cend()) == f.cbegin()+2);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string ascii("1234a");
|
|
||||||
BOOST_CHECK(is_valid::invoke(ascii.cbegin(), ascii.cend()) == ascii.cbegin()+4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_float)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_float<char>;
|
|
||||||
{
|
|
||||||
const std::string simplef("1.0");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simplef.cbegin(), simplef.cend()) == simplef.cend());
|
|
||||||
const std::string simplee("1e0");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simplee.cbegin(), simplee.cend()) == simplee.cend());
|
|
||||||
const std::string both("6.626e-34");
|
|
||||||
BOOST_CHECK(is_valid::invoke(both.cbegin(), both.cend()) == both.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string psign("+1.0");
|
|
||||||
BOOST_CHECK(is_valid::invoke(psign.cbegin(), psign.cend()) == psign.cend());
|
|
||||||
const std::string nsign("-1.0");
|
|
||||||
BOOST_CHECK(is_valid::invoke(nsign.cbegin(), nsign.cend()) == nsign.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string psmall("+0.001");
|
|
||||||
BOOST_CHECK(is_valid::invoke(psmall.cbegin(), psmall.cend()) == psmall.cend());
|
|
||||||
const std::string nsmall("-0.001");
|
|
||||||
BOOST_CHECK(is_valid::invoke(nsmall.cbegin(), nsmall.cend()) == nsmall.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string zero("0.0");
|
|
||||||
BOOST_CHECK(is_valid::invoke(zero.cbegin(), zero.cend()) == zero.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string us("9_224_617.445_991_228_313");
|
|
||||||
BOOST_CHECK(is_valid::invoke(us.cbegin(), us.cend()) == us.cend());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_boolean)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_boolean<char>;
|
|
||||||
{
|
|
||||||
const std::string t("true");
|
|
||||||
BOOST_CHECK(is_valid::invoke(t.cbegin(), t.cend()) == t.cend());
|
|
||||||
const std::string f("false");
|
|
||||||
BOOST_CHECK(is_valid::invoke(f.cbegin(), f.cend()) == f.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string t("True");
|
|
||||||
BOOST_CHECK(is_valid::invoke(t.cbegin(), t.cend()) == t.cbegin());
|
|
||||||
const std::string f("False");
|
|
||||||
BOOST_CHECK(is_valid::invoke(f.cbegin(), f.cend()) == f.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_localtime)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_local_time<char>;
|
|
||||||
{
|
|
||||||
const std::string t("07:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(t.cbegin(), t.cend()) == t.cend());
|
|
||||||
const std::string tf("07:32:00.0000");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tf.cbegin(), tf.cend()) == tf.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string d("1907-32-00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(d.cbegin(), d.cend()) == d.cbegin());
|
|
||||||
const std::string f("1907:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(f.cbegin(), f.cend()) == f.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_localdate)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_local_date<char>;
|
|
||||||
{
|
|
||||||
const std::string d("1907-32-00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(d.cbegin(), d.cend()) == d.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string t("07:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(t.cbegin(), t.cend()) == t.cbegin());
|
|
||||||
const std::string f("1907:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(f.cbegin(),f.cend()) == f.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_localdatetime)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_local_date_time<char>;
|
|
||||||
{
|
|
||||||
const std::string dt("1907-32-00T07:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dt.cbegin(), dt.cend()) == dt.cend());
|
|
||||||
const std::string dtf("1907-32-00T07:32:00.0000");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dtf.cbegin(), dtf.cend()) == dtf.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string d("1907-32-00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(d.cbegin(), d.cend()) == d.cbegin());
|
|
||||||
const std::string t("07:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(t.cbegin(), t.cend()) == t.cbegin());
|
|
||||||
const std::string f("1907-32-00 07:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(f.cbegin(), f.cend()) == f.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_offsetdatetime)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_offset_date_time<char>;
|
|
||||||
{
|
|
||||||
const std::string dtZ("1907-32-00T07:32:00Z");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dtZ.cbegin(), dtZ.cend()) == dtZ.cend());
|
|
||||||
const std::string dtfZ("1907-32-00T07:32:00.0000Z");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dtfZ.cbegin(), dtfZ.cend()) == dtfZ.cend());
|
|
||||||
const std::string dtp("1907-32-00T07:32:00+12:34");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dtp.cbegin(), dtp.cend()) == dtp.cend());
|
|
||||||
const std::string dtfp("1907-32-00T07:32:00.0000+12:34");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dtfp.cbegin(), dtfp.cend()) == dtfp.cend());
|
|
||||||
const std::string dtn("1907-32-00T07:32:00-12:34");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dtn.cbegin(), dtn.cend()) == dtn.cend());
|
|
||||||
const std::string dtfn("1907-32-00T07:32:00.0000-12:34");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dtfn.cbegin(), dtfn.cend()) == dtfn.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string d("1907-32-00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(d.cbegin(), d.cend()) == d.cbegin());
|
|
||||||
const std::string t("07:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(t.cbegin(), t.cend()) == t.cbegin());
|
|
||||||
const std::string l("1907-32-00T07:32:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(l.cbegin(), l.cend()) == l.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_array)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_array<char>;
|
|
||||||
{
|
|
||||||
const std::string arr0("[]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr0.cbegin(), arr0.cend()) == arr0.cend());
|
|
||||||
const std::string arr1("[1,2,3]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr1.cbegin(), arr1.cend()) == arr1.cend());
|
|
||||||
const std::string arr2("[ 1,2,3 ]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr2.cbegin(), arr2.cend()) == arr2.cend());
|
|
||||||
const std::string arr3("[ 1, 2, 3 ]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr3.cbegin(), arr3.cend()) == arr3.cend());
|
|
||||||
const std::string arr4("[ 1, 2, 3, ]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr4.cbegin(), arr4.cend()) == arr4.cend());
|
|
||||||
const std::string arr5("[ 1, 2, 3,]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr5.cbegin(), arr5.cend()) == arr5.cend());
|
|
||||||
const std::string arr6("[ 1 , 2 , 3 ,]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr6.cbegin(), arr6.cend()) == arr6.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string arr1("[\"red\", \"yellow\", \"green\"]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr1.cbegin(), arr1.cend()) == arr1.cend());
|
|
||||||
const std::string arr2("[\"]\", \"#\", \" \"]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr2.cbegin(), arr2.cend()) == arr2.cend());
|
|
||||||
const std::string arr3("[[1, 2, 3], ['a', 'b', 'c']]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr3.cbegin(), arr3.cend()) == arr3.cend());
|
|
||||||
const std::string arr4("[{hoge = 1}, {piyo = 'a'}, {fuga = [1,2,3]}]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr4.cbegin(), arr4.cend()) == arr4.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string arr1("[1,\n2,#comment\n3]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr1.cbegin(), arr1.cend()) == arr1.cend());
|
|
||||||
const std::string arr2("[#c\n1,\n2,#comment\r\n3]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(arr2.cbegin(), arr2.cend()) == arr2.cend());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string invalid("[1, 3.14, 'string']");
|
|
||||||
BOOST_CHECK(is_valid::invoke(invalid.cbegin(), invalid.cend()) == invalid.cbegin());
|
|
||||||
const std::string valid("[[1,2,3], [3.14, 2.71, 1.414], ['foo', 'bar']]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(valid.cbegin(), valid.cend()) == valid.cend());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_inline_table)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_inline_table<char>;
|
|
||||||
{
|
|
||||||
const std::string tab0("{}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab0.cbegin(), tab0.cend()) == tab0.cend());
|
|
||||||
const std::string tab1("{hoge=1,piyo=2,fuga=3}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab1.cbegin(), tab1.cend()) == tab1.cend());
|
|
||||||
const std::string tab2("{hoge=1, piyo=2, fuga=3}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab2.cbegin(), tab2.cend()) == tab2.cend());
|
|
||||||
const std::string tab3("{ hoge=1, piyo=2, fuga=3 }");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab3.cbegin(), tab3.cend()) == tab3.cend());
|
|
||||||
const std::string tab4("{ hoge = 1, piyo = 2, fuga = 3 }");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab4.cbegin(), tab4.cend()) == tab4.cend());
|
|
||||||
const std::string tab5("{hoge = 1, piyo = 2, fuga = 3}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab5.cbegin(), tab5.cend()) == tab5.cend());
|
|
||||||
const std::string tab6("{hoge = 1, piyo = 2, fuga = 3,}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab6.cbegin(), tab6.cend()) == tab6.cend());
|
|
||||||
const std::string tab7("{hoge = 1, piyo = 2, fuga = 3, }");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab7.cbegin(), tab7.cend()) == tab7.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string tab0("{hoge = 1, piyo = 2.0}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab0.cbegin(), tab0.cend()) == tab0.cend());
|
|
||||||
const std::string tab1("{hoge = [1,2,3], piyo = {fuga = {}}}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab1.cbegin(), tab1.cend()) == tab1.cend());
|
|
||||||
const std::string tab2("{hoge = \"}\", piyo = \"#\"}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab2.cbegin(), tab2.cend()) == tab2.cend());
|
|
||||||
const std::string tab3("{b=true, i=1, f=2.0, d=1907-03-02T07:32:00, s='str', a=[1,2,3], t={foo=1}}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab3.cbegin(), tab3.cend()) == tab3.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string tab0("{hoge = \"}\",\n piyo = \"#\"}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(tab0.cbegin(), tab0.cend()) == tab0.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_table_definition)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_table_definition<char>;
|
|
||||||
{
|
|
||||||
const std::string simple("[hoge]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simple.cbegin(), simple.cend()) == simple.cend());
|
|
||||||
const std::string dotted("[hoge.piyo.fuga]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dotted.cbegin(), dotted.cend()) == dotted.cend());
|
|
||||||
const std::string spaced_dotted("[hoge . piyo .fuga. foo]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(spaced_dotted.cbegin(), spaced_dotted.cend()) == spaced_dotted.cend());
|
|
||||||
const std::string quoted("[\"hoge\"]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quoted.cbegin(), quoted.cend()) == quoted.cend());
|
|
||||||
const std::string quoted_dot("[\"hoge\".'piyo'.fuga]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quoted_dot.cbegin(), quoted_dot.cend()) == quoted_dot.cend());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_array_of_table_definition)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_array_of_table_definition<char>;
|
|
||||||
{
|
|
||||||
const std::string simple("[[hoge]]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simple.cbegin(), simple.cend()) == simple.cend());
|
|
||||||
const std::string dotted("[[hoge.piyo.fuga]]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(dotted.cbegin(), dotted.cend()) == dotted.cend());
|
|
||||||
const std::string spaced_dotted("[[hoge . piyo .fuga. foo]]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(spaced_dotted.cbegin(), spaced_dotted.cend()) == spaced_dotted.cend());
|
|
||||||
const std::string quoted("[[\"hoge\"]]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quoted.cbegin(), quoted.cend()) == quoted.cend());
|
|
||||||
const std::string quoted_dot("[[\"hoge\".'piyo'.fuga]]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quoted_dot.cbegin(), quoted_dot.cend()) == quoted_dot.cend());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_key)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_key<char>;
|
|
||||||
{
|
|
||||||
const std::string simple("foobar");
|
|
||||||
BOOST_CHECK(is_valid::invoke(simple.cbegin(), simple.cend()) == simple.cend());
|
|
||||||
const std::string quoted("\"foo#bar.baz\\n\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(quoted.cbegin(), quoted.cend()) == quoted.cend());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_value<char>;
|
|
||||||
{
|
|
||||||
const std::string boolean("true");
|
|
||||||
BOOST_CHECK(is_valid::invoke(boolean.cbegin(), boolean.cend()) == boolean.cend());
|
|
||||||
const std::string integer("-42");
|
|
||||||
BOOST_CHECK(is_valid::invoke(integer.cbegin(), integer.cend()) == integer.cend());
|
|
||||||
const std::string floating("-42e0");
|
|
||||||
BOOST_CHECK(is_valid::invoke(floating.cbegin(), floating.cend()) == floating.cend());
|
|
||||||
const std::string string("\"string\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(string.cbegin(), string.cend()) == string.cend());
|
|
||||||
const std::string datetime("1901-01-01T00:00:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(datetime.cbegin(), datetime.cend()) == datetime.cend());
|
|
||||||
const std::string array("[1,2,3]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(array.cbegin(), array.cend()) == array.cend());
|
|
||||||
const std::string table("{foo=1,bar=2.0,baz='3'}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(table.cbegin(), table.cend()) == table.cend());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_key_value_pair)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_key_value_pair<char>;
|
|
||||||
{
|
|
||||||
const std::string kv("key=1");
|
|
||||||
BOOST_CHECK(is_valid::invoke(kv.cbegin(), kv.cend()) == kv.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string kv("key = 1");
|
|
||||||
BOOST_CHECK(is_valid::invoke(kv.cbegin(), kv.cend()) == kv.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string kv(" key = 1");
|
|
||||||
BOOST_CHECK(is_valid::invoke(kv.cbegin(), kv.cend()) == kv.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string kv(" key = 1 ");
|
|
||||||
BOOST_CHECK(is_valid::invoke(kv.cbegin(), kv.cend()) == kv.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string boolean("key = true");
|
|
||||||
BOOST_CHECK(is_valid::invoke(boolean.cbegin(), boolean.cend()) == boolean.cend());
|
|
||||||
const std::string integer("key = -42");
|
|
||||||
BOOST_CHECK(is_valid::invoke(integer.cbegin(), integer.cend()) == integer.cend());
|
|
||||||
const std::string floating("key = -42.0");
|
|
||||||
BOOST_CHECK(is_valid::invoke(floating.cbegin(), floating.cend()) == floating.cend());
|
|
||||||
const std::string string("key = \"string\"");
|
|
||||||
BOOST_CHECK(is_valid::invoke(string.cbegin(), string.cend()) == string.cend());
|
|
||||||
const std::string datetime("key = 1901-01-01T00:00:00");
|
|
||||||
BOOST_CHECK(is_valid::invoke(datetime.cbegin(), datetime.cend()) == datetime.cend());
|
|
||||||
const std::string array("key = [1,2,3]");
|
|
||||||
BOOST_CHECK(is_valid::invoke(array.cbegin(), array.cend()) == array.cend());
|
|
||||||
const std::string table("key = {foo=1,bar=2.0,baz='3'}");
|
|
||||||
BOOST_CHECK(is_valid::invoke(table.cbegin(), table.cend()) == table.cend());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_empty_line)
|
|
||||||
{
|
|
||||||
using is_valid = toml::is_empty_line<char>;
|
|
||||||
{
|
|
||||||
const std::string empty("\n");
|
|
||||||
BOOST_CHECK(is_valid::invoke(empty.cbegin(), empty.cend()) == empty.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string empty(" \n");
|
|
||||||
BOOST_CHECK(is_valid::invoke(empty.cbegin(), empty.cend()) == empty.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string empty("#comment\n");
|
|
||||||
BOOST_CHECK(is_valid::invoke(empty.cbegin(), empty.cend()) == empty.cend());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string empty(" #comment\n");
|
|
||||||
BOOST_CHECK(is_valid::invoke(empty.cbegin(), empty.cend()) == empty.cend());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,26 +5,117 @@
|
|||||||
#define BOOST_TEST_NO_LIB
|
#define BOOST_TEST_NO_LIB
|
||||||
#include <boost/test/included/unit_test.hpp>
|
#include <boost/test/included/unit_test.hpp>
|
||||||
#endif
|
#endif
|
||||||
#include <toml.hpp>
|
#include <toml/datetime.hpp>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_datetime_convertible)
|
BOOST_AUTO_TEST_CASE(test_local_date)
|
||||||
{
|
{
|
||||||
const auto now = std::chrono::system_clock::now();
|
const toml::local_date date(2018, toml::month_t::Jan, 1);
|
||||||
toml::Datetime d1(now);
|
const toml::local_date date1(date);
|
||||||
const std::chrono::system_clock::time_point cvt(d1);
|
BOOST_CHECK_EQUAL(date, date1);
|
||||||
toml::Datetime d2(cvt);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(d1, d2);
|
const std::chrono::system_clock::time_point tp(date);
|
||||||
|
const toml::local_date date2(tp);
|
||||||
|
BOOST_CHECK_EQUAL(date, date2);
|
||||||
|
|
||||||
const auto time = std::chrono::system_clock::to_time_t(now);
|
const toml::local_date date3(2017, toml::month_t::Dec, 31);
|
||||||
toml::Datetime d3(time);
|
BOOST_CHECK(date > date3);
|
||||||
toml::Datetime d4(std::chrono::system_clock::from_time_t(time));
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(d3, d4);
|
std::ostringstream oss;
|
||||||
|
oss << date;
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01"));
|
||||||
const auto later = std::chrono::system_clock::now();
|
}
|
||||||
toml::Datetime d5(later);
|
|
||||||
BOOST_CHECK(d1 < d5);
|
BOOST_AUTO_TEST_CASE(test_local_time)
|
||||||
|
{
|
||||||
|
const toml::local_time time(12, 30, 45);
|
||||||
|
const toml::local_time time1(time);
|
||||||
|
BOOST_CHECK_EQUAL(time, time1);
|
||||||
|
|
||||||
|
const std::chrono::nanoseconds dur(time);
|
||||||
|
std::chrono::nanoseconds ns(0);
|
||||||
|
ns += std::chrono::hours (12);
|
||||||
|
ns += std::chrono::minutes(30);
|
||||||
|
ns += std::chrono::seconds(45);
|
||||||
|
BOOST_CHECK_EQUAL(dur.count(), ns.count());
|
||||||
|
|
||||||
|
const toml::local_time time3(12, 15, 45);
|
||||||
|
BOOST_CHECK(time > time3);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << time;
|
||||||
|
BOOST_CHECK_EQUAL(oss.str(), std::string("12:30:45"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::local_time time4(12, 30, 45, 123, 456);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << time4;
|
||||||
|
BOOST_CHECK_EQUAL(oss.str(), std::string("12:30:45.123456"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_time_offset)
|
||||||
|
{
|
||||||
|
const toml::time_offset time(9, 30);
|
||||||
|
const toml::time_offset time1(time);
|
||||||
|
BOOST_CHECK_EQUAL(time, time1);
|
||||||
|
|
||||||
|
const std::chrono::minutes dur(time);
|
||||||
|
std::chrono::minutes m(0);
|
||||||
|
m += std::chrono::hours (9);
|
||||||
|
m += std::chrono::minutes(30);
|
||||||
|
BOOST_CHECK_EQUAL(dur.count(), m.count());
|
||||||
|
|
||||||
|
const toml::time_offset time2(9, 0);
|
||||||
|
BOOST_CHECK(time2 < time);
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << time;
|
||||||
|
BOOST_CHECK_EQUAL(oss.str(), std::string("+09:30"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_local_datetime)
|
||||||
|
{
|
||||||
|
const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1),
|
||||||
|
toml::local_time(12, 30, 45));
|
||||||
|
const toml::local_datetime dt1(dt);
|
||||||
|
BOOST_CHECK_EQUAL(dt, dt1);
|
||||||
|
|
||||||
|
const std::chrono::system_clock::time_point tp(dt);
|
||||||
|
const toml::local_datetime dt2(tp);
|
||||||
|
BOOST_CHECK_EQUAL(dt, dt2);
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << dt;
|
||||||
|
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_offset_datetime)
|
||||||
|
{
|
||||||
|
const toml::offset_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1),
|
||||||
|
toml::local_time(12, 30, 45),
|
||||||
|
toml::time_offset(9, 30));
|
||||||
|
const toml::offset_datetime dt1(dt);
|
||||||
|
BOOST_CHECK_EQUAL(dt, dt1);
|
||||||
|
|
||||||
|
const std::chrono::system_clock::time_point tp1(dt);
|
||||||
|
const toml::offset_datetime dt2(tp1);
|
||||||
|
const std::chrono::system_clock::time_point tp2(dt2);
|
||||||
|
BOOST_CHECK(tp1 == tp2);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << dt;
|
||||||
|
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45+09:30"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::offset_datetime dt3(
|
||||||
|
toml::local_date(2018, toml::month_t::Jan, 1),
|
||||||
|
toml::local_time(12, 30, 45),
|
||||||
|
toml::time_offset(0, 0));
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << dt3;
|
||||||
|
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45Z"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
199
tests/test_error_detection.cpp
Normal file
199
tests/test_error_detection.cpp
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_error_detection"
|
||||||
|
#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_detect_empty_key)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string("= \"value\""));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_empty_key");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
// to see the error message
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_missing_value)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string("a ="));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_missing_value");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_too_many_value)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string("a = 1 = \"value\""));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_too_many_value");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"[table]\n"
|
||||||
|
"a = 42\n"
|
||||||
|
"[table]\n"
|
||||||
|
"b = 42\n"
|
||||||
|
));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_duplicate_table");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"[[table]]\n"
|
||||||
|
"a = 42\n"
|
||||||
|
"[table]\n"
|
||||||
|
"b = 42\n"
|
||||||
|
));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_conflict_array_table");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"[table]\n"
|
||||||
|
"a = 42\n"
|
||||||
|
"[[table]]\n"
|
||||||
|
"b = 42\n"
|
||||||
|
));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_conflict_table_array");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"a = 1\n"
|
||||||
|
"a = 2\n"
|
||||||
|
));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_duplicate_value");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"a.b = 1\n"
|
||||||
|
"a.b.c = 2\n"
|
||||||
|
));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_conflicting_value");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"a = [1, 1.0]\n"
|
||||||
|
));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_inhomogeneous_array");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
|
||||||
|
{
|
||||||
|
std::istringstream stream(std::string(
|
||||||
|
"a = [{b = 1}]\n"
|
||||||
|
"[[a]]\n"
|
||||||
|
"b = 2\n"
|
||||||
|
));
|
||||||
|
bool exception_thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::parse(stream, "test_detect_appending_array_of_table");
|
||||||
|
}
|
||||||
|
catch(const toml::syntax_error& syn)
|
||||||
|
{
|
||||||
|
std::cerr << syn.what() << std::endl;
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(exception_thrown);
|
||||||
|
}
|
||||||
|
|
||||||
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,161 +12,52 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_from_toml_exact)
|
BOOST_AUTO_TEST_CASE(test_from_toml)
|
||||||
{
|
{
|
||||||
toml::Boolean b(true);
|
toml::boolean b = false;
|
||||||
toml::Integer i(42);
|
toml::integer i = 0;
|
||||||
toml::Float f(3.14);
|
toml::floating f = 0.;
|
||||||
toml::String s("hoge");
|
toml::string s;
|
||||||
toml::Datetime d(std::chrono::system_clock::now());
|
toml::local_date dt;
|
||||||
toml::Array a;
|
toml::array a;
|
||||||
a.emplace_back(2);
|
toml::table t;
|
||||||
a.emplace_back(7);
|
{
|
||||||
a.emplace_back(1);
|
toml::value v(true);
|
||||||
a.emplace_back(8);
|
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
|
||||||
a.emplace_back(2);
|
BOOST_CHECK_EQUAL(b, true);
|
||||||
toml::Table t;
|
}
|
||||||
t.emplace("val1", true);
|
{
|
||||||
t.emplace("val2", 42);
|
toml::value v(42);
|
||||||
t.emplace("val3", 3.14);
|
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
|
||||||
t.emplace("val4", "piyo");
|
BOOST_CHECK_EQUAL(i, 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v(3.14);
|
||||||
|
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
|
||||||
|
BOOST_CHECK_EQUAL(f, 3.14);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v("foo");
|
||||||
|
|
||||||
toml::value v1(b);
|
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
|
||||||
toml::value v2(i);
|
BOOST_CHECK_EQUAL(s, "foo");
|
||||||
toml::value v3(f);
|
}
|
||||||
toml::value v4(s);
|
{
|
||||||
toml::value v5(d);
|
toml::value v(toml::local_date(2018, toml::month_t::Apr, 22));
|
||||||
toml::value v6(a);
|
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
|
||||||
toml::value v7(t);
|
BOOST_CHECK(dt == toml::local_date(2018, toml::month_t::Apr, 22));
|
||||||
|
}
|
||||||
toml::Boolean u1;
|
{
|
||||||
toml::Integer u2;
|
toml::array ref{toml::value(42), toml::value(54)};
|
||||||
toml::Float u3;
|
toml::value v(ref);
|
||||||
toml::String u4;
|
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
|
||||||
toml::Datetime u5;
|
BOOST_CHECK(ref == a);
|
||||||
toml::Array u6;
|
}
|
||||||
toml::Table u7;
|
{
|
||||||
|
toml::table ref{{"key1", 42}, {"key2", 3.14}};
|
||||||
toml::from_toml(u1, v1);
|
toml::value v(ref);
|
||||||
toml::from_toml(u2, v2);
|
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
|
||||||
toml::from_toml(u3, v3);
|
BOOST_CHECK(ref == t);
|
||||||
toml::from_toml(u4, v4);
|
}
|
||||||
toml::from_toml(u5, v5);
|
|
||||||
toml::from_toml(u6, v6);
|
|
||||||
toml::from_toml(u7, v7);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u1, b);
|
|
||||||
BOOST_CHECK_EQUAL(u2, i);
|
|
||||||
BOOST_CHECK_EQUAL(u3, f);
|
|
||||||
BOOST_CHECK_EQUAL(u4, s);
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(0).cast<toml::value_t::Integer>(), a.at(0).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(1).cast<toml::value_t::Integer>(), a.at(1).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(2).cast<toml::value_t::Integer>(), a.at(2).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(3).cast<toml::value_t::Integer>(), a.at(3).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(4).cast<toml::value_t::Integer>(), a.at(4).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val1").cast<toml::value_t::Boolean>(), true);
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val2").cast<toml::value_t::Integer>(), 42);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(u7.at("val3").cast<toml::value_t::Float>(),3.14, 1e-3);
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val4").cast<toml::value_t::String>(), "piyo");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_from_toml_cast)
|
|
||||||
{
|
|
||||||
toml::Integer i(42);
|
|
||||||
toml::Float f(3.14);
|
|
||||||
toml::Array a{2, 7, 1, 8, 2};
|
|
||||||
toml::Table t{{"val1", true}, {"val2", 42}, {"val3", 3.14}, {"val4", "piyo"}};
|
|
||||||
|
|
||||||
toml::value vi(i);
|
|
||||||
toml::value vf(f);
|
|
||||||
toml::value va(a);
|
|
||||||
toml::value vt(t);
|
|
||||||
|
|
||||||
int u1;
|
|
||||||
std::size_t u2;
|
|
||||||
float u3;
|
|
||||||
std::list<int> u4;
|
|
||||||
std::deque<std::size_t> u5;
|
|
||||||
std::array<long, 5> u6;
|
|
||||||
std::map<std::string, toml::value> u7;
|
|
||||||
|
|
||||||
std::list<int> expect_list{2,7,1,8,2};
|
|
||||||
std::deque<std::size_t> expect_deque{2,7,1,8,2};
|
|
||||||
std::array<long, 5> expect_array{{2,7,1,8,2}};
|
|
||||||
|
|
||||||
toml::from_toml(u1, vi);
|
|
||||||
toml::from_toml(u2, vi);
|
|
||||||
toml::from_toml(u3, vf);
|
|
||||||
toml::from_toml(u4, va);
|
|
||||||
toml::from_toml(u5, va);
|
|
||||||
toml::from_toml(u6, va);
|
|
||||||
toml::from_toml(u7, vt);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u1, 42);
|
|
||||||
BOOST_CHECK_EQUAL(u2, 42ul);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(u3, 3.14, 1e-3);
|
|
||||||
|
|
||||||
const bool same_list = (u4 == expect_list);
|
|
||||||
const bool same_deque = (u5 == expect_deque);
|
|
||||||
const bool same_array = (u6 == expect_array);
|
|
||||||
BOOST_CHECK(same_list);
|
|
||||||
BOOST_CHECK(same_deque);
|
|
||||||
BOOST_CHECK(same_array);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u7["val1"].cast<toml::value_t::Boolean>(), true);
|
|
||||||
BOOST_CHECK_EQUAL(u7["val2"].cast<toml::value_t::Integer>(), 42);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(u7["val3"].cast<toml::value_t::Float>(), 3.14, 1e-3);
|
|
||||||
BOOST_CHECK_EQUAL(u7["val4"].cast<toml::value_t::String >(), "piyo");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_from_toml_tie)
|
|
||||||
{
|
|
||||||
toml::Boolean b(42);
|
|
||||||
toml::Integer i(42);
|
|
||||||
toml::Float f(3.14);
|
|
||||||
toml::Array a;
|
|
||||||
a.emplace_back(2);
|
|
||||||
a.emplace_back(7);
|
|
||||||
a.emplace_back(1);
|
|
||||||
a.emplace_back(8);
|
|
||||||
a.emplace_back(2);
|
|
||||||
toml::Table t;
|
|
||||||
t.emplace("val1", true);
|
|
||||||
t.emplace("val2", 42);
|
|
||||||
t.emplace("val3", 3.14);
|
|
||||||
t.emplace("val4", "piyo");
|
|
||||||
|
|
||||||
toml::value vb(b);
|
|
||||||
toml::value vi(i);
|
|
||||||
toml::value vf(f);
|
|
||||||
toml::value va(a);
|
|
||||||
toml::value vt(t);
|
|
||||||
|
|
||||||
bool ub;
|
|
||||||
int ui;
|
|
||||||
float uf;
|
|
||||||
std::deque<int> ua;
|
|
||||||
std::map<std::string, toml::value> ut;
|
|
||||||
|
|
||||||
toml::from_toml(std::tie(ub, ui, uf, ua, ut), vb);
|
|
||||||
toml::from_toml(std::tie(ub, ui, uf, ua, ut), vi);
|
|
||||||
toml::from_toml(std::tie(ub, ui, uf, ua, ut), vf);
|
|
||||||
toml::from_toml(std::tie(ub, ui, uf, ua, ut), va);
|
|
||||||
toml::from_toml(std::tie(ub, ui, uf, ua, ut), va);
|
|
||||||
toml::from_toml(std::tie(ub, ui, uf, ua, ut), vt);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(ub, true);
|
|
||||||
BOOST_CHECK_EQUAL(ui, 42);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(uf, 3.14, 1e-3);
|
|
||||||
BOOST_CHECK_EQUAL(ua.at(0), 2);
|
|
||||||
BOOST_CHECK_EQUAL(ua.at(1), 7);
|
|
||||||
BOOST_CHECK_EQUAL(ua.at(2), 1);
|
|
||||||
BOOST_CHECK_EQUAL(ua.at(3), 8);
|
|
||||||
BOOST_CHECK_EQUAL(ua.at(4), 2);
|
|
||||||
BOOST_CHECK_EQUAL(ut["val1"].cast<toml::value_t::Boolean>(), true);
|
|
||||||
BOOST_CHECK_EQUAL(ut["val2"].cast<toml::value_t::Integer>(), 42);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(ut["val3"].cast<toml::value_t::Float>(), 3.14, 1e-3);
|
|
||||||
BOOST_CHECK_EQUAL(ut["val4"].cast<toml::value_t::String >(), "piyo");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
#define BOOST_TEST_NO_LIB
|
#define BOOST_TEST_NO_LIB
|
||||||
#include <boost/test/included/unit_test.hpp>
|
#include <boost/test/included/unit_test.hpp>
|
||||||
#endif
|
#endif
|
||||||
#include <toml.hpp>
|
#include <toml/value.hpp>
|
||||||
|
#include <toml/get.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <list>
|
#include <list>
|
||||||
@@ -15,98 +16,358 @@
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_exact)
|
BOOST_AUTO_TEST_CASE(test_get_exact)
|
||||||
{
|
{
|
||||||
toml::Boolean b(true);
|
|
||||||
toml::Integer i(42);
|
|
||||||
toml::Float f(3.14);
|
|
||||||
toml::String s("hoge");
|
|
||||||
toml::Array a;
|
|
||||||
a.emplace_back(2);
|
|
||||||
a.emplace_back(7);
|
|
||||||
a.emplace_back(1);
|
|
||||||
a.emplace_back(8);
|
|
||||||
a.emplace_back(2);
|
|
||||||
toml::Table t;
|
|
||||||
t.emplace("val1", true);
|
|
||||||
t.emplace("val2", 42);
|
|
||||||
t.emplace("val3", 3.14);
|
|
||||||
t.emplace("val4", "piyo");
|
|
||||||
|
|
||||||
toml::value v1(b);
|
|
||||||
toml::value v2(i);
|
|
||||||
toml::value v3(f);
|
|
||||||
toml::value v4(s);
|
|
||||||
toml::value v6(a);
|
|
||||||
toml::value v7(t);
|
|
||||||
|
|
||||||
toml::Boolean u1 = toml::get<toml::Boolean >(v1);
|
|
||||||
toml::Integer u2 = toml::get<toml::Integer >(v2);
|
|
||||||
toml::Float u3 = toml::get<toml::Float >(v3);
|
|
||||||
toml::String u4 = toml::get<toml::String >(v4);
|
|
||||||
toml::Array u6 = toml::get<toml::Array >(v6);
|
|
||||||
toml::Table u7 = toml::get<toml::Table >(v7);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u1, b);
|
|
||||||
BOOST_CHECK_EQUAL(u2, i);
|
|
||||||
BOOST_CHECK_EQUAL(u3, f);
|
|
||||||
BOOST_CHECK_EQUAL(u4, s);
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(0).cast<toml::value_t::Integer>(), a.at(0).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(1).cast<toml::value_t::Integer>(), a.at(1).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(2).cast<toml::value_t::Integer>(), a.at(2).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(3).cast<toml::value_t::Integer>(), a.at(3).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at(4).cast<toml::value_t::Integer>(), a.at(4).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val1").cast<toml::value_t::Boolean>(), true);
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val2").cast<toml::value_t::Integer>(), 42);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(u7.at("val3").cast<toml::value_t::Float>(),3.14, 1e-3);
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val4").cast<toml::value_t::String>(), "piyo");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_cast)
|
|
||||||
{
|
{
|
||||||
toml::Integer i(42);
|
toml::value v(true);
|
||||||
toml::Float f(3.14);
|
BOOST_CHECK_EQUAL(true, toml::get<toml::boolean>(v));
|
||||||
toml::String s("hoge");
|
|
||||||
toml::Datetime d(std::chrono::system_clock::now());
|
|
||||||
toml::Array a;
|
|
||||||
a.emplace_back(2);
|
|
||||||
a.emplace_back(7);
|
|
||||||
a.emplace_back(1);
|
|
||||||
a.emplace_back(8);
|
|
||||||
a.emplace_back(2);
|
|
||||||
toml::Table t;
|
|
||||||
t.emplace("val1", true);
|
|
||||||
t.emplace("val2", 42);
|
|
||||||
t.emplace("val3", 3.14);
|
|
||||||
t.emplace("val4", "piyo");
|
|
||||||
|
|
||||||
toml::value v2(i);
|
toml::get<toml::boolean>(v) = false;
|
||||||
toml::value v3(f);
|
BOOST_CHECK_EQUAL(false, toml::get<toml::boolean>(v));
|
||||||
toml::value v4(s);
|
|
||||||
toml::value v5(d);
|
|
||||||
toml::value v6(a);
|
|
||||||
toml::value v7(t);
|
|
||||||
|
|
||||||
const auto u2 = toml::get<std::size_t>(v2);
|
|
||||||
const auto u3 = toml::get<float>(v3);
|
|
||||||
const auto u4 = toml::get<std::deque<int>>(v6);
|
|
||||||
const auto u5 = toml::get<std::list<int> >(v6);
|
|
||||||
const auto u6 = toml::get<std::array<int,5>>(v6);
|
|
||||||
std::map<std::string, toml::value> u7 = toml::get<std::map<std::string, toml::value>>(v7);
|
|
||||||
|
|
||||||
std::deque<int> r4{2,7,1,8,2};
|
|
||||||
std::list<int> r5{2,7,1,8,2};
|
|
||||||
std::array<int, 5> r6{{2,7,1,8,2}};
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u2, 42ul);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(u3, 3.14, 1e-3);
|
|
||||||
const bool dq = r4 == u4;
|
|
||||||
const bool ls = r5 == u5;
|
|
||||||
const bool ar = r6 == u6;
|
|
||||||
BOOST_CHECK(dq);
|
|
||||||
BOOST_CHECK(ls);
|
|
||||||
BOOST_CHECK(ar);
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val1").cast<toml::value_t::Boolean>(), true);
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val2").cast<toml::value_t::Integer>(), 42);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(u7.at("val3").cast<toml::value_t::Float>(),3.14, 1e-3);
|
|
||||||
BOOST_CHECK_EQUAL(u7.at("val4").cast<toml::value_t::String>(), "piyo");
|
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
toml::value v(42);
|
||||||
|
BOOST_CHECK_EQUAL(toml::integer(42), toml::get<toml::integer>(v));
|
||||||
|
|
||||||
|
toml::get<toml::integer>(v) = 54;
|
||||||
|
BOOST_CHECK_EQUAL(toml::integer(54), toml::get<toml::integer>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v(3.14);
|
||||||
|
BOOST_CHECK_EQUAL(toml::floating(3.14), toml::get<toml::floating>(v));
|
||||||
|
|
||||||
|
toml::get<toml::floating>(v) = 2.71;
|
||||||
|
BOOST_CHECK_EQUAL(toml::floating(2.71), toml::get<toml::floating>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v("foo");
|
||||||
|
BOOST_CHECK_EQUAL(toml::string("foo", toml::string_t::basic),
|
||||||
|
toml::get<toml::string>(v));
|
||||||
|
|
||||||
|
toml::get<toml::string>(v).str += "bar";
|
||||||
|
BOOST_CHECK_EQUAL(toml::string("foobar", toml::string_t::basic),
|
||||||
|
toml::get<toml::string>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v("foo", toml::string_t::literal);
|
||||||
|
BOOST_CHECK_EQUAL(toml::string("foo", toml::string_t::literal),
|
||||||
|
toml::get<toml::string>(v));
|
||||||
|
|
||||||
|
toml::get<toml::string>(v).str += "bar";
|
||||||
|
BOOST_CHECK_EQUAL(toml::string("foobar", toml::string_t::literal),
|
||||||
|
toml::get<toml::string>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::local_date d(2018, toml::month_t::Apr, 22);
|
||||||
|
toml::value v(d);
|
||||||
|
BOOST_CHECK(d == toml::get<toml::local_date>(v));
|
||||||
|
|
||||||
|
toml::get<toml::local_date>(v).year = 2017;
|
||||||
|
d.year = 2017;
|
||||||
|
BOOST_CHECK(d == toml::get<toml::local_date>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::local_time t(12, 30, 45);
|
||||||
|
toml::value v(t);
|
||||||
|
BOOST_CHECK(t == toml::get<toml::local_time>(v));
|
||||||
|
|
||||||
|
toml::get<toml::local_time>(v).hour = 9;
|
||||||
|
t.hour = 9;
|
||||||
|
BOOST_CHECK(t == toml::get<toml::local_time>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
|
toml::local_time(12, 30, 45));
|
||||||
|
toml::value v(dt);
|
||||||
|
BOOST_CHECK(dt == toml::get<toml::local_datetime>(v));
|
||||||
|
|
||||||
|
toml::get<toml::local_datetime>(v).date.year = 2017;
|
||||||
|
dt.date.year = 2017;
|
||||||
|
BOOST_CHECK(dt == toml::get<toml::local_datetime>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::offset_datetime dt(toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||||
|
toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
|
||||||
|
toml::value v(dt);
|
||||||
|
BOOST_CHECK(dt == toml::get<toml::offset_datetime>(v));
|
||||||
|
|
||||||
|
toml::get<toml::offset_datetime>(v).date.year = 2017;
|
||||||
|
dt.date.year = 2017;
|
||||||
|
BOOST_CHECK(dt == toml::get<toml::offset_datetime>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::array vec;
|
||||||
|
vec.push_back(toml::value(42));
|
||||||
|
vec.push_back(toml::value(54));
|
||||||
|
toml::value v(vec);
|
||||||
|
BOOST_CHECK(vec == toml::get<toml::array>(v));
|
||||||
|
|
||||||
|
toml::get<toml::array>(v).push_back(toml::value(123));
|
||||||
|
vec.push_back(toml::value(123));
|
||||||
|
BOOST_CHECK(vec == toml::get<toml::array>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::table tab;
|
||||||
|
tab["key1"] = toml::value(42);
|
||||||
|
tab["key2"] = toml::value(3.14);
|
||||||
|
toml::value v(tab);
|
||||||
|
BOOST_CHECK(tab == toml::get<toml::table>(v));
|
||||||
|
|
||||||
|
toml::get<toml::table>(v)["key3"] = toml::value(123);
|
||||||
|
tab["key3"] = toml::value(123);
|
||||||
|
BOOST_CHECK(tab == toml::get<toml::table>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
BOOST_CHECK(v1 == toml::get<toml::value>(v1));
|
||||||
|
|
||||||
|
toml::value v2(54);
|
||||||
|
toml::get<toml::value>(v1) = v2;
|
||||||
|
BOOST_CHECK(v2 == toml::get<toml::value>(v1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_integer_type)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v(42);
|
||||||
|
BOOST_CHECK_EQUAL(int(42), toml::get<int >(v));
|
||||||
|
BOOST_CHECK_EQUAL(short(42), toml::get<short >(v));
|
||||||
|
BOOST_CHECK_EQUAL(char(42), toml::get<char >(v));
|
||||||
|
BOOST_CHECK_EQUAL(unsigned(42), toml::get<unsigned >(v));
|
||||||
|
BOOST_CHECK_EQUAL(long(42), toml::get<long >(v));
|
||||||
|
BOOST_CHECK_EQUAL(std::int64_t(42), toml::get<std::int64_t >(v));
|
||||||
|
BOOST_CHECK_EQUAL(std::uint64_t(42), toml::get<std::uint64_t>(v));
|
||||||
|
BOOST_CHECK_EQUAL(std::int16_t(42), toml::get<std::int16_t >(v));
|
||||||
|
BOOST_CHECK_EQUAL(std::uint16_t(42), toml::get<std::uint16_t>(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_floating_type)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v(3.14);
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<float >(3.14), toml::get<float >(v));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<double >(3.14), toml::get<double >(v));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<long double>(3.14), toml::get<long double>(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_string_type)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v("foo", toml::string_t::basic);
|
||||||
|
BOOST_CHECK_EQUAL("foo", toml::get<std::string>(v));
|
||||||
|
toml::get<std::string>(v) += "bar";
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v("foo", toml::string_t::literal);
|
||||||
|
BOOST_CHECK_EQUAL("foo", toml::get<std::string>(v));
|
||||||
|
toml::get<std::string>(v) += "bar";
|
||||||
|
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_toml_array)
|
||||||
|
{
|
||||||
|
toml::value v(toml::array(0));
|
||||||
|
toml::get<toml::array>(v).push_back(toml::value(42));
|
||||||
|
toml::get<toml::array>(v).push_back(toml::value(54));
|
||||||
|
toml::get<toml::array>(v).push_back(toml::value(69));
|
||||||
|
toml::get<toml::array>(v).push_back(toml::value(72));
|
||||||
|
|
||||||
|
const std::vector<int> vec = toml::get<std::vector<int>>(v);
|
||||||
|
const std::list<short> lst = toml::get<std::list<short>>(v);
|
||||||
|
const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(42, vec.at(0));
|
||||||
|
BOOST_CHECK_EQUAL(54, vec.at(1));
|
||||||
|
BOOST_CHECK_EQUAL(69, vec.at(2));
|
||||||
|
BOOST_CHECK_EQUAL(72, vec.at(3));
|
||||||
|
|
||||||
|
std::list<short>::const_iterator iter = lst.begin();
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<short>(42), *(iter++));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<short>(54), *(iter++));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<short>(69), *(iter++));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<short>(72), *(iter++));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(42), deq.at(0));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(54), deq.at(1));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(69), deq.at(2));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(72), deq.at(3));
|
||||||
|
|
||||||
|
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<int>(42), ary.at(0));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<int>(54), ary.at(1));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<int>(69), ary.at(2));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<int>(72), ary.at(3));
|
||||||
|
|
||||||
|
std::tuple<int, short, unsigned, long> tpl =
|
||||||
|
toml::get<std::tuple<int, short, unsigned, long>>(v);
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<int >(42), std::get<0>(tpl));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<short >(54), std::get<1>(tpl));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<unsigned>(69), std::get<2>(tpl));
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<long >(72), std::get<3>(tpl));
|
||||||
|
|
||||||
|
toml::value p(toml::array{});
|
||||||
|
toml::get<toml::array>(p).push_back(toml::value(3.14));
|
||||||
|
toml::get<toml::array>(p).push_back(toml::value(2.71));
|
||||||
|
std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
|
||||||
|
BOOST_CHECK_EQUAL(3.14, pr.first);
|
||||||
|
BOOST_CHECK_EQUAL(2.71, pr.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_toml_array_of_array)
|
||||||
|
{
|
||||||
|
toml::value v1(toml::array{});
|
||||||
|
toml::get<toml::array>(v1).push_back(toml::value(42));
|
||||||
|
toml::get<toml::array>(v1).push_back(toml::value(54));
|
||||||
|
toml::get<toml::array>(v1).push_back(toml::value(69));
|
||||||
|
toml::get<toml::array>(v1).push_back(toml::value(72));
|
||||||
|
|
||||||
|
toml::value v2(toml::array{});
|
||||||
|
toml::get<toml::array>(v2).push_back(toml::value("foo"));
|
||||||
|
toml::get<toml::array>(v2).push_back(toml::value("bar"));
|
||||||
|
toml::get<toml::array>(v2).push_back(toml::value("baz"));
|
||||||
|
|
||||||
|
toml::value v(toml::array(2));
|
||||||
|
toml::get<toml::array>(v).at(0) = v1;
|
||||||
|
toml::get<toml::array>(v).at(1) = v2;
|
||||||
|
|
||||||
|
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||||
|
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(p.first.at(0), 42);
|
||||||
|
BOOST_CHECK_EQUAL(p.first.at(1), 54);
|
||||||
|
BOOST_CHECK_EQUAL(p.first.at(2), 69);
|
||||||
|
BOOST_CHECK_EQUAL(p.first.at(3), 72);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(p.second.at(0), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(p.second.at(1), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(p.second.at(2), "baz");
|
||||||
|
|
||||||
|
std::tuple<std::vector<int>, std::vector<std::string>> t =
|
||||||
|
toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(std::get<0>(t).at(0), 42);
|
||||||
|
BOOST_CHECK_EQUAL(std::get<0>(t).at(1), 54);
|
||||||
|
BOOST_CHECK_EQUAL(std::get<0>(t).at(2), 69);
|
||||||
|
BOOST_CHECK_EQUAL(std::get<0>(t).at(3), 72);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(std::get<1>(t).at(0), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(std::get<1>(t).at(1), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(std::get<1>(t).at(2), "baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_toml_table)
|
||||||
|
{
|
||||||
|
toml::value v1(toml::table{
|
||||||
|
{"key1", 1},
|
||||||
|
{"key2", 2},
|
||||||
|
{"key3", 3},
|
||||||
|
{"key4", 4}
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto v = toml::get<std::map<std::string, int>>(v1);
|
||||||
|
BOOST_CHECK_EQUAL(v.at("key1"), 1);
|
||||||
|
BOOST_CHECK_EQUAL(v.at("key2"), 2);
|
||||||
|
BOOST_CHECK_EQUAL(v.at("key3"), 3);
|
||||||
|
BOOST_CHECK_EQUAL(v.at("key4"), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_toml_local_date)
|
||||||
|
{
|
||||||
|
toml::value v1(toml::local_date{2018, toml::month_t::Apr, 1});
|
||||||
|
const auto date = std::chrono::system_clock::to_time_t(
|
||||||
|
toml::get<std::chrono::system_clock::time_point>(v1));
|
||||||
|
|
||||||
|
std::tm t;
|
||||||
|
t.tm_year = 2018 - 1900;
|
||||||
|
t.tm_mon = 4 - 1;
|
||||||
|
t.tm_mday = 1;
|
||||||
|
t.tm_hour = 0;
|
||||||
|
t.tm_min = 0;
|
||||||
|
t.tm_sec = 0;
|
||||||
|
t.tm_isdst = -1;
|
||||||
|
const auto c = std::mktime(&t);
|
||||||
|
BOOST_CHECK_EQUAL(c, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_toml_local_time)
|
||||||
|
{
|
||||||
|
toml::value v1(toml::local_time{12, 30, 45});
|
||||||
|
const auto time = toml::get<std::chrono::seconds>(v1);
|
||||||
|
BOOST_CHECK(time == std::chrono::hours(12) +
|
||||||
|
std::chrono::minutes(30) + std::chrono::seconds(45));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_toml_local_datetime)
|
||||||
|
{
|
||||||
|
toml::value v1(toml::local_datetime(
|
||||||
|
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||||
|
toml::local_time{12, 30, 45}));
|
||||||
|
|
||||||
|
const auto date = std::chrono::system_clock::to_time_t(
|
||||||
|
toml::get<std::chrono::system_clock::time_point>(v1));
|
||||||
|
std::tm t;
|
||||||
|
t.tm_year = 2018 - 1900;
|
||||||
|
t.tm_mon = 4 - 1;
|
||||||
|
t.tm_mday = 1;
|
||||||
|
t.tm_hour = 12;
|
||||||
|
t.tm_min = 30;
|
||||||
|
t.tm_sec = 45;
|
||||||
|
t.tm_isdst = -1;
|
||||||
|
const auto c = std::mktime(&t);
|
||||||
|
BOOST_CHECK_EQUAL(c, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v1(toml::offset_datetime(
|
||||||
|
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||||
|
toml::local_time{12, 30, 0},
|
||||||
|
toml::time_offset{9, 0}));
|
||||||
|
// 2018-04-01T12:30:00+09:00
|
||||||
|
// == 2018-04-01T03:30:00Z
|
||||||
|
|
||||||
|
const auto date = toml::get<std::chrono::system_clock::time_point>(v1);
|
||||||
|
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||||
|
|
||||||
|
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||||
|
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
|
||||||
|
BOOST_CHECK(tmp);
|
||||||
|
const auto tm = *tmp;
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_year + 1900, 2018);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_mon + 1, 4);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_mday, 1);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_hour, 3);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_min, 30);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_sec, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
toml::value v1(toml::offset_datetime(
|
||||||
|
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||||
|
toml::local_time{12, 30, 0},
|
||||||
|
toml::time_offset{-8, 0}));
|
||||||
|
// 2018-04-01T12:30:00-08:00
|
||||||
|
// == 2018-04-01T20:30:00Z
|
||||||
|
|
||||||
|
const auto date = toml::get<std::chrono::system_clock::time_point>(v1);
|
||||||
|
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||||
|
|
||||||
|
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||||
|
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
|
||||||
|
BOOST_CHECK(tmp);
|
||||||
|
const auto tm = *tmp;
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_year + 1900, 2018);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_mon + 1, 4);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_mday, 1);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_hour, 20);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_min, 30);
|
||||||
|
BOOST_CHECK_EQUAL(tm.tm_sec, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
#define BOOST_TEST_MODULE "test_get_or"
|
|
||||||
#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 <unordered_map>
|
|
||||||
#include <list>
|
|
||||||
#include <deque>
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_or_exist)
|
|
||||||
{
|
|
||||||
toml::Boolean raw_v1(true);
|
|
||||||
toml::Integer raw_v2(42);
|
|
||||||
toml::Float raw_v3(3.14);
|
|
||||||
toml::String raw_v4("hoge");
|
|
||||||
toml::Array raw_v5{2,7,1,8,2};
|
|
||||||
toml::Table raw_v6{{"key", 42}};
|
|
||||||
|
|
||||||
toml::value v1(raw_v1);
|
|
||||||
toml::value v2(raw_v2);
|
|
||||||
toml::value v3(raw_v3);
|
|
||||||
toml::value v4(raw_v4);
|
|
||||||
toml::value v5(raw_v5);
|
|
||||||
toml::value v6(raw_v6);
|
|
||||||
|
|
||||||
toml::Table table{
|
|
||||||
{"value1", v1},
|
|
||||||
{"value2", v2},
|
|
||||||
{"value3", v3},
|
|
||||||
{"value4", v4},
|
|
||||||
{"value5", v5},
|
|
||||||
{"value6", v6}
|
|
||||||
};
|
|
||||||
|
|
||||||
toml::Boolean u1 = toml::get_or(table, "value1", raw_v1);
|
|
||||||
toml::Integer u2 = toml::get_or(table, "value2", raw_v2);
|
|
||||||
toml::Float u3 = toml::get_or(table, "value3", raw_v3);
|
|
||||||
toml::String u4 = toml::get_or(table, "value4", raw_v4);
|
|
||||||
toml::Array u5 = toml::get_or(table, "value5", raw_v5);
|
|
||||||
toml::Table u6 = toml::get_or(table, "value6", raw_v6);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u1, raw_v1);
|
|
||||||
BOOST_CHECK_EQUAL(u2, raw_v2);
|
|
||||||
BOOST_CHECK_EQUAL(u3, raw_v3);
|
|
||||||
BOOST_CHECK_EQUAL(u4, raw_v4);
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(0).cast<toml::value_t::Integer>(), raw_v5.at(0).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(1).cast<toml::value_t::Integer>(), raw_v5.at(1).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(2).cast<toml::value_t::Integer>(), raw_v5.at(2).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(3).cast<toml::value_t::Integer>(), raw_v5.at(3).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(4).cast<toml::value_t::Integer>(), raw_v5.at(4).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at("key").cast<toml::value_t::Integer>(), 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_or_empty)
|
|
||||||
{
|
|
||||||
toml::Boolean raw_v1(true);
|
|
||||||
toml::Integer raw_v2(42);
|
|
||||||
toml::Float raw_v3(3.14);
|
|
||||||
toml::String raw_v4("hoge");
|
|
||||||
toml::Array raw_v5{2,7,1,8,2};
|
|
||||||
toml::Table raw_v6{{"key", 42}};
|
|
||||||
|
|
||||||
toml::Table table; // empty!
|
|
||||||
|
|
||||||
toml::Boolean u1 = toml::get_or(table, std::string("value1"), raw_v1);
|
|
||||||
toml::Integer u2 = toml::get_or(table, std::string("value2"), raw_v2);
|
|
||||||
toml::Float u3 = toml::get_or(table, std::string("value3"), raw_v3);
|
|
||||||
toml::String u4 = toml::get_or(table, std::string("value4"), raw_v4);
|
|
||||||
toml::Array u5 = toml::get_or(table, std::string("value5"), raw_v5);
|
|
||||||
toml::Table u6 = toml::get_or(table, std::string("value6"), raw_v6);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u1, raw_v1);
|
|
||||||
BOOST_CHECK_EQUAL(u2, raw_v2);
|
|
||||||
BOOST_CHECK_EQUAL(u3, raw_v3);
|
|
||||||
BOOST_CHECK_EQUAL(u4, raw_v4);
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(0).cast<toml::value_t::Integer>(), raw_v5.at(0).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(1).cast<toml::value_t::Integer>(), raw_v5.at(1).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(2).cast<toml::value_t::Integer>(), raw_v5.at(2).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(3).cast<toml::value_t::Integer>(), raw_v5.at(3).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u5.at(4).cast<toml::value_t::Integer>(), raw_v5.at(4).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(u6.at("key").cast<toml::value_t::Integer>(), 42);
|
|
||||||
}
|
|
||||||
254
tests/test_get_related_func.cpp
Normal file
254
tests/test_get_related_func.cpp
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_get_or"
|
||||||
|
#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 <unordered_map>
|
||||||
|
#include <list>
|
||||||
|
#include <deque>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_find)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v(true);
|
||||||
|
bool thrown = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toml::find<toml::boolean>(v, "key");
|
||||||
|
}
|
||||||
|
catch(toml::type_error const& te)
|
||||||
|
{
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
BOOST_CHECK(thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
toml::table v{{"num", 42}};
|
||||||
|
BOOST_CHECK_EQUAL(42, toml::find<int>(v, "num"));
|
||||||
|
toml::find<toml::integer>(v, "num") = 54;
|
||||||
|
BOOST_CHECK_EQUAL(54, toml::find<int>(v, "num"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
toml::value v = toml::table{{"num", 42}};
|
||||||
|
BOOST_CHECK_EQUAL(42, toml::find<int>(v, "num"));
|
||||||
|
toml::find<toml::integer>(v, "num") = 54;
|
||||||
|
BOOST_CHECK_EQUAL(54, toml::find<int>(v, "num"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_get_or)
|
||||||
|
{
|
||||||
|
// requires conversion int -> uint
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
toml::value v2(3.14);
|
||||||
|
BOOST_CHECK_EQUAL(42u, toml::get_or(v1, 0u));
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_expect)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::value v1(42);
|
||||||
|
toml::value v2(3.14);
|
||||||
|
const auto v1_or_0 = toml::expect<int>(v1).unwrap_or(0);
|
||||||
|
const auto v2_or_0 = toml::expect<int>(v2).unwrap_or(0);
|
||||||
|
BOOST_CHECK_EQUAL(42, v1_or_0);
|
||||||
|
BOOST_CHECK_EQUAL( 0, v2_or_0);
|
||||||
|
|
||||||
|
const auto v1_or_none = toml::expect<int>(v1).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
|
||||||
|
const auto v2_or_none = toml::expect<int>(v2).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
|
||||||
|
BOOST_CHECK_EQUAL("42", v1_or_none);
|
||||||
|
BOOST_CHECK_EQUAL("none", v2_or_none);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
tests/test_lex_aux.hpp
Normal file
35
tests/test_lex_aux.hpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <toml/region.hpp>
|
||||||
|
#include <toml/result.hpp>
|
||||||
|
|
||||||
|
#define TOML11_TEST_LEX_ACCEPT(lxr, tkn, expct) \
|
||||||
|
do { \
|
||||||
|
const std::string token (tkn); \
|
||||||
|
const std::string expected(expct); \
|
||||||
|
toml::detail::location<std::string> loc("test", token); \
|
||||||
|
const auto result = lxr::invoke(loc); \
|
||||||
|
BOOST_CHECK(result.is_ok()); \
|
||||||
|
if(result.is_ok()){ \
|
||||||
|
const auto region = result.unwrap(); \
|
||||||
|
BOOST_CHECK_EQUAL(region.str(), expected); \
|
||||||
|
BOOST_CHECK_EQUAL(region.str().size(), expected.size()); \
|
||||||
|
BOOST_CHECK_EQUAL(static_cast<std::size_t>(std::distance( \
|
||||||
|
loc.begin(), loc.iter())), region.size()); \
|
||||||
|
} else { \
|
||||||
|
std::cerr << "lexer " << lxr::pattern() << " failed with input `"; \
|
||||||
|
std::cerr << token << "`. expected `" << expected << "`\n"; \
|
||||||
|
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
|
||||||
|
} \
|
||||||
|
} while(false); \
|
||||||
|
/**/
|
||||||
|
|
||||||
|
#define TOML11_TEST_LEX_REJECT(lxr, tkn) \
|
||||||
|
do { \
|
||||||
|
const std::string token (tkn); \
|
||||||
|
toml::detail::location<std::string> loc("test", token); \
|
||||||
|
const auto result = lxr::invoke(loc); \
|
||||||
|
BOOST_CHECK(result.is_err()); \
|
||||||
|
BOOST_CHECK(loc.begin() == loc.iter()); \
|
||||||
|
} while(false); /**/
|
||||||
23
tests/test_lex_boolean.cpp
Normal file
23
tests/test_lex_boolean.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_lex_boolean"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <toml/lexer.hpp>
|
||||||
|
#include "test_lex_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_correct)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_boolean, "true", "true");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_boolean, "false", "false");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_boolean, "true # trailing", "true");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_boolean, "false # trailing", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_invalid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_boolean, "TRUE");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_boolean, "FALSE");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_boolean, "True");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_boolean, "False");
|
||||||
|
}
|
||||||
57
tests/test_lex_datetime.cpp
Normal file
57
tests/test_lex_datetime.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_lex_datetime"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <toml/lexer.hpp>
|
||||||
|
#include "test_lex_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_offset_datetime)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
|
||||||
|
"1979-05-27T07:32:00Z",
|
||||||
|
"1979-05-27T07:32:00Z");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
|
||||||
|
"1979-05-27T07:32:00-07:00",
|
||||||
|
"1979-05-27T07:32:00-07:00");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
|
||||||
|
"1979-05-27T07:32:00.999999-07:00",
|
||||||
|
"1979-05-27T07:32:00.999999-07:00");
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
|
||||||
|
"1979-05-27 07:32:00Z",
|
||||||
|
"1979-05-27 07:32:00Z");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
|
||||||
|
"1979-05-27 07:32:00-07:00",
|
||||||
|
"1979-05-27 07:32:00-07:00");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
|
||||||
|
"1979-05-27 07:32:00.999999-07:00",
|
||||||
|
"1979-05-27 07:32:00.999999-07:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_local_datetime)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
|
||||||
|
"1979-05-27T07:32:00",
|
||||||
|
"1979-05-27T07:32:00");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
|
||||||
|
"1979-05-27T07:32:00.999999",
|
||||||
|
"1979-05-27T07:32:00.999999");
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
|
||||||
|
"1979-05-27 07:32:00",
|
||||||
|
"1979-05-27 07:32:00");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
|
||||||
|
"1979-05-27 07:32:00.999999",
|
||||||
|
"1979-05-27 07:32:00.999999");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_local_date)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_local_date, "1979-05-27", "1979-05-27");
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_CASE(test_local_time)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_local_time, "07:32:00", "07:32:00");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_local_time, "07:32:00.999999", "07:32:00.999999");
|
||||||
|
}
|
||||||
84
tests/test_lex_floating.cpp
Normal file
84
tests/test_lex_floating.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_lex_floating"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <toml/lexer.hpp>
|
||||||
|
#include <limits>
|
||||||
|
#include "test_lex_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_fractional_valid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0", "1.0" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "0.1", "0.1" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "0.001", "0.001" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "0.100", "0.100" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "+3.14", "+3.14" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "-3.14", "-3.14" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "3.1415_9265_3589", "3.1415_9265_3589" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "+3.1415_9265_3589", "+3.1415_9265_3589");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "-3.1415_9265_3589", "-3.1415_9265_3589");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "123_456.789", "123_456.789" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "+123_456.789", "+123_456.789" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "-123_456.789", "-123_456.789" );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_fractional_invalid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_float, "0.");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_float, ".0");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_float, "01.0");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_float, "3,14");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_float, "+-1.0");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_float, "1._0");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_exponential_valid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1e10", "1e10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1e+10", "1e+10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1e-10", "1e-10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e10", "+1e10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e+10", "+1e+10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e-10", "+1e-10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e10", "-1e10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e+10", "-1e+10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e-10", "-1e-10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "123e-10", "123e-10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1E10", "1E10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1E+10", "1E+10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1E-10", "1E-10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "123E-10", "123E-10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-10", "1_2_3E-10");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-1_0", "1_2_3E-1_0");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_exponential_invalid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1E0", "1e1");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1E1e0", "1E1");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_both_valid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e23", "6.02e23");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e+23", "6.02e+23");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1.112_650_06e-17", "1.112_650_06e-17");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_both_invalid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1.0", "1e1");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_float, "01e1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_special_floating_point)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "inf", "inf");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "+inf", "+inf");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "-inf", "-inf");
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "nan", "nan");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "+nan", "+nan");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_float, "-nan", "-nan");
|
||||||
|
}
|
||||||
101
tests/test_lex_integer.cpp
Normal file
101
tests/test_lex_integer.cpp
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_lex_integer"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <toml/lexer.hpp>
|
||||||
|
#include "test_lex_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_decimal_correct)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "1234", "1234" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "+1234", "+1234" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "-1234", "-1234" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0", "0" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "1_2_3_4", "1_2_3_4" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "+1_2_3_4", "+1_2_3_4" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "-1_2_3_4", "-1_2_3_4" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "123_456_789", "123_456_789");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_decimal_invalid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "123+45", "123");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "123-45", "123");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "01234", "0");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "123__45", "123");
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_integer, "_1234");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_hex_correct)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEADBEEF", "0xDEADBEEF" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdeadbeef", "0xdeadbeef" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEADbeef", "0xDEADbeef" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD_BEEF", "0xDEAD_BEEF");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdead_beef", "0xdead_beef");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdead_BEEF", "0xdead_BEEF");
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xFF", "0xFF" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0x00FF", "0x00FF" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0x0000FF", "0x0000FF");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_hex_invalid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xAPPLE", "0xA");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD+BEEF", "0xDEAD");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD__BEEF", "0xDEAD");
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_hex_int, "0x_DEADBEEF");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_hex_int, "0x+DEADBEEF");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_hex_int, "-0xFF" );
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_hex_int, "-0x00FF" );
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0x_DEADBEEF", "0" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0x+DEADBEEF", "0" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "-0xFF" , "-0" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "-0x00FF" , "-0" );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_oct_correct)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o777", "0o777" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o7_7_7", "0o7_7_7");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o007", "0o007" );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_oct_invalid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o77+7", "0o77");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o1__0", "0o1");
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_oct_int, "0o800" );
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_oct_int, "-0o777");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_oct_int, "0o+777");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_oct_int, "0o_10" );
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o800", "0");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "-0o777", "-0");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o+777", "0");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o_10", "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_bin_correct)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0b10000", "0b10000" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0b010000", "0b010000" );
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0b01_00_00", "0b01_00_00");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_integer, "0b111111", "0b111111" );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_bin_invalid)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_bin_int, "0b11__11", "0b11");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_bin_int, "0b11+11" , "0b11");
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_bin_int, "-0b10000");
|
||||||
|
TOML11_TEST_LEX_REJECT(lex_bin_int, "0b_1111" );
|
||||||
|
}
|
||||||
53
tests/test_lex_key_comment.cpp
Normal file
53
tests/test_lex_key_comment.cpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#define BOOST_TEST_MODULE "lex_key_comment_test"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <toml/lexer.hpp>
|
||||||
|
#include "test_lex_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_bare_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "barekey", "barekey");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "bare-key", "bare-key");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "bare_key", "bare_key");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "1234", "1234");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_quoted_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "\"127.0.0.1\"", "\"127.0.0.1\"");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "\"character encoding\"", "\"character encoding\"");
|
||||||
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"",
|
||||||
|
"\"\xCA\x8E\xC7\x9D\xCA\x9E\"");
|
||||||
|
#else
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, u8"\"ʎǝʞ\"", u8"\"ʎǝʞ\"");
|
||||||
|
#endif
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "'key2'", "'key2'");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "'quoted \"value\"'", "'quoted \"value\"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_dotted_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "physical.color", "physical.color");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "physical.shape", "physical.shape");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x.y", "x.y");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x . y", "x . y");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x.y.z", "x.y.z");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x. y .z", "x. y .z");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x .y. z", "x .y. z");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x . y . z", "x . y . z");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x.y.z.w", "x.y.z.w");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x. y .z. w", "x. y .z. w");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "x . y . z . w", "x . y . z . w");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_key, "site.\"google.com\"", "site.\"google.com\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_comment)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_comment, "# hoge", "# hoge");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_comment, "# \n", "# ");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_comment, "# \r\n", "# ");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_comment, "# # \n", "# # ");
|
||||||
|
}
|
||||||
86
tests/test_lex_string.cpp
Normal file
86
tests/test_lex_string.cpp
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_lex_string"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <toml/lexer.hpp>
|
||||||
|
#include "test_lex_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\"The quick brown fox jumps over the lazy dog\"",
|
||||||
|
"\"The quick brown fox jumps over the lazy dog\"");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\'The quick brown fox jumps over the lazy dog\'",
|
||||||
|
"\'The quick brown fox jumps over the lazy dog\'");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_ml_basic_string,
|
||||||
|
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
|
||||||
|
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_ml_literal_string,
|
||||||
|
"'''The quick brown fox \njumps over the lazy dog'''",
|
||||||
|
"'''The quick brown fox \njumps over the lazy dog'''");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_basic_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
|
||||||
|
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\"192.168.1.1\"",
|
||||||
|
"\"192.168.1.1\"");
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
|
||||||
|
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"");
|
||||||
|
#else
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
u8"\"中国\"",
|
||||||
|
u8"\"中国\"");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\"You'll hate me after this - #\"",
|
||||||
|
"\"You'll hate me after this - #\"");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\" And when \\\"'s are in the string, along with # \\\"\"",
|
||||||
|
"\" And when \\\"'s are in the string, along with # \\\"\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_ml_basic_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"",
|
||||||
|
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"",
|
||||||
|
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_literal_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"'C:\\Users\\nodejs\\templates'",
|
||||||
|
"'C:\\Users\\nodejs\\templates'");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"'\\\\ServerX\\admin$\\system32\\'",
|
||||||
|
"'\\\\ServerX\\admin$\\system32\\'");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"'Tom \"Dubs\" Preston-Werner'",
|
||||||
|
"'Tom \"Dubs\" Preston-Werner'");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"'<\\i\\c*\\s*>'",
|
||||||
|
"'<\\i\\c*\\s*>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_ml_literal_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"'''I [dw]on't need \\d{2} apples'''",
|
||||||
|
"'''I [dw]on't need \\d{2} apples'''");
|
||||||
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
|
"'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''",
|
||||||
|
"'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''");
|
||||||
|
}
|
||||||
129
tests/test_literals.cpp
Normal file
129
tests/test_literals.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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"));
|
||||||
|
}
|
||||||
130
tests/test_parse_array.cpp
Normal file
130
tests/test_parse_array.cpp
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_array_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_oneline_array)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[]", array());
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
|
||||||
|
a[3] = toml::value(1); a[4] = toml::value(5);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5]", a);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(3);
|
||||||
|
a[0] = toml::value("foo"); a[1] = toml::value("bar");
|
||||||
|
a[2] = toml::value("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\"]", a);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
|
||||||
|
a[3] = toml::value(1); a[4] = toml::value(5);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5,]", a);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(3);
|
||||||
|
a[0] = toml::value("foo"); a[1] = toml::value("bar");
|
||||||
|
a[2] = toml::value("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\",]", a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_oneline_array_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[]", toml::value(array()));
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
|
||||||
|
a[3] = toml::value(1); a[4] = toml::value(5);
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,1,4,1,5]", toml::value(a));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(3);
|
||||||
|
a[0] = toml::value("foo"); a[1] = toml::value("bar");
|
||||||
|
a[2] = toml::value("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\"]", toml::value(a));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
|
||||||
|
a[3] = toml::value(1); a[4] = toml::value(5);
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,1,4,1,5,]", toml::value(a));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(3);
|
||||||
|
a[0] = toml::value("foo"); a[1] = toml::value("bar");
|
||||||
|
a[2] = toml::value("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\",]", toml::value(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_multiline_array)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[\n#comment\n]", array());
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
|
||||||
|
a[3] = toml::value(1); a[4] = toml::value(5);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,\n1,\n4,\n1,\n5]", a);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(3);
|
||||||
|
a[0] = toml::value("foo"); a[1] = toml::value("bar");
|
||||||
|
a[2] = toml::value("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
|
||||||
|
a[3] = toml::value(1); a[4] = toml::value(5);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", a);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(3);
|
||||||
|
a[0] = toml::value("foo"); a[1] = toml::value("b#r");
|
||||||
|
a[2] = toml::value("b#z");
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_multiline_array_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\n#comment\n]", toml::value(array()));
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
|
||||||
|
a[3] = toml::value(1); a[4] = toml::value(5);
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,\n1,\n4,\n1,\n5]", toml::value(a));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(3);
|
||||||
|
a[0] = toml::value("foo"); a[1] = toml::value("bar");
|
||||||
|
a[2] = toml::value("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",\n\"bar\",\n\"baz\"]", toml::value(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
array a(5);
|
||||||
|
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
|
||||||
|
a[3] = toml::value(1); a[4] = toml::value(5);
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", toml::value(a));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
array a(3);
|
||||||
|
a[0] = toml::value("foo"); a[1] = toml::value("b#r");
|
||||||
|
a[2] = toml::value("b#z");
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", toml::value(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
38
tests/test_parse_aux.hpp
Normal file
38
tests/test_parse_aux.hpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <toml/region.hpp>
|
||||||
|
#include <toml/result.hpp>
|
||||||
|
|
||||||
|
// some of the parsers returns not only a value but also a region.
|
||||||
|
#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \
|
||||||
|
do { \
|
||||||
|
const std::string token(tkn); \
|
||||||
|
toml::detail::location<std::string> loc("test", token); \
|
||||||
|
const auto result = psr(loc); \
|
||||||
|
BOOST_CHECK(result.is_ok()); \
|
||||||
|
if(result.is_ok()){ \
|
||||||
|
BOOST_CHECK(result.unwrap().first == expct); \
|
||||||
|
} else { \
|
||||||
|
std::cerr << "parser " << #psr << " failed with input `"; \
|
||||||
|
std::cerr << token << "`.\n"; \
|
||||||
|
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
|
||||||
|
} \
|
||||||
|
} while(false); \
|
||||||
|
/**/
|
||||||
|
|
||||||
|
#define TOML11_TEST_PARSE_EQUAL_VALUE(psr, tkn, expct) \
|
||||||
|
do { \
|
||||||
|
const std::string token(tkn); \
|
||||||
|
toml::detail::location<std::string> loc("test", token); \
|
||||||
|
const auto result = psr(loc); \
|
||||||
|
BOOST_CHECK(result.is_ok()); \
|
||||||
|
if(result.is_ok()){ \
|
||||||
|
BOOST_CHECK(result.unwrap() == expct); \
|
||||||
|
} else { \
|
||||||
|
std::cerr << "parse_value failed with input `"; \
|
||||||
|
std::cerr << token << "`.\n"; \
|
||||||
|
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
|
||||||
|
} \
|
||||||
|
} while(false); \
|
||||||
|
/**/
|
||||||
24
tests/test_parse_boolean.cpp
Normal file
24
tests/test_parse_boolean.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_parse_boolean"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_boolean)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_boolean, "true", true);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_boolean, "false", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_boolean_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "true", toml::value( true));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "false", toml::value(false));
|
||||||
|
}
|
||||||
133
tests/test_parse_datetime.cpp
Normal file
133
tests/test_parse_datetime.cpp
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_datetime_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_time)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00", toml::local_time(7, 32, 0));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.99", toml::local_time(7, 32, 0, 990, 0));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.999", toml::local_time(7, 32, 0, 999, 0));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.999999", toml::local_time(7, 32, 0, 999, 999));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_time_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00", toml::value(toml::local_time(7, 32, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.99", toml::value(toml::local_time(7, 32, 0, 990, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.999", toml::value(toml::local_time(7, 32, 0, 999, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.999999", toml::value(toml::local_time(7, 32, 0, 999, 999)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_date)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_date, "1979-05-27",
|
||||||
|
toml::local_date(1979, toml::month_t::May, 27));
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_CASE(test_date_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27",
|
||||||
|
value(toml::local_date(1979, toml::month_t::May, 27)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_datetime)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00.99",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00.999999",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)));
|
||||||
|
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00.99",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00.999999",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)));
|
||||||
|
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00.99",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00.999999",
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_datetime_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.99",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.999999",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
|
||||||
|
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27t07:32:00",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27t07:32:00.99",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27t07:32:00.999999",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
|
||||||
|
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27 07:32:00",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27 07:32:00.99",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27 07:32:00.999999",
|
||||||
|
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_offset_datetime)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00Z",
|
||||||
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.99Z",
|
||||||
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0, 990, 0), toml::time_offset(0, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.999999Z",
|
||||||
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0, 999, 999), toml::time_offset(0, 0)));
|
||||||
|
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00+09:00",
|
||||||
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0), toml::time_offset(9, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.99+09:00",
|
||||||
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0, 990, 0), toml::time_offset(9, 0)));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.999999+09:00",
|
||||||
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_offset_datetime_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00Z",
|
||||||
|
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0), toml::time_offset(0, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.99Z",
|
||||||
|
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0, 990, 0), toml::time_offset(0, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.999999Z",
|
||||||
|
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0, 999, 999), toml::time_offset(0, 0))));
|
||||||
|
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00+09:00",
|
||||||
|
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0), toml::time_offset(9, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.99+09:00",
|
||||||
|
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0, 990, 0), toml::time_offset(9, 0))));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.999999+09:00",
|
||||||
|
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0))));
|
||||||
|
}
|
||||||
@@ -22,7 +22,8 @@ BOOST_AUTO_TEST_CASE(test_example)
|
|||||||
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")),
|
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")),
|
||||||
"GitHub Cofounder & CEO\nLikes tater tots and beer.");
|
"GitHub Cofounder & CEO\nLikes tater tots and beer.");
|
||||||
BOOST_CHECK_EQUAL(toml::get<toml::Datetime>(owner.at("dob")),
|
BOOST_CHECK_EQUAL(toml::get<toml::Datetime>(owner.at("dob")),
|
||||||
toml::Datetime(1979, 5, 27, 7, 32, 0, 0, 0, 0, 0));
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
toml::Table database = toml::get<toml::Table>(data.at("database"));
|
toml::Table database = toml::get<toml::Table>(data.at("database"));
|
||||||
@@ -90,7 +91,8 @@ BOOST_AUTO_TEST_CASE(test_example_stream)
|
|||||||
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")),
|
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")),
|
||||||
"GitHub Cofounder & CEO\nLikes tater tots and beer.");
|
"GitHub Cofounder & CEO\nLikes tater tots and beer.");
|
||||||
BOOST_CHECK_EQUAL(toml::get<toml::Datetime>(owner.at("dob")),
|
BOOST_CHECK_EQUAL(toml::get<toml::Datetime>(owner.at("dob")),
|
||||||
toml::Datetime(1979, 5, 27, 7, 32, 0, 0, 0, 0, 0));
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
toml::Table database = toml::get<toml::Table>(data.at("database"));
|
toml::Table database = toml::get<toml::Table>(data.at("database"));
|
||||||
@@ -192,3 +194,504 @@ BOOST_AUTO_TEST_CASE(test_hard_example)
|
|||||||
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
|
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
|
||||||
expected_multi_line_array);
|
expected_multi_line_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// after here, the test codes generate the content of a file.
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_file_with_BOM)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"\xEF\xBB\xBF" // BOM
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss, "test_file_with_BOM.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"\xEF\xBB\xBF" // BOM
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
);
|
||||||
|
{
|
||||||
|
std::ofstream ofs("tmp.toml");
|
||||||
|
ofs << table;
|
||||||
|
}
|
||||||
|
const auto data = toml::parse("tmp.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"\xEF\xBB\xBF" // BOM
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"\xEF\xBB\xBF" // BOM
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
);
|
||||||
|
{
|
||||||
|
// with text-mode, "\n" is converted to "\r\n" and the resulting
|
||||||
|
// value will be "\r\r\n". To avoid the additional "\r", use binary
|
||||||
|
// mode.
|
||||||
|
std::ofstream ofs("tmp.toml", std::ios_base::binary);
|
||||||
|
ofs.write(table.data(), table.size());
|
||||||
|
}
|
||||||
|
const auto data = toml::parse("tmp.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\""
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_file_without_newline_at_the_end_of_file.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\""
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_file_without_newline_at_the_end_of_file_CRLF.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\" # comment"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_file_without_newline_at_the_end_of_file_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\" # comment"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_file_without_newline_at_the_end_of_file_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\" \t"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_file_without_newline_at_the_end_of_file_ws.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\" \t"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_file_without_newline_at_the_end_of_file_ws.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
|
||||||
|
{
|
||||||
|
// comment w/o newline
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"# comment"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"# comment\n"
|
||||||
|
"# one more comment"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// comment w/ newline
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"# comment\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"# comment\n"
|
||||||
|
"# one more comment\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRLF version
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"# comment"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"# comment\r\n"
|
||||||
|
"# one more comment"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"# comment\r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"# comment\r\n"
|
||||||
|
"# one more comment\r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_comment.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// with whitespaces
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
" \n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
" \n"
|
||||||
|
" \n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"\n"
|
||||||
|
" \n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
" \n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// with whitespaces but no newline
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
" "
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// CRLF
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// with whitespaces
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
" \r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
" \r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
" \r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
" \r\n"
|
||||||
|
" \r\n"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
"[table]\r\n"
|
||||||
|
"key = \"value\"\r\n"
|
||||||
|
" "
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
158
tests/test_parse_floating.cpp
Normal file
158
tests/test_parse_floating.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_floating_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include <cmath>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_fractional)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1.0", 1.0);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "0.1", 0.1);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "0.001", 0.001);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "0.100", 0.1);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+3.14", 3.14);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-3.14", -3.14);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "3.1415_9265_3589", 3.141592653589);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+3.1415_9265_3589", 3.141592653589);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-3.1415_9265_3589", -3.141592653589);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "123_456.789", 123456.789);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+123_456.789", 123456.789);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-123_456.789", -123456.789);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+0.0", 0.0);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-0.0", -0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_fractional_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1.0", value( 1.0));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.1", value( 0.1));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.001", value( 0.001));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.100", value( 0.1));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+3.14", value( 3.14));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-3.14", value(-3.14));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "3.1415_9265_3589", value( 3.141592653589));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+3.1415_9265_3589", value( 3.141592653589));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-3.1415_9265_3589", value(-3.141592653589));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123_456.789", value( 123456.789));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+123_456.789", value( 123456.789));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-123_456.789", value(-123456.789));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+0.0", value( 0.0));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0.0", value(-0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_exponential)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1e10", 1e10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1e+10", 1e10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1e-10", 1e-10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e10", 1e10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e+10", 1e10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e-10", 1e-10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e10", -1e10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e+10", -1e10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e-10", -1e-10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "123e-10", 123e-10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1E10", 1e10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1E+10", 1e10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1E-10", 1e-10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "123E-10", 123e-10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-10", 123e-10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-1_0", 123e-10);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "+0e0", 0.0);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "-0e0", -0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_exponential_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e10", value(1e10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e+10", value(1e10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e-10", value(1e-10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e10", value(1e10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e+10", value(1e10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e-10", value(1e-10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e10", value(-1e10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e+10", value(-1e10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e-10", value(-1e-10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123e-10", value(123e-10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E10", value(1e10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E+10", value(1e10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E-10", value(1e-10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123E-10", value(123e-10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3E-10", value(123e-10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3E-1_0", value(123e-10));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+0e0", value( 0.0));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0e0", value(-0.0));
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_CASE(test_fe)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "6.02e23", 6.02e23);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "6.02e+23", 6.02e23);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_floating, "1.112_650_06e-17", 1.11265006e-17);
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_CASE(test_fe_vaule)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "6.02e23", value(6.02e23));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "6.02e+23", value(6.02e23));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1.112_650_06e-17", value(1.11265006e-17));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_inf)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const std::string token("inf");
|
||||||
|
toml::detail::location<std::string> loc("test", token);
|
||||||
|
const auto r = parse_floating(loc);
|
||||||
|
BOOST_CHECK(r.is_ok());
|
||||||
|
BOOST_CHECK(std::isinf(r.unwrap().first));
|
||||||
|
BOOST_CHECK(r.unwrap().first > 0.0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string token("+inf");
|
||||||
|
toml::detail::location<std::string> loc("test", token);
|
||||||
|
const auto r = parse_floating(loc);
|
||||||
|
BOOST_CHECK(r.is_ok());
|
||||||
|
BOOST_CHECK(std::isinf(r.unwrap().first));
|
||||||
|
BOOST_CHECK(r.unwrap().first > 0.0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string token("-inf");
|
||||||
|
toml::detail::location<std::string> loc("test", token);
|
||||||
|
const auto r = parse_floating(loc);
|
||||||
|
BOOST_CHECK(r.is_ok());
|
||||||
|
BOOST_CHECK(std::isinf(r.unwrap().first));
|
||||||
|
BOOST_CHECK(r.unwrap().first < 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_nan)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const std::string token("nan");
|
||||||
|
toml::detail::location<std::string> loc("test", token);
|
||||||
|
const auto r = parse_floating(loc);
|
||||||
|
BOOST_CHECK(r.is_ok());
|
||||||
|
BOOST_CHECK(std::isnan(r.unwrap().first));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string token("+nan");
|
||||||
|
toml::detail::location<std::string> loc("test", token);
|
||||||
|
const auto r = parse_floating(loc);
|
||||||
|
BOOST_CHECK(r.is_ok());
|
||||||
|
BOOST_CHECK(std::isnan(r.unwrap().first));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string token("-nan");
|
||||||
|
toml::detail::location<std::string> loc("test", token);
|
||||||
|
const auto r = parse_floating(loc);
|
||||||
|
BOOST_CHECK(r.is_ok());
|
||||||
|
BOOST_CHECK(std::isnan(r.unwrap().first));
|
||||||
|
}
|
||||||
|
}
|
||||||
48
tests/test_parse_inline_table.cpp
Normal file
48
tests/test_parse_inline_table.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_inline_table_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_inline_table)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{}", table());
|
||||||
|
{
|
||||||
|
table t;
|
||||||
|
t["foo"] = toml::value(42);
|
||||||
|
t["bar"] = toml::value("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{foo = 42, bar = \"baz\"}", t);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
table t;
|
||||||
|
table t_sub;
|
||||||
|
t_sub["name"] = toml::value("pug");
|
||||||
|
t["type"] = toml::value(t_sub);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{type.name = \"pug\"}", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_inline_table_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{}", value(table()));
|
||||||
|
{
|
||||||
|
table t;
|
||||||
|
t["foo"] = toml::value(42);
|
||||||
|
t["bar"] = toml::value("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{foo = 42, bar = \"baz\"}", value(t));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
table t;
|
||||||
|
table t_sub;
|
||||||
|
t_sub["name"] = toml::value("pug");
|
||||||
|
t["type"] = toml::value(t_sub);
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{type.name = \"pug\"}", value(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
92
tests/test_parse_integer.cpp
Normal file
92
tests/test_parse_integer.cpp
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_integer_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_decimal)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "1234", 1234);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "+1234", 1234);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "-1234", -1234);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0", 0);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "1_2_3_4", 1234);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "+1_2_3_4", +1234);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "-1_2_3_4", -1234);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "123_456_789", 123456789);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_decimal_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1234", toml::value( 1234));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1234", toml::value( 1234));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1234", toml::value( -1234));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0", toml::value( 0));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3_4", toml::value( 1234));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1_2_3_4", toml::value( +1234));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1_2_3_4", toml::value( -1234));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123_456_789", toml::value(123456789));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_hex)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEADBEEF", 0xDEADBEEF);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdeadbeef", 0xDEADBEEF);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEADbeef", 0xDEADBEEF);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEAD_BEEF", 0xDEADBEEF);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdead_beef", 0xDEADBEEF);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdead_BEEF", 0xDEADBEEF);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xFF", 0xFF);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0x00FF", 0xFF);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0x0000FF", 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_hex_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADBEEF", value(0xDEADBEEF));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdeadbeef", value(0xDEADBEEF));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADbeef", value(0xDEADBEEF));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEAD_BEEF", value(0xDEADBEEF));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_beef", value(0xDEADBEEF));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_BEEF", value(0xDEADBEEF));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xFF", value(0xFF));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x00FF", value(0xFF));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x0000FF", value(0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_oct)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0o777", 64*7+8*7+7);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0o7_7_7", 64*7+8*7+7);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0o007", 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_oct_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o777", value(64*7+8*7+7));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o7_7_7", value(64*7+8*7+7));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o007", value(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_bin)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0b10000", 16);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0b010000", 16);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0b01_00_00", 16);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_integer, "0b111111", 63);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_bin_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b10000", value(16));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b010000", value(16));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b01_00_00", value(16));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b111111", value(63));
|
||||||
|
}
|
||||||
63
tests/test_parse_key.cpp
Normal file
63
tests/test_parse_key.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_key_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_bare_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "barekey", std::vector<key>(1, "barekey"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(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(parse_key, "1234", std::vector<key>(1, "1234"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_quoted_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "\"127.0.0.1\"", std::vector<key>(1, "127.0.0.1" ));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "\"character encoding\"", std::vector<key>(1, "character encoding"));
|
||||||
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"", std::vector<key>(1, "\xCA\x8E\xC7\x9D\xCA\x9E"));
|
||||||
|
#else
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "\"ʎǝʞ\"", std::vector<key>(1, "ʎǝʞ" ));
|
||||||
|
#endif
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "'key2'", std::vector<key>(1, "key2" ));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "'quoted \"value\"'", std::vector<key>(1, "quoted \"value\"" ));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_dotted_key)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "physical";
|
||||||
|
keys[1] = "color";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "physical.color", keys);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "physical";
|
||||||
|
keys[1] = "shape";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "physical.shape", keys);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(4);
|
||||||
|
keys[0] = "x";
|
||||||
|
keys[1] = "y";
|
||||||
|
keys[2] = "z";
|
||||||
|
keys[3] = "w";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "x.y.z.w", keys);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "site";
|
||||||
|
keys[1] = "google.com";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_key, "site.\"google.com\"", keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
188
tests/test_parse_string.cpp
Normal file
188
tests/test_parse_string.cpp
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_string_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"The quick brown fox jumps over the lazy dog\"",
|
||||||
|
string("The quick brown fox jumps over the lazy dog", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\'The quick brown fox jumps over the lazy dog\'",
|
||||||
|
string("The quick brown fox jumps over the lazy dog", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
|
||||||
|
string("The quick brown fox jumps over the lazy dog", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"'''The quick brown fox \njumps over the lazy dog'''",
|
||||||
|
string("The quick brown fox \njumps over the lazy dog", string_t::literal));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_string_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"The quick brown fox jumps over the lazy dog\"",
|
||||||
|
toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\'The quick brown fox jumps over the lazy dog\'",
|
||||||
|
toml::value("The quick brown fox jumps over the lazy dog", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
|
||||||
|
toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"'''The quick brown fox \njumps over the lazy dog'''",
|
||||||
|
toml::value("The quick brown fox \njumps over the lazy dog", string_t::literal));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_basic_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
|
||||||
|
string("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"192.168.1.1\"",
|
||||||
|
string("192.168.1.1", string_t::basic));
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
|
||||||
|
string("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic));
|
||||||
|
#else
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"中国\"",
|
||||||
|
string("中国", string_t::basic));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"You'll hate me after this - #\"",
|
||||||
|
string("You'll hate me after this - #", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\" And when \\\"'s are in the along with # \\\"\"",
|
||||||
|
string(" And when \"'s are in the along with # \"", string_t::basic));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_basic_string_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
|
||||||
|
value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"192.168.1.1\"",
|
||||||
|
value("192.168.1.1", string_t::basic));
|
||||||
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
|
||||||
|
value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic));
|
||||||
|
#else
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"中国\"",
|
||||||
|
value("中国", string_t::basic));
|
||||||
|
#endif
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"You'll hate me after this - #\"",
|
||||||
|
value("You'll hate me after this - #", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\" And when \\\"'s are in the along with # \\\"\"",
|
||||||
|
value(" And when \"'s are in the along with # \"", string_t::basic));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_ml_basic_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"",
|
||||||
|
string("The quick brown fox jumps over the lazy dog.", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"",
|
||||||
|
string("The quick brown fox jumps over the lazy dog.", string_t::basic));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_ml_basic_string_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"",
|
||||||
|
value("The quick brown fox jumps over the lazy dog.", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"",
|
||||||
|
value("The quick brown fox jumps over the lazy dog.", string_t::basic));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_literal_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"'C:\\Users\\nodejs\\templates'",
|
||||||
|
string("C:\\Users\\nodejs\\templates", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"'\\\\ServerX\\admin$\\system32\\'",
|
||||||
|
string("\\\\ServerX\\admin$\\system32\\", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"'Tom \"Dubs\" Preston-Werner'",
|
||||||
|
string("Tom \"Dubs\" Preston-Werner", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"'<\\i\\c*\\s*>'",
|
||||||
|
string("<\\i\\c*\\s*>", string_t::literal));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_literal_string_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"'C:\\Users\\nodejs\\templates'",
|
||||||
|
value("C:\\Users\\nodejs\\templates", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"'\\\\ServerX\\admin$\\system32\\'",
|
||||||
|
value("\\\\ServerX\\admin$\\system32\\", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"'Tom \"Dubs\" Preston-Werner'",
|
||||||
|
value("Tom \"Dubs\" Preston-Werner", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"'<\\i\\c*\\s*>'",
|
||||||
|
value("<\\i\\c*\\s*>", string_t::literal));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_ml_literal_string)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"'''I [dw]on't need \\d{2} apples'''",
|
||||||
|
string("I [dw]on't need \\d{2} apples", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''",
|
||||||
|
string("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_ml_literal_string_value)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"'''I [dw]on't need \\d{2} apples'''",
|
||||||
|
value("I [dw]on't need \\d{2} apples", string_t::literal));
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
|
||||||
|
"'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''",
|
||||||
|
value("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_unicode_escape_sequence)
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"\\u03B1\\u03B2\\u03B3\"",
|
||||||
|
string("\xCE\xB1\xCE\xB2\xCE\xB3", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"\\U0001D7AA\"",
|
||||||
|
string("\xF0\x9D\x9E\xAA", string_t::basic));
|
||||||
|
#else
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"\\u03B1\\u03B2\\u03B3\"",
|
||||||
|
string("αβγ", string_t::basic));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_string,
|
||||||
|
"\"\\U0001D7AA\"",
|
||||||
|
string("𝞪", string_t::basic));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
50
tests/test_parse_table.cpp
Normal file
50
tests/test_parse_table.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_table_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include <toml/get.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_normal_table)
|
||||||
|
{
|
||||||
|
std::string table(
|
||||||
|
"key1 = \"value\"\n"
|
||||||
|
"key2 = 42\n"
|
||||||
|
"key3 = 3.14\n"
|
||||||
|
);
|
||||||
|
location<std::string> loc("test", table);
|
||||||
|
|
||||||
|
const auto result = toml::detail::parse_ml_table(loc);
|
||||||
|
BOOST_CHECK(result.is_ok());
|
||||||
|
const auto data = result.unwrap();
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<std::string >(data.at("key1")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(data.at("key2")), 42);
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<double >(data.at("key3")), 3.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_nested_table)
|
||||||
|
{
|
||||||
|
std::string table(
|
||||||
|
"a.b = \"value\"\n"
|
||||||
|
"a.c.d = 42\n"
|
||||||
|
);
|
||||||
|
location<std::string> loc("test", table);
|
||||||
|
|
||||||
|
const auto result = toml::detail::parse_ml_table(loc);
|
||||||
|
BOOST_CHECK(result.is_ok());
|
||||||
|
const auto data = result.unwrap();
|
||||||
|
|
||||||
|
const auto a = toml::get<toml::table>(data.at("a"));
|
||||||
|
const auto c = toml::get<toml::table>(a.at("c"));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<std::string >(a.at("b")), "value");
|
||||||
|
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(c.at("d")), 42);
|
||||||
|
}
|
||||||
117
tests/test_parse_table_key.cpp
Normal file
117
tests/test_parse_table_key.cpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
#define BOOST_TEST_MODULE "parse_table_key_test"
|
||||||
|
#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/parser.hpp>
|
||||||
|
#include "test_parse_aux.hpp"
|
||||||
|
|
||||||
|
using namespace toml;
|
||||||
|
using namespace detail;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_table_bare_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[barekey]", std::vector<key>(1, "barekey"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[bare-key]", std::vector<key>(1, "bare-key"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[bare_key]", std::vector<key>(1, "bare_key"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[1234]", std::vector<key>(1, "1234"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_table_quoted_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"127.0.0.1\"]", std::vector<key>(1, "127.0.0.1" ));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"character encoding\"]", std::vector<key>(1, "character encoding"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"ʎǝʞ\"]", std::vector<key>(1, "ʎǝʞ" ));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "['key2']", std::vector<key>(1, "key2" ));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "['quoted \"value\"']", std::vector<key>(1, "quoted \"value\"" ));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_table_dotted_key)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "physical";
|
||||||
|
keys[1] = "color";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[physical.color]", keys);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "physical";
|
||||||
|
keys[1] = "shape";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[physical.shape]", keys);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(4);
|
||||||
|
keys[0] = "x";
|
||||||
|
keys[1] = "y";
|
||||||
|
keys[2] = "z";
|
||||||
|
keys[3] = "w";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x.y.z.w]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x . y . z . w]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x. y .z. w]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x .y. z .w]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[ x. y .z . w ]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[ x . y . z . w ]", keys);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "site";
|
||||||
|
keys[1] = "google.com";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[site.\"google.com\"]", keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_array_of_table_bare_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[barekey]]", std::vector<key>(1, "barekey"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[bare-key]]", std::vector<key>(1, "bare-key"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[bare_key]]", std::vector<key>(1, "bare_key"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[1234]]", std::vector<key>(1, "1234"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_array_of_table_quoted_key)
|
||||||
|
{
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"127.0.0.1\"]]", std::vector<key>(1, "127.0.0.1" ));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"character encoding\"]]", std::vector<key>(1, "character encoding"));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"ʎǝʞ\"]]", std::vector<key>(1, "ʎǝʞ" ));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[['key2']]", std::vector<key>(1, "key2" ));
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[['quoted \"value\"']]", std::vector<key>(1, "quoted \"value\"" ));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_array_of_table_dotted_key)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "physical";
|
||||||
|
keys[1] = "color";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[physical.color]]", keys);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "physical";
|
||||||
|
keys[1] = "shape";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[physical.shape]]", keys);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(4);
|
||||||
|
keys[0] = "x";
|
||||||
|
keys[1] = "y";
|
||||||
|
keys[2] = "z";
|
||||||
|
keys[3] = "w";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x.y.z.w]]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x . y . z . w]]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x. y .z. w]]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x .y. z .w]]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[ x. y .z . w ]]", keys);
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[ x . y . z . w ]]", keys);
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::vector<key> keys(2);
|
||||||
|
keys[0] = "site";
|
||||||
|
keys[1] = "google.com";
|
||||||
|
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[site.\"google.com\"]]", keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,935 +0,0 @@
|
|||||||
#define BOOST_TEST_MODULE "test_parser"
|
|
||||||
#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/acceptor.hpp>
|
|
||||||
#include <toml/parser.hpp>
|
|
||||||
#include <toml/from_toml.hpp>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_basic_inline_string)
|
|
||||||
{
|
|
||||||
typedef toml::parse_basic_inline_string parser;
|
|
||||||
typedef toml::is_basic_inline_string<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("\"simple\"");
|
|
||||||
const std::string expected("simple");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("\"I'm a string. \\\"You can quote me\\\". Name\\tJos\\u00E9\\nLocation\\tSF.\"");
|
|
||||||
const std::string expected("I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF.");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("dummy");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_basic_multiline_string)
|
|
||||||
{
|
|
||||||
typedef toml::parse_basic_multiline_string parser;
|
|
||||||
typedef toml::is_basic_multiline_string<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
//XXX ifdef windows platform
|
|
||||||
const std::string source("\"\"\"\nRoses are red\nViolets are blue\"\"\"");
|
|
||||||
const std::string expected("Roses are red\nViolets are blue");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"");
|
|
||||||
const std::string expected("The quick brown fox jumps over the lazy dog.");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("\"\"\"\nThe quick brown \\\n fox jumps over \\\n the lazy dog.\\\n \"\"\"");
|
|
||||||
const std::string expected("The quick brown fox jumps over the lazy dog.");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("dummy");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_literal_inline_string)
|
|
||||||
{
|
|
||||||
typedef toml::parse_literal_inline_string parser;
|
|
||||||
typedef toml::is_literal_inline_string<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("'C:\\Users\\nodejs\\templates'");
|
|
||||||
const std::string expected("C:\\Users\\nodejs\\templates");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("'\\\\ServerX\\admin$\\system32\\'");
|
|
||||||
const std::string expected("\\\\ServerX\\admin$\\system32\\");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("'Tom \"Dubs\" Preston-Werner'");
|
|
||||||
const std::string expected("Tom \"Dubs\" Preston-Werner");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("'<\\i\\c*\\s*>'");
|
|
||||||
const std::string expected("<\\i\\c*\\s*>");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("dummy");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_literal_multiline_string)
|
|
||||||
{
|
|
||||||
typedef toml::parse_literal_multiline_string parser;
|
|
||||||
typedef toml::is_literal_multiline_string<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("'''I [dw]on't need \\d{2} apples'''");
|
|
||||||
const std::string expected("I [dw]on't need \\d{2} apples");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("'''\nThe first newline is \ntrimmed in raw strings.\n All other whitespace\n is preserved.'''");
|
|
||||||
const std::string expected("The first newline is \ntrimmed in raw strings.\n All other whitespace\n is preserved.");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("dummy");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_string)
|
|
||||||
{
|
|
||||||
typedef toml::parse_string parser;
|
|
||||||
typedef toml::is_string<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("\"string\"");
|
|
||||||
const std::string expected("string");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("\"\"\"string\"\"\"");
|
|
||||||
const std::string expected("string");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("'string'");
|
|
||||||
const std::string expected("string");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("'''string'''");
|
|
||||||
const std::string expected("string");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("dummy");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_integer)
|
|
||||||
{
|
|
||||||
typedef toml::parse_integer parser;
|
|
||||||
typedef toml::is_integer<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("42");
|
|
||||||
const toml::Integer expected(42);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("+42");
|
|
||||||
const toml::Integer expected(42);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("-42");
|
|
||||||
const toml::Integer expected(-42);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("-4_2");
|
|
||||||
const toml::Integer expected(-42);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("dummy");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_float)
|
|
||||||
{
|
|
||||||
typedef toml::parse_float parser;
|
|
||||||
typedef toml::is_float<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("42.0");
|
|
||||||
const toml::Float expected(42.0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("+42.0");
|
|
||||||
const toml::Float expected(42.0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("-42.0");
|
|
||||||
const toml::Float expected(-42.0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("-4_2.0");
|
|
||||||
const toml::Float expected(-42.0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("-42e0");
|
|
||||||
const toml::Float expected(-42.0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("-42.0e0");
|
|
||||||
const toml::Float expected(-42.0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("dummy");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("42");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_boolean)
|
|
||||||
{
|
|
||||||
typedef toml::parse_boolean parser;
|
|
||||||
typedef toml::is_boolean<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("true");
|
|
||||||
const toml::Boolean expected(true);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("false");
|
|
||||||
const toml::Boolean expected(false);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("dummy");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_local_time)
|
|
||||||
{
|
|
||||||
typedef toml::parse_local_time parser;
|
|
||||||
typedef toml::is_local_time<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("12:34:56");
|
|
||||||
const toml::Datetime expected(12, 34, 56, 0, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("12:34:56.7");
|
|
||||||
const toml::Datetime expected(12, 34, 56, 700, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("12:34:56.7891");
|
|
||||||
const toml::Datetime expected(12, 34, 56, 789, 100);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("10");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_local_date)
|
|
||||||
{
|
|
||||||
typedef toml::parse_local_date parser;
|
|
||||||
typedef toml::is_local_date<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27");
|
|
||||||
const toml::Datetime expected(1979, 9, 27);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("10");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_local_date_time)
|
|
||||||
{
|
|
||||||
typedef toml::parse_local_date_time parser;
|
|
||||||
typedef toml::is_local_date_time<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56.789000");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("1000-11-11");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_offset_date_time)
|
|
||||||
{
|
|
||||||
typedef toml::parse_offset_date_time parser;
|
|
||||||
typedef toml::is_offset_date_time<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56Z");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 0, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56.789000Z");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, 0, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56+07:30");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 7, 30);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56.789000+07:30");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, 7, 30);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56-07:30");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, -7, -30);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56.789000-07:30");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, -7, -30);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("1000-11-11");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_datetime)
|
|
||||||
{
|
|
||||||
typedef toml::parse_datetime parser;
|
|
||||||
typedef toml::is_datetime<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56Z");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 0, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27T12:34:56");
|
|
||||||
const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("1979-09-27");
|
|
||||||
const toml::Datetime expected(1979, 9, 27);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("12:34:56");
|
|
||||||
const toml::Datetime expected(12, 34, 56, 0, 0);
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK_EQUAL(result.first.get(), expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("12");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_array)
|
|
||||||
{
|
|
||||||
typedef toml::parse_array<toml::character> parser;
|
|
||||||
typedef toml::is_array<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("[1,2,3]");
|
|
||||||
const toml::Array expected{1, 2, 3};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[1, 2, 3]");
|
|
||||||
const toml::Array expected{1, 2, 3};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[ 1,2,3 ]");
|
|
||||||
const toml::Array expected{1, 2, 3};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[ 1 , 2 , 3 ]");
|
|
||||||
const toml::Array expected{1, 2, 3};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[ 1 \n,#comment\n 2 ,\n 3\n ]");
|
|
||||||
const toml::Array expected{1, 2, 3};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[ # empty array\n ]");
|
|
||||||
const toml::Array expected{};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[ \"] \", ' # ', \n']', # ] \n]");
|
|
||||||
const toml::Array expected{"] ", " # ", "]"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string source("[ \"Test #11 ]proved that\", 'Experiment #9 was a success' ]");
|
|
||||||
const toml::Array expected{"Test #11 ]proved that", "Experiment #9 was a success"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string source("[ \"Test #11 ]proved that\", 'Experiment #9 was a success' ]");
|
|
||||||
const toml::Array expected{"Test #11 ]proved that", "Experiment #9 was a success"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string source("[ [1,2,3] , ['a', 'b', 'c'] ]");
|
|
||||||
const toml::Array expected{{1,2,3}, {"a", "b", "c"}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string source("[ {foo=1}, {foo=1, bar=2.0}, {foo=1, bar=2.0, baz='str'} ]");
|
|
||||||
const toml::Array expected{{{"foo", 1}}, {{"foo", 1}, {"bar", 2.0}}, {{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[dummy]");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_inline_table)
|
|
||||||
{
|
|
||||||
typedef toml::parse_inline_table<toml::character> parser;
|
|
||||||
typedef toml::is_inline_table<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("{foo=1,bar=2.0,baz='str'}");
|
|
||||||
const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("{ foo=1, bar=2.0, baz='str' }");
|
|
||||||
const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("{ foo = 1, bar = 2.0, baz = 'str' }");
|
|
||||||
const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string source("{b=true, i=1, f=2.0, d=1907-03-02T07:32:00, s='str', a=[1,2,3], t={foo=1}}");
|
|
||||||
const toml::Table expected{{"b", true}, {"i", 1}, {"f", 2.0},
|
|
||||||
{"d", toml::Datetime(1907,3,2,7,32,0,0,0)},
|
|
||||||
{"s", "str"}, {"a", {1, 2, 3}},
|
|
||||||
{"t", {{"foo", 1}}}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("{dummy}");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(!result.first.ok());
|
|
||||||
BOOST_CHECK(result.second == source.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_barekey)
|
|
||||||
{
|
|
||||||
typedef toml::parse_barekey parser;
|
|
||||||
typedef toml::is_barekey<toml::character> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("hoge");
|
|
||||||
const toml::key expected("hoge");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("bare-key");
|
|
||||||
const toml::key expected("bare-key");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("bare_key");
|
|
||||||
const toml::key expected("bare_key");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("42");
|
|
||||||
const toml::key expected("42");
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_key_value_pair)
|
|
||||||
{
|
|
||||||
typedef toml::parse_key_value_pair<char> parser;
|
|
||||||
typedef toml::is_key_value_pair<char> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("key=1");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key", 1};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key =\t1");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key", 1};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = true");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key", true};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = -42");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key", -42};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = -42.0");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key", -42.};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = \"string\"");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key", "string"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = 1901-01-01T00:00:00");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key", toml::Datetime(1901, 1,1,0,0,0,0,0)};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = [1,2,3]");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key", {1,2,3}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = {foo=1,bar=2.0,baz='3'}");
|
|
||||||
const std::pair<toml::key, toml::value> expected{"key",
|
|
||||||
{{"foo", 1}, {"bar", 2.0}, {"baz", "3"}}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_table_definition)
|
|
||||||
{
|
|
||||||
typedef toml::parse_table_definition parser;
|
|
||||||
typedef toml::is_table_definition<char> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("[foo]");
|
|
||||||
const std::vector<toml::key> expected{"foo"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[foo.bar.baz]");
|
|
||||||
const std::vector<toml::key> expected{"foo", "bar", "baz"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[foo . bar. baz]");
|
|
||||||
const std::vector<toml::key> expected{"foo", "bar", "baz"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[foo . \"bar\" . baz]");
|
|
||||||
const std::vector<toml::key> expected{"foo", "bar", "baz"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[foo . \"b\\tar\" . baz]");
|
|
||||||
const std::vector<toml::key> expected{"foo", "b\tar", "baz"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_array_of_table_definition)
|
|
||||||
{
|
|
||||||
typedef toml::parse_array_of_table_definition parser;
|
|
||||||
typedef toml::is_array_of_table_definition<char> acceptor;
|
|
||||||
{
|
|
||||||
const std::string source("[[foo]]");
|
|
||||||
const std::vector<toml::key> expected{"foo"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[[foo.bar.baz]]");
|
|
||||||
const std::vector<toml::key> expected{"foo", "bar", "baz"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[[foo . bar. baz]]");
|
|
||||||
const std::vector<toml::key> expected{"foo", "bar", "baz"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[[foo . \"bar\" . baz]]");
|
|
||||||
const std::vector<toml::key> expected{"foo", "bar", "baz"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[[foo . \"b\\tar\" . baz]]");
|
|
||||||
const std::vector<toml::key> expected{"foo", "b\tar", "baz"};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result.first.ok());
|
|
||||||
BOOST_CHECK(result.first.get() == expected);
|
|
||||||
BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_parse_data)
|
|
||||||
{
|
|
||||||
typedef toml::parse_data parser;
|
|
||||||
{
|
|
||||||
const std::string source("#hogehoge");
|
|
||||||
const toml::Table expected{};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result == expected);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = 'value'");
|
|
||||||
const toml::Table expected{{"key", "value"}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result == expected);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("key = 'value' #hoge");
|
|
||||||
const toml::Table expected{{"key", "value"}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result == expected);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[table]\nkey = 'value' #hoge");
|
|
||||||
const toml::Table expected{{"table", {{"key", "value"}} }};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result == expected);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[table]\n\tkey = 'value'\n\t#hoge");
|
|
||||||
const toml::Table expected{{"table", {{"key", "value"}} }};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result == expected);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[table]\n\tkey = 'value'\n\t#hoge");
|
|
||||||
const toml::Table expected{{"table", {{"key", "value"}} }};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result == expected);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::string source("[nested.table]\n\tkey = 'value'\n\t#hoge");
|
|
||||||
const toml::Table expected{{"nested", {{"table", {{"key", "value"}}}}}};
|
|
||||||
const auto result = parser::invoke(source.cbegin(), source.cend());
|
|
||||||
BOOST_CHECK(result == expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
441
tests/test_result.cpp
Normal file
441
tests/test_result.cpp
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_result"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <toml/result.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_construct)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto s = toml::ok(42);
|
||||||
|
toml::result<int, std::string> result(s);
|
||||||
|
BOOST_CHECK(!!result);
|
||||||
|
BOOST_CHECK(result.is_ok());
|
||||||
|
BOOST_CHECK(!result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto s = toml::ok(42);
|
||||||
|
toml::result<int, std::string> result(s);
|
||||||
|
BOOST_CHECK(!!result);
|
||||||
|
BOOST_CHECK(result.is_ok());
|
||||||
|
BOOST_CHECK(!result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<int, std::string> result(toml::ok(42));
|
||||||
|
BOOST_CHECK(!!result);
|
||||||
|
BOOST_CHECK(result.is_ok());
|
||||||
|
BOOST_CHECK(!result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap(), 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto f = toml::err<std::string>("foobar");
|
||||||
|
toml::result<int, std::string> result(f);
|
||||||
|
BOOST_CHECK(!result);
|
||||||
|
BOOST_CHECK(!result.is_ok());
|
||||||
|
BOOST_CHECK(result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto f = toml::err<std::string>("foobar");
|
||||||
|
toml::result<int, std::string> result(f);
|
||||||
|
BOOST_CHECK(!result);
|
||||||
|
BOOST_CHECK(!result.is_ok());
|
||||||
|
BOOST_CHECK(result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
|
||||||
|
BOOST_CHECK(!result);
|
||||||
|
BOOST_CHECK(!result.is_ok());
|
||||||
|
BOOST_CHECK(result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_assignment)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
|
||||||
|
result = toml::ok(42);
|
||||||
|
BOOST_CHECK(!!result);
|
||||||
|
BOOST_CHECK(result.is_ok());
|
||||||
|
BOOST_CHECK(!result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
|
||||||
|
auto s = toml::ok(42);
|
||||||
|
result = s;
|
||||||
|
BOOST_CHECK(!!result);
|
||||||
|
BOOST_CHECK(result.is_ok());
|
||||||
|
BOOST_CHECK(!result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
|
||||||
|
const auto s = toml::ok(42);
|
||||||
|
result = s;
|
||||||
|
BOOST_CHECK(!!result);
|
||||||
|
BOOST_CHECK(result.is_ok());
|
||||||
|
BOOST_CHECK(!result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
|
||||||
|
result = toml::err<std::string>("hoge");
|
||||||
|
BOOST_CHECK(!result);
|
||||||
|
BOOST_CHECK(!result.is_ok());
|
||||||
|
BOOST_CHECK(result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
|
||||||
|
auto f = toml::err<std::string>("hoge");
|
||||||
|
result = f;
|
||||||
|
BOOST_CHECK(!result);
|
||||||
|
BOOST_CHECK(!result.is_ok());
|
||||||
|
BOOST_CHECK(result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
|
||||||
|
const auto f = toml::err<std::string>("hoge");
|
||||||
|
result = f;
|
||||||
|
BOOST_CHECK(!result);
|
||||||
|
BOOST_CHECK(!result.is_ok());
|
||||||
|
BOOST_CHECK(result.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_map)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::ok(42));
|
||||||
|
const auto mapped = result.map(
|
||||||
|
[](const int i) -> int {
|
||||||
|
return i * 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!!mapped);
|
||||||
|
BOOST_CHECK(mapped.is_ok());
|
||||||
|
BOOST_CHECK(!mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||||
|
const auto mapped = std::move(result).map(
|
||||||
|
[](std::unique_ptr<int> i) -> int {
|
||||||
|
return *i;
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!!mapped);
|
||||||
|
BOOST_CHECK(mapped.is_ok());
|
||||||
|
BOOST_CHECK(!mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = result.map(
|
||||||
|
[](const int i) -> int {
|
||||||
|
return i * 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!mapped);
|
||||||
|
BOOST_CHECK(!mapped.is_ok());
|
||||||
|
BOOST_CHECK(mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = std::move(result).map(
|
||||||
|
[](std::unique_ptr<int> i) -> int {
|
||||||
|
return *i;
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!mapped);
|
||||||
|
BOOST_CHECK(!mapped.is_ok());
|
||||||
|
BOOST_CHECK(mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_map_err)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::ok(42));
|
||||||
|
const auto mapped = result.map_err(
|
||||||
|
[](const std::string s) -> std::string {
|
||||||
|
return s + s;
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!!mapped);
|
||||||
|
BOOST_CHECK(mapped.is_ok());
|
||||||
|
BOOST_CHECK(!mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||||
|
const auto mapped = std::move(result).map_err(
|
||||||
|
[](const std::string s) -> std::string {
|
||||||
|
return s + s;
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!!mapped);
|
||||||
|
BOOST_CHECK(mapped.is_ok());
|
||||||
|
BOOST_CHECK(!mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(*(mapped.unwrap()), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = result.map_err(
|
||||||
|
[](const std::string s) -> std::string {
|
||||||
|
return s + s;
|
||||||
|
});
|
||||||
|
BOOST_CHECK(!mapped);
|
||||||
|
BOOST_CHECK(!mapped.is_ok());
|
||||||
|
BOOST_CHECK(mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<int, std::unique_ptr<std::string>>
|
||||||
|
result(toml::err(std::unique_ptr<std::string>(new std::string("hoge"))));
|
||||||
|
const auto mapped = std::move(result).map_err(
|
||||||
|
[](std::unique_ptr<std::string> p) -> std::string {
|
||||||
|
return *p;
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!mapped);
|
||||||
|
BOOST_CHECK(!mapped.is_ok());
|
||||||
|
BOOST_CHECK(mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_map_or_else)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::ok(42));
|
||||||
|
const auto mapped = result.map_or_else(
|
||||||
|
[](const int i) -> int {
|
||||||
|
return i * 2;
|
||||||
|
}, 54);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(mapped, 42 * 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||||
|
const auto mapped = std::move(result).map_or_else(
|
||||||
|
[](std::unique_ptr<int> i) -> int {
|
||||||
|
return *i;
|
||||||
|
}, 54);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(mapped, 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = result.map_or_else(
|
||||||
|
[](const int i) -> int {
|
||||||
|
return i * 2;
|
||||||
|
}, 54);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(mapped, 54);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = std::move(result).map_or_else(
|
||||||
|
[](std::unique_ptr<int> i) -> int {
|
||||||
|
return *i;
|
||||||
|
}, 54);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(mapped, 54);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_map_err_or_else)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::ok(42));
|
||||||
|
const auto mapped = result.map_err_or_else(
|
||||||
|
[](const std::string i) -> std::string {
|
||||||
|
return i + i;
|
||||||
|
}, "foobar");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(mapped, "foobar");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||||
|
const auto mapped = std::move(result).map_err_or_else(
|
||||||
|
[](const std::string i) -> std::string {
|
||||||
|
return i + i;
|
||||||
|
}, "foobar");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(mapped, "foobar");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = result.map_err_or_else(
|
||||||
|
[](const std::string i) -> std::string {
|
||||||
|
return i + i;
|
||||||
|
}, "foobar");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(mapped, "hogehoge");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = result.map_err_or_else(
|
||||||
|
[](const std::string i) -> std::string {
|
||||||
|
return i + i;
|
||||||
|
}, "foobar");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(mapped, "hogehoge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_and_then)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::ok(42));
|
||||||
|
const auto mapped = result.and_then(
|
||||||
|
[](const int i) -> toml::result<int, std::string> {
|
||||||
|
return toml::ok(i * 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!!mapped);
|
||||||
|
BOOST_CHECK(mapped.is_ok());
|
||||||
|
BOOST_CHECK(!mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||||
|
const auto mapped = std::move(result).and_then(
|
||||||
|
[](std::unique_ptr<int> i) -> toml::result<int, std::string> {
|
||||||
|
return toml::ok(*i);
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!!mapped);
|
||||||
|
BOOST_CHECK(mapped.is_ok());
|
||||||
|
BOOST_CHECK(!mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = result.and_then(
|
||||||
|
[](const int i) -> toml::result<int, std::string> {
|
||||||
|
return toml::ok(i * 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!mapped);
|
||||||
|
BOOST_CHECK(!mapped.is_ok());
|
||||||
|
BOOST_CHECK(mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = std::move(result).and_then(
|
||||||
|
[](std::unique_ptr<int> i) -> toml::result<int, std::string> {
|
||||||
|
return toml::ok(*i);
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!mapped);
|
||||||
|
BOOST_CHECK(!mapped.is_ok());
|
||||||
|
BOOST_CHECK(mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_or_else)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::ok(42));
|
||||||
|
const auto mapped = result.or_else(
|
||||||
|
[](const std::string& s) -> toml::result<int, std::string> {
|
||||||
|
return toml::err(s + s);
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!!mapped);
|
||||||
|
BOOST_CHECK(mapped.is_ok());
|
||||||
|
BOOST_CHECK(!mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::ok(std::unique_ptr<int>(new int(42))));
|
||||||
|
const auto mapped = std::move(result).or_else(
|
||||||
|
[](const std::string& s) -> toml::result<std::unique_ptr<int>, std::string> {
|
||||||
|
return toml::err(s + s);
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!!mapped);
|
||||||
|
BOOST_CHECK(mapped.is_ok());
|
||||||
|
BOOST_CHECK(!mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(*mapped.unwrap(), 42);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = result.or_else(
|
||||||
|
[](const std::string& s) -> toml::result<int, std::string> {
|
||||||
|
return toml::err(s + s);
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!mapped);
|
||||||
|
BOOST_CHECK(!mapped.is_ok());
|
||||||
|
BOOST_CHECK(mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::result<std::unique_ptr<int>, std::string>
|
||||||
|
result(toml::err<std::string>("hoge"));
|
||||||
|
const auto mapped = std::move(result).or_else(
|
||||||
|
[](const std::string& s) -> toml::result<std::unique_ptr<int>, std::string> {
|
||||||
|
return toml::err(s + s);
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_CHECK(!mapped);
|
||||||
|
BOOST_CHECK(!mapped.is_ok());
|
||||||
|
BOOST_CHECK(mapped.is_err());
|
||||||
|
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_and_or_other)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::result<int, std::string> r1(toml::ok(42));
|
||||||
|
const toml::result<int, std::string> r2(toml::err<std::string>("foo"));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(r1, r1.or_other(r2));
|
||||||
|
BOOST_CHECK_EQUAL(r2, r1.and_other(r2));
|
||||||
|
BOOST_CHECK_EQUAL(42, r1.or_other(r2).unwrap());
|
||||||
|
BOOST_CHECK_EQUAL("foo", r1.and_other(r2).unwrap_err());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1_gen = []() -> toml::result<int, std::string> {
|
||||||
|
return toml::ok(42);
|
||||||
|
};
|
||||||
|
auto r2_gen = []() -> toml::result<int, std::string> {
|
||||||
|
return toml::err<std::string>("foo");
|
||||||
|
};
|
||||||
|
const auto r3 = r1_gen();
|
||||||
|
const auto r4 = r2_gen();
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(r3, r1_gen().or_other (r2_gen()));
|
||||||
|
BOOST_CHECK_EQUAL(r4, r1_gen().and_other(r2_gen()));
|
||||||
|
BOOST_CHECK_EQUAL(42, r1_gen().or_other (r2_gen()).unwrap());
|
||||||
|
BOOST_CHECK_EQUAL("foo", r1_gen().and_other(r2_gen()).unwrap_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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,105 +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_to_toml_exact)
|
|
||||||
{
|
|
||||||
toml::Boolean b(true);
|
|
||||||
toml::Integer i(42);
|
|
||||||
toml::Float f(3.14);
|
|
||||||
toml::String s("hoge");
|
|
||||||
toml::Datetime d(std::chrono::system_clock::now());
|
|
||||||
toml::Array a;
|
|
||||||
a.emplace_back(2);
|
|
||||||
a.emplace_back(7);
|
|
||||||
a.emplace_back(1);
|
|
||||||
a.emplace_back(8);
|
|
||||||
a.emplace_back(2);
|
|
||||||
toml::Table t;
|
|
||||||
t.emplace("val1", true);
|
|
||||||
t.emplace("val2", 42);
|
|
||||||
t.emplace("val3", 3.14);
|
|
||||||
t.emplace("val4", "piyo");
|
|
||||||
|
|
||||||
auto v1 = toml::to_toml(b);
|
|
||||||
auto v2 = toml::to_toml(i);
|
|
||||||
auto v3 = toml::to_toml(f);
|
|
||||||
auto v4 = toml::to_toml(s);
|
|
||||||
auto v5 = toml::to_toml(d);
|
|
||||||
auto v6 = toml::to_toml(a);
|
|
||||||
auto v7 = toml::to_toml(t);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Integer);
|
|
||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Float);
|
|
||||||
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::String);
|
|
||||||
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::Datetime);
|
|
||||||
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::Array);
|
|
||||||
BOOST_CHECK_EQUAL(v7.type(), toml::value_t::Table);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean >(), b);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer >(), i);
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Float >(), f);
|
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String >(), s);
|
|
||||||
const auto& ar = v6.cast<toml::value_t::Array>();
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(0).cast<toml::value_t::Integer>(), a.at(0).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(1).cast<toml::value_t::Integer>(), a.at(1).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(2).cast<toml::value_t::Integer>(), a.at(2).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(3).cast<toml::value_t::Integer>(), a.at(3).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(4).cast<toml::value_t::Integer>(), a.at(4).cast<toml::value_t::Integer>());
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_to_toml_castable)
|
|
||||||
{
|
|
||||||
auto v1 = toml::to_toml(true);
|
|
||||||
auto v2 = toml::to_toml(42ul);
|
|
||||||
auto v3 = toml::to_toml(3.14f);
|
|
||||||
auto v4 = toml::to_toml("hoge");
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Integer);
|
|
||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Float);
|
|
||||||
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::String);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean >(), true);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer >(), 42);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v3.cast<toml::value_t::Float >(), 3.14, 1e-5);
|
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String >(), "hoge");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_to_toml_initializer_list)
|
|
||||||
{
|
|
||||||
toml::value v1 = toml::to_toml({3,1,4,1,5});
|
|
||||||
toml::value v2 = toml::to_toml({{"hoge", 1}, {"piyo", 3.14}, {"fuga", "string"}});
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Table);
|
|
||||||
|
|
||||||
const auto& ar = v1.cast<toml::value_t::Array>();
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(0).cast<toml::value_t::Integer>(), 3);
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(1).cast<toml::value_t::Integer>(), 1);
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(2).cast<toml::value_t::Integer>(), 4);
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(3).cast<toml::value_t::Integer>(), 1);
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(4).cast<toml::value_t::Integer>(), 5);
|
|
||||||
|
|
||||||
const auto& tb = v2.cast<toml::value_t::Table>();
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(tb.at("hoge").type(), toml::value_t::Integer);
|
|
||||||
BOOST_CHECK_EQUAL(tb.at("piyo").type(), toml::value_t::Float);
|
|
||||||
BOOST_CHECK_EQUAL(tb.at("fuga").type(), toml::value_t::String);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(tb.at("hoge").cast<toml::value_t::Integer>(), 1);
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(tb.at("piyo").cast<toml::value_t::Float>(), 3.14, 1e-3);
|
|
||||||
BOOST_CHECK_EQUAL(tb.at("fuga").cast<toml::value_t::String>(), "string");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
#define BOOST_TEST_NO_LIB
|
#define BOOST_TEST_NO_LIB
|
||||||
#include <boost/test/included/unit_test.hpp>
|
#include <boost/test/included/unit_test.hpp>
|
||||||
#endif
|
#endif
|
||||||
#include <toml.hpp>
|
#include <toml/types.hpp>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
@@ -74,16 +74,11 @@ BOOST_AUTO_TEST_CASE(test_is_xxx)
|
|||||||
BOOST_CHECK(toml::detail::is_container<std_array_type>::value);
|
BOOST_CHECK(toml::detail::is_container<std_array_type>::value);
|
||||||
BOOST_CHECK(toml::detail::is_container<std::set<dummy_type>>::value);
|
BOOST_CHECK(toml::detail::is_container<std::set<dummy_type>>::value);
|
||||||
BOOST_CHECK(toml::detail::is_container<std::unordered_set<std::string>>::value);
|
BOOST_CHECK(toml::detail::is_container<std::unordered_set<std::string>>::value);
|
||||||
BOOST_CHECK(toml::detail::is_container<std_map_type>::value);
|
|
||||||
BOOST_CHECK(toml::detail::is_container<std_unordered_map_type>::value);
|
|
||||||
BOOST_CHECK(toml::detail::is_container<dummy_container<dummy_type>>::value);
|
BOOST_CHECK(toml::detail::is_container<dummy_container<dummy_type>>::value);
|
||||||
|
|
||||||
|
BOOST_CHECK(!toml::detail::is_container<std_map_type>::value);
|
||||||
|
BOOST_CHECK(!toml::detail::is_container<std_unordered_map_type>::value);
|
||||||
|
|
||||||
BOOST_CHECK(toml::detail::is_map<std_map_type>::value);
|
BOOST_CHECK(toml::detail::is_map<std_map_type>::value);
|
||||||
BOOST_CHECK(toml::detail::is_map<std_unordered_map_type>::value);
|
BOOST_CHECK(toml::detail::is_map<std_unordered_map_type>::value);
|
||||||
|
|
||||||
BOOST_CHECK(toml::detail::is_key_convertible<std_map_type>::value);
|
|
||||||
BOOST_CHECK(toml::detail::is_key_convertible<std_unordered_map_type>::value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(test_resize)
|
|||||||
thrown = true;
|
thrown = true;
|
||||||
}
|
}
|
||||||
BOOST_CHECK(!thrown);
|
BOOST_CHECK(!thrown);
|
||||||
BOOST_CHECK_EQUAL(v.size(), 10);
|
BOOST_CHECK_EQUAL(v.size(), 10u);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(test_resize)
|
|||||||
thrown = true;
|
thrown = true;
|
||||||
}
|
}
|
||||||
BOOST_CHECK(!thrown);
|
BOOST_CHECK(!thrown);
|
||||||
BOOST_CHECK_EQUAL(a.size(), 15);
|
BOOST_CHECK_EQUAL(a.size(), 15u);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -62,3 +62,21 @@ BOOST_AUTO_TEST_CASE(test_resize)
|
|||||||
BOOST_CHECK(thrown);
|
BOOST_CHECK(thrown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_concat_to_string)
|
||||||
|
{
|
||||||
|
const std::string cat = toml::concat_to_string("foo", "bar", 42);
|
||||||
|
BOOST_CHECK(cat == "foobar42");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_from_string)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const std::string str("123");
|
||||||
|
BOOST_CHECK_EQUAL(toml::from_string<int>(str, 0), 123);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const std::string str("01");
|
||||||
|
BOOST_CHECK_EQUAL(toml::from_string<int>(str, 0), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,223 +5,680 @@
|
|||||||
#define BOOST_TEST_NO_LIB
|
#define BOOST_TEST_NO_LIB
|
||||||
#include <boost/test/included/unit_test.hpp>
|
#include <boost/test/included/unit_test.hpp>
|
||||||
#endif
|
#endif
|
||||||
#include <toml.hpp>
|
#include <toml/value.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_exact_constructor)
|
BOOST_AUTO_TEST_CASE(test_value_boolean)
|
||||||
{
|
{
|
||||||
toml::Boolean b(true);
|
toml::value v1(true);
|
||||||
toml::Integer i(42);
|
toml::value v2(false);
|
||||||
toml::Float f(3.14);
|
|
||||||
toml::String s("hoge");
|
|
||||||
toml::Datetime d(std::chrono::system_clock::now());
|
|
||||||
toml::Array a;
|
|
||||||
a.emplace_back(2);
|
|
||||||
a.emplace_back(7);
|
|
||||||
a.emplace_back(1);
|
|
||||||
a.emplace_back(8);
|
|
||||||
a.emplace_back(2);
|
|
||||||
toml::Table t;
|
|
||||||
t.emplace("val1", true);
|
|
||||||
t.emplace("val2", 42);
|
|
||||||
t.emplace("val3", 3.14);
|
|
||||||
t.emplace("val4", "piyo");
|
|
||||||
|
|
||||||
toml::value v1(b);
|
|
||||||
toml::value v2(i);
|
|
||||||
toml::value v3(f);
|
|
||||||
toml::value v4(s);
|
|
||||||
toml::value v5(d);
|
|
||||||
toml::value v6(a);
|
|
||||||
toml::value v7(t);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
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(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_boolean());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
||||||
|
|
||||||
|
v1 = false;
|
||||||
|
v2 = true;
|
||||||
|
|
||||||
|
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(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_boolean());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
||||||
|
|
||||||
|
toml::value v3(v1);
|
||||||
|
toml::value v4(v2);
|
||||||
|
BOOST_CHECK(v3 == v1);
|
||||||
|
BOOST_CHECK(v4 == v2);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v3.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v4.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v3.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(v4.cast<toml::value_t::Boolean>(), true);
|
||||||
|
|
||||||
|
toml::value v5(std::move(v1));
|
||||||
|
toml::value v6(std::move(v2));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v5.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v6.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v5.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(v6.cast<toml::value_t::Boolean>(), true);
|
||||||
|
|
||||||
|
v1 = 42;
|
||||||
|
v2 = 3.14;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Integer);
|
||||||
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Float);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Integer));
|
||||||
|
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||||
|
BOOST_CHECK(v1.is<toml::Integer>());
|
||||||
|
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(v2.cast<toml::value_t::Float>(), 3.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_integer)
|
||||||
|
{
|
||||||
|
toml::value v1(-42);
|
||||||
|
toml::value v2(42u);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Integer);
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Integer);
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Integer);
|
||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Float);
|
BOOST_CHECK(v1.is(toml::value_t::Integer));
|
||||||
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::String);
|
BOOST_CHECK(v2.is(toml::value_t::Integer));
|
||||||
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::Datetime);
|
BOOST_CHECK(v1.is<toml::Integer>());
|
||||||
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::Array);
|
BOOST_CHECK(v2.is<toml::Integer>());
|
||||||
BOOST_CHECK_EQUAL(v7.type(), toml::value_t::Table);
|
BOOST_CHECK(v1.is_integer());
|
||||||
|
BOOST_CHECK(v2.is_integer());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean >(), b);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), -42);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer >(), i);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), 42u);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Float >(), f);
|
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String >(), s);
|
|
||||||
const auto& ar = v6.cast<toml::value_t::Array>();
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(0).cast<toml::value_t::Integer>(), a.at(0).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(1).cast<toml::value_t::Integer>(), a.at(1).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(2).cast<toml::value_t::Integer>(), a.at(2).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(3).cast<toml::value_t::Integer>(), a.at(3).cast<toml::value_t::Integer>());
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(4).cast<toml::value_t::Integer>(), a.at(4).cast<toml::value_t::Integer>());
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_convertible_constructor)
|
v1 = 54;
|
||||||
{
|
v2 = -54;
|
||||||
int i(42);
|
|
||||||
float f(3.14);
|
|
||||||
const char* s = "hoge";
|
|
||||||
|
|
||||||
toml::value v1(i);
|
|
||||||
toml::value v2(f);
|
|
||||||
toml::value v3(s);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Integer);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Integer);
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Float);
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Integer);
|
||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::String);
|
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(v1.is_integer());
|
||||||
|
BOOST_CHECK(v2.is_integer());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer >(), i);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Float >(), f);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), -54);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String >(), s);
|
|
||||||
|
toml::value v3(v1);
|
||||||
|
toml::value v4(v2);
|
||||||
|
BOOST_CHECK(v3 == v1);
|
||||||
|
BOOST_CHECK(v4 == v2);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Integer);
|
||||||
|
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::Integer);
|
||||||
|
BOOST_CHECK(v3.is(toml::value_t::Integer));
|
||||||
|
BOOST_CHECK(v4.is(toml::value_t::Integer));
|
||||||
|
BOOST_CHECK(v3.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(v4.cast<toml::value_t::Integer>(), -54);
|
||||||
|
|
||||||
|
toml::value v5(std::move(v1));
|
||||||
|
toml::value v6(std::move(v2));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::Integer);
|
||||||
|
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::Integer);
|
||||||
|
BOOST_CHECK(v5.is(toml::value_t::Integer));
|
||||||
|
BOOST_CHECK(v6.is(toml::value_t::Integer));
|
||||||
|
BOOST_CHECK(v5.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(v6.cast<toml::value_t::Integer>(), -54);
|
||||||
|
|
||||||
|
v1 = true;
|
||||||
|
v2 = 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(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_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_copy_move_constructor)
|
BOOST_AUTO_TEST_CASE(test_value_float)
|
||||||
{
|
{
|
||||||
toml::Array a;
|
toml::value v1(3.14);
|
||||||
toml::Table t;
|
toml::value v2(3.14f);
|
||||||
toml::value v1(true);
|
|
||||||
toml::value v2(42);
|
|
||||||
toml::value v3(3.14);
|
|
||||||
toml::value v4("hoge");
|
|
||||||
toml::value v5(std::chrono::system_clock::now());
|
|
||||||
toml::value v6(a);
|
|
||||||
toml::value v7(t);
|
|
||||||
|
|
||||||
toml::value u1(v1);
|
|
||||||
toml::value u2(v2);
|
|
||||||
toml::value u3(v3);
|
|
||||||
toml::value u4(v4);
|
|
||||||
toml::value u5(v5);
|
|
||||||
toml::value u6(v6);
|
|
||||||
toml::value u7(v7);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u1.type(), toml::value_t::Boolean);
|
|
||||||
BOOST_CHECK_EQUAL(u2.type(), toml::value_t::Integer);
|
|
||||||
BOOST_CHECK_EQUAL(u3.type(), toml::value_t::Float);
|
|
||||||
BOOST_CHECK_EQUAL(u4.type(), toml::value_t::String);
|
|
||||||
BOOST_CHECK_EQUAL(u5.type(), toml::value_t::Datetime);
|
|
||||||
BOOST_CHECK_EQUAL(u6.type(), toml::value_t::Array);
|
|
||||||
BOOST_CHECK_EQUAL(u7.type(), toml::value_t::Table);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(u1.cast<toml::value_t::Boolean >(), true);
|
|
||||||
BOOST_CHECK_EQUAL(u2.cast<toml::value_t::Integer >(), 42);
|
|
||||||
BOOST_CHECK_EQUAL(u3.cast<toml::value_t::Float >(), 3.14);
|
|
||||||
BOOST_CHECK_EQUAL(u4.cast<toml::value_t::String >(), "hoge");
|
|
||||||
|
|
||||||
toml::value w1(std::move(v1));
|
|
||||||
toml::value w2(std::move(v2));
|
|
||||||
toml::value w3(std::move(v3));
|
|
||||||
toml::value w4(std::move(v4));
|
|
||||||
toml::value w5(std::move(v5));
|
|
||||||
toml::value w6(std::move(v6));
|
|
||||||
toml::value w7(std::move(v7));
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(w1.type(), toml::value_t::Boolean);
|
|
||||||
BOOST_CHECK_EQUAL(w2.type(), toml::value_t::Integer);
|
|
||||||
BOOST_CHECK_EQUAL(w3.type(), toml::value_t::Float);
|
|
||||||
BOOST_CHECK_EQUAL(w4.type(), toml::value_t::String);
|
|
||||||
BOOST_CHECK_EQUAL(w5.type(), toml::value_t::Datetime);
|
|
||||||
BOOST_CHECK_EQUAL(w6.type(), toml::value_t::Array);
|
|
||||||
BOOST_CHECK_EQUAL(w7.type(), toml::value_t::Table);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(w1.cast<toml::value_t::Boolean >(), true);
|
|
||||||
BOOST_CHECK_EQUAL(w2.cast<toml::value_t::Integer >(), 42);
|
|
||||||
BOOST_CHECK_EQUAL(w3.cast<toml::value_t::Float >(), 3.14);
|
|
||||||
BOOST_CHECK_EQUAL(w4.cast<toml::value_t::String >(), "hoge");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_copy_move_substitution)
|
|
||||||
{
|
|
||||||
toml::Boolean b(true);
|
|
||||||
toml::Integer i(42);
|
|
||||||
toml::Float f(3.14);
|
|
||||||
toml::String s("hoge");
|
|
||||||
toml::Datetime d(std::chrono::system_clock::now());
|
|
||||||
toml::Array a;
|
|
||||||
a.emplace_back(2);
|
|
||||||
a.emplace_back(7);
|
|
||||||
a.emplace_back(1);
|
|
||||||
a.emplace_back(8);
|
|
||||||
a.emplace_back(2);
|
|
||||||
toml::Table t;
|
|
||||||
t.emplace("val1", true);
|
|
||||||
t.emplace("val2", 42);
|
|
||||||
t.emplace("val3", 3.14);
|
|
||||||
t.emplace("val4", "piyo");
|
|
||||||
|
|
||||||
toml::value v1(b);
|
|
||||||
toml::value v2(i);
|
|
||||||
toml::value v3(f);
|
|
||||||
toml::value v4(s);
|
|
||||||
toml::value v5(d);
|
|
||||||
toml::value v6(a);
|
|
||||||
toml::value v7(t);
|
|
||||||
|
|
||||||
v1 = i;
|
|
||||||
v2 = f;
|
|
||||||
v3 = s;
|
|
||||||
v4 = d;
|
|
||||||
v5 = a;
|
|
||||||
v6 = t;
|
|
||||||
v7 = b;
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Integer);
|
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Float);
|
|
||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::String);
|
|
||||||
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::Datetime);
|
|
||||||
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::Array);
|
|
||||||
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::Table);
|
|
||||||
BOOST_CHECK_EQUAL(v7.type(), toml::value_t::Boolean);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v7.cast<toml::value_t::Boolean >(), b);
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer >(), i);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Float >(), f);
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String >(), s);
|
|
||||||
|
|
||||||
v1 = std::move(f);
|
|
||||||
v2 = std::move(s);
|
|
||||||
v3 = std::move(d);
|
|
||||||
v4 = std::move(a);
|
|
||||||
v5 = std::move(t);
|
|
||||||
v6 = std::move(b);
|
|
||||||
v7 = std::move(i);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Float);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Float);
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::String);
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Float);
|
||||||
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Datetime);
|
BOOST_CHECK(v1.is(toml::value_t::Float));
|
||||||
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::Array);
|
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||||
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::Table);
|
BOOST_CHECK(v1.is<toml::Float>());
|
||||||
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::Boolean);
|
BOOST_CHECK(v2.is<toml::Float>());
|
||||||
BOOST_CHECK_EQUAL(v7.type(), toml::value_t::Integer);
|
BOOST_CHECK(v1.is_float());
|
||||||
|
BOOST_CHECK(v2.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Boolean >(), b);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Float>(), 3.14);
|
||||||
BOOST_CHECK_EQUAL(v7.cast<toml::value_t::Integer >(), i);
|
BOOST_CHECK_CLOSE_FRACTION(v2.cast<toml::value_t::Float>(), 3.14, 1e-2);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Float >(), f);
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String >(), s);
|
v1 = 2.718f;
|
||||||
|
v2 = 2.718;
|
||||||
|
|
||||||
|
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(v1.is_float());
|
||||||
|
BOOST_CHECK(v2.is_float());
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
toml::value v3(v1);
|
||||||
|
toml::value v4(v2);
|
||||||
|
BOOST_CHECK(v3 == v1);
|
||||||
|
BOOST_CHECK(v4 == v2);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Float);
|
||||||
|
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::Float);
|
||||||
|
BOOST_CHECK(v3.is(toml::value_t::Float));
|
||||||
|
BOOST_CHECK(v4.is(toml::value_t::Float));
|
||||||
|
BOOST_CHECK(v3.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_EQUAL(v4.cast<toml::value_t::Float>(), 2.718);
|
||||||
|
|
||||||
|
toml::value v5(std::move(v1));
|
||||||
|
toml::value v6(std::move(v2));
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::Float);
|
||||||
|
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::Float);
|
||||||
|
BOOST_CHECK(v5.is(toml::value_t::Float));
|
||||||
|
BOOST_CHECK(v6.is(toml::value_t::Float));
|
||||||
|
BOOST_CHECK(v5.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_EQUAL(v6.cast<toml::value_t::Float>(), 2.718);
|
||||||
|
|
||||||
|
v1 = true;
|
||||||
|
v2 = 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(v1.is_boolean());
|
||||||
|
BOOST_CHECK(v2.is_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_initializer_list)
|
BOOST_AUTO_TEST_CASE(test_value_string)
|
||||||
{
|
{
|
||||||
toml::value v1{3,1,4,1,5};
|
toml::value v1(std::string("foo"));
|
||||||
toml::value v2{{"hoge", 1}, {"piyo", 3.14}, {"fuga", "string"}};
|
toml::value v2(std::string("foo"), toml::string_t::literal);
|
||||||
|
toml::value v3("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(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(v2.cast<toml::value_t::String>(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "foo");
|
||||||
|
|
||||||
|
v1 = "bar";
|
||||||
|
v2 = "bar";
|
||||||
|
v3 = "bar";
|
||||||
|
|
||||||
|
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_string());
|
||||||
|
BOOST_CHECK(v2.is_string());
|
||||||
|
BOOST_CHECK(v3.is_string());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.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");
|
||||||
|
|
||||||
|
toml::value v4(v1);
|
||||||
|
toml::value v5(v2);
|
||||||
|
toml::value v6(v3);
|
||||||
|
BOOST_CHECK(v4 == v1);
|
||||||
|
BOOST_CHECK(v5 == v2);
|
||||||
|
BOOST_CHECK(v6 == v3);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK(v4.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v5.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v6.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v4.is<toml::String>());
|
||||||
|
BOOST_CHECK(v5.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(v5.cast<toml::value_t::String>(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::String>(), "bar");
|
||||||
|
|
||||||
|
v4.cast<toml::value_t::String>().str.at(2) = 'z';
|
||||||
|
v5.cast<toml::value_t::String>().str.at(2) = 'z';
|
||||||
|
v6.cast<toml::value_t::String>().str.at(2) = 'z';
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v4.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK_EQUAL(v5.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK_EQUAL(v6.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK(v4.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v5.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v6.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v4.is<toml::String>());
|
||||||
|
BOOST_CHECK(v5.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(v5.cast<toml::value_t::String>(), "baz");
|
||||||
|
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::String>(), "baz");
|
||||||
|
|
||||||
|
v1 = true;
|
||||||
|
v2 = true;
|
||||||
|
v3 = true;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v2.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v3.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v2.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(v2.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_local_date)
|
||||||
|
{
|
||||||
|
toml::value v1(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(v1.is_local_date());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
||||||
|
toml::local_date(2018, toml::month_t::Jan, 31));
|
||||||
|
|
||||||
|
v1 = toml::local_date(2018, toml::month_t::Apr, 1);
|
||||||
|
|
||||||
|
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(v1.is_local_date());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
|
||||||
|
toml::value v2(v1);
|
||||||
|
BOOST_CHECK(v2 == v1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::LocalDate);
|
||||||
|
BOOST_CHECK(v2.is(toml::value_t::LocalDate));
|
||||||
|
BOOST_CHECK(v2.is<toml::LocalDate>());
|
||||||
|
BOOST_CHECK(v2.is_local_date());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalDate>(),
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
|
||||||
|
v1 = true;
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_local_time)
|
||||||
|
{
|
||||||
|
toml::value v1(toml::local_time(12, 30, 45));
|
||||||
|
toml::value v2(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(v1.is_local_time());
|
||||||
|
BOOST_CHECK(v2.is_local_time());
|
||||||
|
|
||||||
|
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>());
|
||||||
|
|
||||||
|
v1 = toml::local_time(1, 30, 0, /*ms*/ 100, /*us*/ 0);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalTime);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::LocalTime));
|
||||||
|
BOOST_CHECK(v1.is<toml::LocalTime>());
|
||||||
|
BOOST_CHECK(v1.is_local_time());
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
||||||
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
|
||||||
|
toml::value v3(v1);
|
||||||
|
BOOST_CHECK(v3 == v1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::LocalTime);
|
||||||
|
BOOST_CHECK(v3.is(toml::value_t::LocalTime));
|
||||||
|
BOOST_CHECK(v3.is<toml::LocalTime>());
|
||||||
|
BOOST_CHECK(v3.is_local_time());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::LocalTime>(),
|
||||||
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
|
||||||
|
v1 = true;
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
||||||
|
{
|
||||||
|
toml::value v1(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(v1.is_local_datetime());
|
||||||
|
|
||||||
|
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)));
|
||||||
|
|
||||||
|
v1 = toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30));
|
||||||
|
|
||||||
|
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(v1.is_local_datetime());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDatetime>(),
|
||||||
|
toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30)));
|
||||||
|
|
||||||
|
toml::value v2(v1);
|
||||||
|
BOOST_CHECK(v2 == v1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::LocalDatetime);
|
||||||
|
BOOST_CHECK(v2.is(toml::value_t::LocalDatetime));
|
||||||
|
BOOST_CHECK(v2.is<toml::LocalDatetime>());
|
||||||
|
BOOST_CHECK(v2.is_local_datetime());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalDatetime>(),
|
||||||
|
toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30)));
|
||||||
|
|
||||||
|
v1 = true;
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
||||||
|
{
|
||||||
|
toml::value v1(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(v1.is_offset_datetime());
|
||||||
|
|
||||||
|
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)
|
||||||
|
));
|
||||||
|
|
||||||
|
v1 = toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30),
|
||||||
|
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(v1.is_offset_datetime());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::OffsetDatetime>(),
|
||||||
|
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);
|
||||||
|
BOOST_CHECK(v2 == v1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::OffsetDatetime);
|
||||||
|
BOOST_CHECK(v2.is(toml::value_t::OffsetDatetime));
|
||||||
|
BOOST_CHECK(v2.is<toml::OffsetDatetime>());
|
||||||
|
BOOST_CHECK(v2.is_offset_datetime());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::OffsetDatetime>(),
|
||||||
|
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;
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_array)
|
||||||
|
{
|
||||||
|
std::vector<int> v{1,2,3,4,5};
|
||||||
|
toml::value v1(v);
|
||||||
|
toml::value v2{6,7,8,9,0};
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
|
||||||
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Table);
|
BOOST_CHECK(v1.is(toml::value_t::Array));
|
||||||
|
BOOST_CHECK(v1.is<toml::Array>());
|
||||||
|
BOOST_CHECK(v1.is_array());
|
||||||
|
|
||||||
const auto& ar = v1.cast<toml::value_t::Array>();
|
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Array);
|
||||||
BOOST_CHECK_EQUAL(ar.at(0).cast<toml::value_t::Integer>(), 3);
|
BOOST_CHECK(v2.is(toml::value_t::Array));
|
||||||
BOOST_CHECK_EQUAL(ar.at(1).cast<toml::value_t::Integer>(), 1);
|
BOOST_CHECK(v2.is<toml::Array>());
|
||||||
BOOST_CHECK_EQUAL(ar.at(2).cast<toml::value_t::Integer>(), 4);
|
BOOST_CHECK(v2.is_array());
|
||||||
BOOST_CHECK_EQUAL(ar.at(3).cast<toml::value_t::Integer>(), 1);
|
|
||||||
BOOST_CHECK_EQUAL(ar.at(4).cast<toml::value_t::Integer>(), 5);
|
|
||||||
|
|
||||||
const auto& tb = v2.cast<toml::value_t::Table>();
|
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(tb.at("hoge").type(), toml::value_t::Integer);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
||||||
BOOST_CHECK_EQUAL(tb.at("piyo").type(), toml::value_t::Float);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
||||||
BOOST_CHECK_EQUAL(tb.at("fuga").type(), toml::value_t::String);
|
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_CHECK_EQUAL(tb.at("hoge").cast<toml::value_t::Integer>(), 1);
|
v1 = {6,7,8,9,0};
|
||||||
BOOST_CHECK_CLOSE_FRACTION(tb.at("piyo").cast<toml::value_t::Float>(), 3.14, 1e-3);
|
v2 = v;
|
||||||
BOOST_CHECK_EQUAL(tb.at("fuga").cast<toml::value_t::String>(), "string");
|
|
||||||
|
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(v1.is_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(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(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(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(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(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(4).cast<toml::value_t::Integer>(), 5);
|
||||||
|
|
||||||
|
toml::value v3(v1);
|
||||||
|
BOOST_CHECK(v3 == v1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Array);
|
||||||
|
BOOST_CHECK(v3.is(toml::value_t::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(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(3).cast<toml::value_t::Integer>(), 9);
|
||||||
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
||||||
|
|
||||||
|
v1 = true;
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_table)
|
||||||
|
{
|
||||||
|
toml::value v1{{"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(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("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");
|
||||||
|
|
||||||
|
v1 = toml::table{{"foo", 2.71}, {"bar", 54}, {"baz", "quux"}};
|
||||||
|
|
||||||
|
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(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("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");
|
||||||
|
|
||||||
|
toml::value v3(v1);
|
||||||
|
BOOST_CHECK(v3 == v1);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::Table);
|
||||||
|
BOOST_CHECK(v3.is(toml::value_t::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("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");
|
||||||
|
|
||||||
|
v1 = true;
|
||||||
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
|
BOOST_CHECK(v1.is_boolean());
|
||||||
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
#define BOOST_TEST_MODULE "test_value_operator"
|
|
||||||
#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_equal)
|
|
||||||
{
|
|
||||||
toml::Boolean b(true);
|
|
||||||
toml::Integer i(42);
|
|
||||||
toml::Float f(3.14);
|
|
||||||
toml::String s("hoge");
|
|
||||||
toml::Datetime d(std::chrono::system_clock::now());
|
|
||||||
toml::Array a;
|
|
||||||
a.emplace_back(2);
|
|
||||||
a.emplace_back(7);
|
|
||||||
a.emplace_back(1);
|
|
||||||
a.emplace_back(8);
|
|
||||||
a.emplace_back(2);
|
|
||||||
toml::Table t;
|
|
||||||
t.emplace("val1", true);
|
|
||||||
t.emplace("val2", 42);
|
|
||||||
t.emplace("val3", 3.14);
|
|
||||||
t.emplace("val4", "piyo");
|
|
||||||
|
|
||||||
toml::value v1(b);
|
|
||||||
toml::value v2(i);
|
|
||||||
toml::value v3(f);
|
|
||||||
toml::value v4(s);
|
|
||||||
toml::value v5(d);
|
|
||||||
toml::value v6(a);
|
|
||||||
toml::value v7(t);
|
|
||||||
|
|
||||||
toml::value u1(b);
|
|
||||||
toml::value u2(i);
|
|
||||||
toml::value u3(f);
|
|
||||||
toml::value u4(s);
|
|
||||||
toml::value u5(d);
|
|
||||||
toml::value u6(a);
|
|
||||||
toml::value u7(t);
|
|
||||||
|
|
||||||
const bool b1 = v1 == u1;
|
|
||||||
const bool b2 = v2 == u2;
|
|
||||||
const bool b3 = v3 == u3;
|
|
||||||
const bool b4 = v4 == u4;
|
|
||||||
const bool b5 = v5 == u5;
|
|
||||||
const bool b6 = v6 == u6;
|
|
||||||
const bool b7 = v7 == u7;
|
|
||||||
|
|
||||||
BOOST_CHECK(b1);
|
|
||||||
BOOST_CHECK(b2);
|
|
||||||
BOOST_CHECK(b3);
|
|
||||||
BOOST_CHECK(b4);
|
|
||||||
BOOST_CHECK(b5);
|
|
||||||
BOOST_CHECK(b6);
|
|
||||||
BOOST_CHECK(b7);
|
|
||||||
|
|
||||||
{
|
|
||||||
const bool n1 = v1 != u1;
|
|
||||||
const bool n2 = v2 != u2;
|
|
||||||
const bool n3 = v3 != u3;
|
|
||||||
const bool n4 = v4 != u4;
|
|
||||||
const bool n5 = v5 != u5;
|
|
||||||
const bool n6 = v6 != u6;
|
|
||||||
const bool n7 = v7 != u7;
|
|
||||||
|
|
||||||
BOOST_CHECK(!n1);
|
|
||||||
BOOST_CHECK(!n2);
|
|
||||||
BOOST_CHECK(!n3);
|
|
||||||
BOOST_CHECK(!n4);
|
|
||||||
BOOST_CHECK(!n5);
|
|
||||||
BOOST_CHECK(!n6);
|
|
||||||
BOOST_CHECK(!n7);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const bool n1 = v1 == u2;
|
|
||||||
const bool n2 = v2 == u3;
|
|
||||||
const bool n3 = v3 == u4;
|
|
||||||
const bool n4 = v4 == u5;
|
|
||||||
const bool n5 = v5 == u6;
|
|
||||||
const bool n6 = v6 == u7;
|
|
||||||
const bool n7 = v7 == u1;
|
|
||||||
|
|
||||||
BOOST_CHECK(!n1);
|
|
||||||
BOOST_CHECK(!n2);
|
|
||||||
BOOST_CHECK(!n3);
|
|
||||||
BOOST_CHECK(!n4);
|
|
||||||
BOOST_CHECK(!n5);
|
|
||||||
BOOST_CHECK(!n6);
|
|
||||||
BOOST_CHECK(!n7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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"
|
||||||
|
|
||||||
|
|||||||
@@ -1,777 +0,0 @@
|
|||||||
#ifndef TOML11_ACCEPTOR
|
|
||||||
#define TOML11_ACCEPTOR
|
|
||||||
#include <type_traits>
|
|
||||||
#include <iterator>
|
|
||||||
#include <limits>
|
|
||||||
#include "exception.hpp"
|
|
||||||
|
|
||||||
namespace toml
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename charT, charT c>
|
|
||||||
struct is_character
|
|
||||||
{
|
|
||||||
typedef charT value_type;
|
|
||||||
constexpr static value_type target = c;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
constexpr static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
return iter == end ? iter : *iter == c ? std::next(iter) : iter;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename charT, charT lw, charT up>
|
|
||||||
struct is_in_range
|
|
||||||
{
|
|
||||||
typedef charT value_type;
|
|
||||||
constexpr static value_type upper = up;
|
|
||||||
constexpr static value_type lower = lw;
|
|
||||||
static_assert(lower <= upper, "lower <= upper");
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
constexpr static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
return iter == end ? iter :
|
|
||||||
(lower <= *iter && *iter <= upper) ? std::next(iter) : iter;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename headT, typename ... condT>
|
|
||||||
struct is_one_of
|
|
||||||
{
|
|
||||||
typedef typename headT::value_type value_type;
|
|
||||||
static_assert(
|
|
||||||
std::is_same<value_type, typename is_one_of<condT...>::value_type>::value,
|
|
||||||
"different value_type");
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
const Iterator tmp = headT::invoke(iter, end);
|
|
||||||
return (tmp != iter) ? tmp : is_one_of<condT...>::invoke(iter, end);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template<typename tailT>
|
|
||||||
struct is_one_of<tailT>
|
|
||||||
{
|
|
||||||
typedef typename tailT::value_type value_type;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
const Iterator tmp = tailT::invoke(iter, end);
|
|
||||||
return (tmp != iter) ? tmp : iter;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// just a wrapper for maybe_ignored
|
|
||||||
template<typename condT>
|
|
||||||
struct is_ignorable
|
|
||||||
{
|
|
||||||
typedef typename condT::value_type value_type;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
const Iterator tmp = condT::invoke(iter, end);
|
|
||||||
return (tmp != iter) ? tmp : iter;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename condT>
|
|
||||||
struct maybe_ignored : std::false_type{};
|
|
||||||
template<typename condT>
|
|
||||||
struct maybe_ignored<is_ignorable<condT>> : std::true_type{};
|
|
||||||
|
|
||||||
template<typename headT, typename ... condT>
|
|
||||||
struct is_chain_of_impl
|
|
||||||
{
|
|
||||||
typedef typename headT::value_type value_type;
|
|
||||||
static_assert(std::is_same<value_type,
|
|
||||||
typename is_chain_of_impl<condT...>::value_type>::value,
|
|
||||||
"different value_type");
|
|
||||||
|
|
||||||
constexpr static bool ignorable = maybe_ignored<headT>::value;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end, Iterator rollback)
|
|
||||||
{
|
|
||||||
const Iterator tmp = headT::invoke(iter, end);
|
|
||||||
return (tmp == iter && !ignorable) ? rollback :
|
|
||||||
is_chain_of_impl<condT...>::invoke(tmp, end, rollback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename tailT>
|
|
||||||
struct is_chain_of_impl<tailT>
|
|
||||||
{
|
|
||||||
typedef typename tailT::value_type value_type;
|
|
||||||
constexpr static bool ignorable = maybe_ignored<tailT>::value;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end, Iterator rollback)
|
|
||||||
{
|
|
||||||
const Iterator tmp = tailT::invoke(iter, end);
|
|
||||||
return (tmp == iter) ? (ignorable ? iter : rollback) : tmp;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename headT, typename ...condT>
|
|
||||||
struct is_chain_of
|
|
||||||
{
|
|
||||||
typedef typename is_chain_of_impl<headT, condT...>::value_type value_type;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
return is_chain_of_impl<headT, condT...>::invoke(iter, end, iter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr inline std::size_t repeat_infinite(){return 0ul;}
|
|
||||||
|
|
||||||
template<typename condT, std::size_t N>
|
|
||||||
struct is_repeat_of
|
|
||||||
{
|
|
||||||
typedef typename condT::value_type value_type;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
const Iterator rollback = iter;
|
|
||||||
Iterator tmp;
|
|
||||||
for(auto i=0ul; i<N; ++i)
|
|
||||||
{
|
|
||||||
tmp = condT::invoke(iter, end);
|
|
||||||
if(tmp == iter) return rollback;
|
|
||||||
iter = tmp;
|
|
||||||
}
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename condT>
|
|
||||||
struct is_repeat_of<condT, 0>
|
|
||||||
{
|
|
||||||
typedef typename condT::value_type value_type;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
Iterator tmp = condT::invoke(iter, end);
|
|
||||||
while(tmp != iter)
|
|
||||||
{
|
|
||||||
iter = tmp;
|
|
||||||
tmp = condT::invoke(iter, end);
|
|
||||||
}
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename headT, typename ... tailT>
|
|
||||||
struct is_none_of
|
|
||||||
{
|
|
||||||
typedef typename headT::value_type value_type;
|
|
||||||
static_assert(
|
|
||||||
std::is_same<value_type, typename is_one_of<tailT...>::value_type>::value,
|
|
||||||
"different value_type");
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
const Iterator tmp = headT::invoke(iter, end);
|
|
||||||
return (tmp != iter) ? iter : is_none_of<tailT...>::invoke(iter, end);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename tailT>
|
|
||||||
struct is_none_of<tailT>
|
|
||||||
{
|
|
||||||
typedef typename tailT::value_type value_type;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
const Iterator tmp = tailT::invoke(iter, end);
|
|
||||||
return (tmp != iter) ? iter : std::next(iter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename notT, typename butT>
|
|
||||||
struct is_not_but
|
|
||||||
{
|
|
||||||
typedef typename notT::value_type value_type;
|
|
||||||
static_assert(
|
|
||||||
std::is_same<value_type, typename butT::value_type>::value,
|
|
||||||
"different value type");
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
return (iter != notT::invoke(iter, end)) ? iter : butT::invoke(iter, end);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_space = is_character<charT, ' '>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_tab = is_character<charT, '\t'>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_number = is_in_range<charT, '0', '9'>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_lowercase = is_in_range<charT, 'a', 'z'>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_uppercase = is_in_range<charT, 'A', 'Z'>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_alphabet = is_one_of<is_lowercase<charT>, is_uppercase<charT>>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_hex = is_one_of<is_number<charT>, is_in_range<charT, 'a', 'f'>,
|
|
||||||
is_in_range<charT, 'A', 'F'>>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_whitespace = is_one_of<is_space<charT>, is_tab<charT>>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_any_num_of_ws =
|
|
||||||
is_ignorable<is_repeat_of<is_whitespace<charT>, repeat_infinite()>>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_newline = is_one_of<is_character<charT, '\n'>,
|
|
||||||
is_chain_of<is_character<charT, '\r'>, is_character<charT, '\n'>>>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_barekey_component = is_one_of<is_alphabet<charT>, is_number<charT>,
|
|
||||||
is_character<charT, '_'>, is_character<charT, '-'>>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_barekey = is_repeat_of<is_barekey_component<charT>, repeat_infinite()>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_comment =
|
|
||||||
is_chain_of<
|
|
||||||
is_character<charT, '#'>,
|
|
||||||
is_repeat_of<is_none_of<is_newline<charT>>, repeat_infinite()>,
|
|
||||||
is_newline<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_basic_inline_string_component =
|
|
||||||
is_one_of<
|
|
||||||
is_none_of< is_in_range<charT, '\0', '\31'>, is_character<charT, '\"'>,
|
|
||||||
is_character<charT, '\\'>, is_newline<charT>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, '\"'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, '\\'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'b'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 't'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'n'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'f'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'r'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'u'>,
|
|
||||||
is_repeat_of<is_hex<charT>, 4>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'U'>,
|
|
||||||
is_repeat_of<is_hex<charT>, 8>>
|
|
||||||
>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_basic_inline_string =
|
|
||||||
is_not_but<
|
|
||||||
is_repeat_of<is_character<charT, '\"'>, 3>, // not multiline
|
|
||||||
is_chain_of<
|
|
||||||
is_character<charT, '\"'>,
|
|
||||||
is_ignorable<is_repeat_of<is_basic_inline_string_component<charT>,
|
|
||||||
repeat_infinite()>>,
|
|
||||||
is_character<charT, '\"'>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_basic_multiline_string_component =
|
|
||||||
is_one_of<
|
|
||||||
is_none_of< is_in_range<charT, '\0', '\31'>,
|
|
||||||
is_repeat_of<is_character<charT, '\"'>, 3>,
|
|
||||||
is_character<charT, '\\'>>,
|
|
||||||
is_newline<charT>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_newline<charT>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, '\"'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, '\\'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'b'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 't'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'n'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'f'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'r'>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'u'>,
|
|
||||||
is_repeat_of<is_hex<charT>, 4>>,
|
|
||||||
is_chain_of<is_character<charT, '\\'>, is_character<charT, 'U'>,
|
|
||||||
is_repeat_of<is_hex<charT>, 8>>
|
|
||||||
>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_basic_multiline_string =
|
|
||||||
is_chain_of<
|
|
||||||
is_repeat_of<is_character<charT, '\"'>, 3>,
|
|
||||||
is_ignorable<is_repeat_of<is_basic_multiline_string_component<charT>,
|
|
||||||
repeat_infinite()>>,
|
|
||||||
is_repeat_of<is_character<charT, '\"'>, 3>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_literal_inline_string_component =
|
|
||||||
is_none_of<is_in_range<charT, '\0', '\31'>, is_character<charT, '\''>>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_literal_inline_string =
|
|
||||||
is_not_but<
|
|
||||||
is_repeat_of<is_character<charT, '\''>, 3>,
|
|
||||||
is_chain_of<
|
|
||||||
is_character<charT, '\''>,
|
|
||||||
is_ignorable<is_repeat_of<is_literal_inline_string_component<charT>,
|
|
||||||
repeat_infinite()>>,
|
|
||||||
is_character<charT, '\''>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_literal_multiline_string_component =
|
|
||||||
is_one_of<
|
|
||||||
is_none_of<is_in_range<charT, '\0', '\31'>,
|
|
||||||
is_repeat_of<is_character<charT, '\''>, 3>>,
|
|
||||||
is_newline<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_literal_multiline_string =
|
|
||||||
is_chain_of<
|
|
||||||
is_repeat_of<is_character<charT, '\''>, 3>,
|
|
||||||
is_ignorable<is_repeat_of<is_literal_multiline_string_component<charT>,
|
|
||||||
repeat_infinite()>>,
|
|
||||||
is_repeat_of<is_character<charT, '\''>, 3>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_string =
|
|
||||||
is_one_of<
|
|
||||||
is_basic_inline_string<charT>,
|
|
||||||
is_basic_multiline_string<charT>,
|
|
||||||
is_literal_inline_string<charT>,
|
|
||||||
is_literal_multiline_string<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_sign = is_one_of<is_character<charT, '+'>, is_character<charT, '-'>>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_nonzero_number = is_in_range<charT, '1', '9'>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_integer_component =
|
|
||||||
is_not_but<
|
|
||||||
is_repeat_of<is_character<charT, '_'>, 2>,
|
|
||||||
is_one_of<
|
|
||||||
is_character<charT, '_'>, is_number<charT>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_integer =
|
|
||||||
is_chain_of<
|
|
||||||
is_ignorable<is_sign<charT>>,
|
|
||||||
is_one_of<
|
|
||||||
is_character<charT, '0'>,
|
|
||||||
is_chain_of<
|
|
||||||
is_nonzero_number<charT>,
|
|
||||||
is_ignorable<is_repeat_of<is_integer_component<charT>,
|
|
||||||
repeat_infinite()>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_fractional_part =
|
|
||||||
is_chain_of<
|
|
||||||
is_character<charT, '.'>,
|
|
||||||
is_repeat_of<is_integer_component<charT>, repeat_infinite()>
|
|
||||||
>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_exponent_part =
|
|
||||||
is_chain_of<
|
|
||||||
is_one_of<is_character<charT, 'e'>, is_character<charT, 'E'>>,
|
|
||||||
is_integer<charT>
|
|
||||||
>;
|
|
||||||
template<typename charT>
|
|
||||||
using is_float =
|
|
||||||
is_one_of<
|
|
||||||
is_chain_of<
|
|
||||||
is_integer<charT>,
|
|
||||||
is_fractional_part<charT>,
|
|
||||||
is_exponent_part<charT>
|
|
||||||
>,
|
|
||||||
is_chain_of<
|
|
||||||
is_integer<charT>,
|
|
||||||
is_fractional_part<charT>
|
|
||||||
>,
|
|
||||||
is_chain_of<
|
|
||||||
is_integer<charT>,
|
|
||||||
is_exponent_part<charT>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_boolean =
|
|
||||||
is_one_of<
|
|
||||||
is_chain_of<
|
|
||||||
is_character<charT, 't'>,
|
|
||||||
is_character<charT, 'r'>,
|
|
||||||
is_character<charT, 'u'>,
|
|
||||||
is_character<charT, 'e'>
|
|
||||||
>,
|
|
||||||
is_chain_of<
|
|
||||||
is_character<charT, 'f'>,
|
|
||||||
is_character<charT, 'a'>,
|
|
||||||
is_character<charT, 'l'>,
|
|
||||||
is_character<charT, 's'>,
|
|
||||||
is_character<charT, 'e'>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_local_time =
|
|
||||||
is_chain_of<
|
|
||||||
is_repeat_of<is_number<charT>, 2>,
|
|
||||||
is_character<charT, ':'>,
|
|
||||||
is_repeat_of<is_number<charT>, 2>,
|
|
||||||
is_character<charT, ':'>,
|
|
||||||
is_repeat_of<is_number<charT>, 2>,
|
|
||||||
is_ignorable<
|
|
||||||
is_chain_of<
|
|
||||||
is_character<charT, '.'>,
|
|
||||||
is_repeat_of<is_number<charT>, repeat_infinite()>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_local_date =
|
|
||||||
is_chain_of<
|
|
||||||
is_repeat_of<is_number<charT>, 4>,
|
|
||||||
is_character<charT, '-'>,
|
|
||||||
is_repeat_of<is_number<charT>, 2>,
|
|
||||||
is_character<charT, '-'>,
|
|
||||||
is_repeat_of<is_number<charT>, 2>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_local_date_time =
|
|
||||||
is_chain_of<
|
|
||||||
is_local_date<charT>,
|
|
||||||
is_character<charT, 'T'>,
|
|
||||||
is_local_time<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_offset =
|
|
||||||
is_one_of<
|
|
||||||
is_character<charT, 'Z'>,
|
|
||||||
is_chain_of<
|
|
||||||
is_sign<charT>,
|
|
||||||
is_repeat_of<is_number<charT>, 2>,
|
|
||||||
is_character<charT, ':'>,
|
|
||||||
is_repeat_of<is_number<charT>, 2>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_offset_date_time =
|
|
||||||
is_chain_of<
|
|
||||||
is_local_date_time<charT>,
|
|
||||||
is_offset<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_datetime =
|
|
||||||
is_one_of<
|
|
||||||
is_offset_date_time<charT>,
|
|
||||||
is_local_date_time<charT>,
|
|
||||||
is_local_date<charT>,
|
|
||||||
is_local_time<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_fundamental_type =
|
|
||||||
is_one_of<
|
|
||||||
is_basic_inline_string<charT>,
|
|
||||||
is_basic_multiline_string<charT>,
|
|
||||||
is_literal_inline_string<charT>,
|
|
||||||
is_literal_multiline_string<charT>,
|
|
||||||
is_offset_date_time<charT>,
|
|
||||||
is_local_date_time<charT>,
|
|
||||||
is_local_date<charT>,
|
|
||||||
is_local_time<charT>,
|
|
||||||
is_boolean<charT>,
|
|
||||||
is_float<charT>,
|
|
||||||
is_integer<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_skippable_in_array =
|
|
||||||
is_repeat_of<
|
|
||||||
is_one_of<is_whitespace<charT>, is_newline<charT>, is_comment<charT>>,
|
|
||||||
repeat_infinite()
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
struct is_inline_table;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_key =
|
|
||||||
is_one_of<
|
|
||||||
is_barekey<charT>,
|
|
||||||
is_string<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename charT, typename is_array_component>
|
|
||||||
using is_fixed_type_array =
|
|
||||||
is_chain_of<
|
|
||||||
is_character<charT, '['>,
|
|
||||||
is_ignorable<
|
|
||||||
is_repeat_of<
|
|
||||||
is_chain_of<
|
|
||||||
is_ignorable<is_skippable_in_array<charT>>,
|
|
||||||
is_array_component,
|
|
||||||
is_ignorable<is_skippable_in_array<charT>>,
|
|
||||||
is_character<charT, ','>
|
|
||||||
>,
|
|
||||||
repeat_infinite()
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
is_ignorable<
|
|
||||||
is_chain_of<
|
|
||||||
is_ignorable<is_skippable_in_array<charT>>,
|
|
||||||
is_array_component,
|
|
||||||
is_ignorable<is_skippable_in_array<charT>>,
|
|
||||||
is_ignorable<is_character<charT, ','>>
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
is_ignorable<is_skippable_in_array<charT>>,
|
|
||||||
is_character<charT, ']'>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
struct is_array
|
|
||||||
{
|
|
||||||
typedef charT value_type;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
return is_one_of<
|
|
||||||
is_fixed_type_array<charT, is_boolean<charT>>,
|
|
||||||
is_fixed_type_array<charT, is_integer<charT>>,
|
|
||||||
is_fixed_type_array<charT, is_float<charT>>,
|
|
||||||
is_fixed_type_array<charT, is_string<charT>>,
|
|
||||||
is_fixed_type_array<charT, is_datetime<charT>>,
|
|
||||||
is_fixed_type_array<charT, is_array<charT>>,
|
|
||||||
is_fixed_type_array<charT, is_inline_table<charT>>
|
|
||||||
>::invoke(iter, end);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
struct is_inline_table
|
|
||||||
{
|
|
||||||
typedef charT value_type;
|
|
||||||
|
|
||||||
template<typename Iterator, class = typename std::enable_if<
|
|
||||||
std::is_same<typename std::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type>::value>::type>
|
|
||||||
static Iterator invoke(Iterator iter, Iterator end)
|
|
||||||
{
|
|
||||||
typedef is_one_of<is_fundamental_type<charT>,
|
|
||||||
is_array<charT>, is_inline_table<charT>> is_component;
|
|
||||||
|
|
||||||
typedef is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_key<charT>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_character<charT, '='>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_component,
|
|
||||||
is_any_num_of_ws<charT>
|
|
||||||
> is_inline_key_value_pair;
|
|
||||||
|
|
||||||
typedef is_chain_of<
|
|
||||||
is_character<charT, '{'>,
|
|
||||||
is_ignorable<
|
|
||||||
is_repeat_of<
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_inline_key_value_pair,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_character<charT, ','>
|
|
||||||
>,
|
|
||||||
repeat_infinite()
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
is_ignorable<
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_inline_key_value_pair,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_ignorable<is_character<charT, ','>>
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_character<charT, '}'>
|
|
||||||
> entity;
|
|
||||||
return entity::invoke(iter, end);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_value =
|
|
||||||
is_one_of<is_fundamental_type<charT>, is_array<charT>, is_inline_table<charT>>;
|
|
||||||
|
|
||||||
// []
|
|
||||||
template<typename charT>
|
|
||||||
using is_table_definition =
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_character<charT, '['>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_key<charT>,
|
|
||||||
is_ignorable<
|
|
||||||
is_repeat_of<
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_character<charT, '.'>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_key<charT>,
|
|
||||||
is_any_num_of_ws<charT>
|
|
||||||
>,
|
|
||||||
repeat_infinite()>
|
|
||||||
>,
|
|
||||||
is_character<charT, ']'>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_array_of_table_definition =
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_repeat_of<is_character<charT, '['>, 2>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_key<charT>,
|
|
||||||
is_ignorable<
|
|
||||||
is_repeat_of<
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_character<charT, '.'>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_key<charT>,
|
|
||||||
is_any_num_of_ws<charT>
|
|
||||||
>,
|
|
||||||
repeat_infinite()>
|
|
||||||
>,
|
|
||||||
is_repeat_of<is_character<charT, ']'>, 2>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_key_value_pair =
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_key<charT>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_character<charT, '='>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_value<charT>,
|
|
||||||
is_any_num_of_ws<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_empty_line =
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_one_of<is_comment<charT>, is_newline<charT>>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_empty_lines =
|
|
||||||
is_repeat_of<
|
|
||||||
is_chain_of<
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_one_of<is_comment<charT>, is_newline<charT>>
|
|
||||||
>,
|
|
||||||
repeat_infinite()
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_table_contents =
|
|
||||||
is_repeat_of<
|
|
||||||
is_one_of<
|
|
||||||
is_empty_lines<charT>,
|
|
||||||
is_chain_of<
|
|
||||||
is_key_value_pair<charT>,
|
|
||||||
is_one_of<
|
|
||||||
is_comment<charT>,
|
|
||||||
is_newline<charT>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
repeat_infinite()
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_standard_table =
|
|
||||||
is_chain_of<
|
|
||||||
is_table_definition<charT>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_one_of<is_comment<charT>, is_newline<charT>>,
|
|
||||||
is_table_contents<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_array_of_table =
|
|
||||||
is_chain_of<
|
|
||||||
is_array_of_table_definition<charT>,
|
|
||||||
is_any_num_of_ws<charT>,
|
|
||||||
is_one_of<is_comment<charT>, is_newline<charT>>,
|
|
||||||
is_table_contents<charT>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename charT>
|
|
||||||
using is_toml_data =
|
|
||||||
is_chain_of<
|
|
||||||
is_ignorable<is_table_contents<charT>>,
|
|
||||||
is_ignorable<
|
|
||||||
is_repeat_of<
|
|
||||||
is_one_of<
|
|
||||||
is_standard_table<charT>,
|
|
||||||
is_array_of_table<charT>
|
|
||||||
>,
|
|
||||||
repeat_infinite()
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
|
|
||||||
}//toml
|
|
||||||
#endif// TOML11_ACCEPTOR
|
|
||||||
364
toml/combinator.hpp
Normal file
364
toml/combinator.hpp
Normal file
@@ -0,0 +1,364 @@
|
|||||||
|
// Copyright Toru Niina 2017.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_COMBINATOR_HPP
|
||||||
|
#define TOML11_COMBINATOR_HPP
|
||||||
|
#include "traits.hpp"
|
||||||
|
#include "result.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
#include "region.hpp"
|
||||||
|
#include <type_traits>
|
||||||
|
#include <iterator>
|
||||||
|
#include <limits>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
// they scans characters and returns region if it matches to the condition.
|
||||||
|
// when they fail, it does not change the location.
|
||||||
|
// in lexer.hpp, these are used.
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// to output character as an error message.
|
||||||
|
inline std::string show_char(const char c)
|
||||||
|
{
|
||||||
|
// It supress an error that occurs only in Debug mode of MSVC++ on Windows.
|
||||||
|
// I'm not completely sure but they check the value of char to be in the
|
||||||
|
// range [0, 256) and some of the COMPLETELY VALID utf-8 character sometimes
|
||||||
|
// has negative value (if char has sign). So here it re-interprets c as
|
||||||
|
// unsigned char through pointer. In general, converting pointer to a
|
||||||
|
// pointer that has different type cause UB, but `(signed|unsigned)?char`
|
||||||
|
// are one of the exceptions. Converting pointer only to char and std::byte
|
||||||
|
// (c++17) are valid.
|
||||||
|
if(std::isgraph(*reinterpret_cast<unsigned char const*>(std::addressof(c))))
|
||||||
|
{
|
||||||
|
return std::string(1, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "0x" << std::hex << std::setfill('0') << std::setw(2)
|
||||||
|
<< static_cast<int>(c);
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<char C>
|
||||||
|
struct character
|
||||||
|
{
|
||||||
|
static constexpr char target = C;
|
||||||
|
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
|
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
||||||
|
const auto first = loc.iter();
|
||||||
|
|
||||||
|
const char c = *(loc.iter());
|
||||||
|
if(c != target)
|
||||||
|
{
|
||||||
|
return err(concat_to_string("expected '", show_char(target),
|
||||||
|
"' but got '", show_char(c), "'."));
|
||||||
|
}
|
||||||
|
loc.advance(); // update location
|
||||||
|
|
||||||
|
return ok(region<Cont>(loc, first, loc.iter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string pattern() {return show_char(target);}
|
||||||
|
};
|
||||||
|
template<char C>
|
||||||
|
constexpr char character<C>::target;
|
||||||
|
|
||||||
|
// closed interval [Low, Up]. both Low and Up are included.
|
||||||
|
template<char Low, char Up>
|
||||||
|
struct in_range
|
||||||
|
{
|
||||||
|
// assuming ascii part of UTF-8...
|
||||||
|
static_assert(Low <= Up, "lower bound should be less than upper bound.");
|
||||||
|
|
||||||
|
static constexpr char upper = Up;
|
||||||
|
static constexpr char lower = Low;
|
||||||
|
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
|
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
||||||
|
const auto first = loc.iter();
|
||||||
|
|
||||||
|
const char c = *(loc.iter());
|
||||||
|
if(c < lower || upper < c)
|
||||||
|
{
|
||||||
|
return err(concat_to_string("expected character in range "
|
||||||
|
"[", show_char(lower), ", ", show_char(upper), "] but got ",
|
||||||
|
"'", show_char(c), "'."));
|
||||||
|
}
|
||||||
|
|
||||||
|
loc.advance();
|
||||||
|
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>::lower;
|
||||||
|
|
||||||
|
// keep iterator if `Combinator` matches. otherwise, increment `iter` by 1 char.
|
||||||
|
// for detecting invalid characters, like control sequences in toml string.
|
||||||
|
template<typename Combinator>
|
||||||
|
struct exclude
|
||||||
|
{
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
|
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
||||||
|
auto first = loc.iter();
|
||||||
|
|
||||||
|
auto rslt = Combinator::invoke(loc);
|
||||||
|
if(rslt.is_ok())
|
||||||
|
{
|
||||||
|
loc.reset(first);
|
||||||
|
return err(concat_to_string(
|
||||||
|
"invalid pattern (", Combinator::pattern(), ") appeared ",
|
||||||
|
rslt.unwrap().str()));
|
||||||
|
}
|
||||||
|
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
||||||
|
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.
|
||||||
|
template<typename Combinator>
|
||||||
|
struct maybe
|
||||||
|
{
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
|
const auto rslt = Combinator::invoke(loc);
|
||||||
|
if(rslt.is_ok())
|
||||||
|
{
|
||||||
|
return rslt;
|
||||||
|
}
|
||||||
|
return ok(region<Cont>(loc));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string pattern()
|
||||||
|
{
|
||||||
|
return concat_to_string('(', Combinator::pattern(), ")?");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ... Ts>
|
||||||
|
struct sequence;
|
||||||
|
|
||||||
|
template<typename Head, typename ... Tail>
|
||||||
|
struct sequence<Head, Tail...>
|
||||||
|
{
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
|
const auto first = loc.iter();
|
||||||
|
const auto rslt = Head::invoke(loc);
|
||||||
|
if(rslt.is_err())
|
||||||
|
{
|
||||||
|
loc.reset(first);
|
||||||
|
return err(rslt.unwrap_err());
|
||||||
|
}
|
||||||
|
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
|
||||||
|
}
|
||||||
|
|
||||||
|
// called from the above function only, recursively.
|
||||||
|
template<typename Cont, typename Iterator>
|
||||||
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
||||||
|
{
|
||||||
|
const auto rslt = Head::invoke(loc);
|
||||||
|
if(rslt.is_err())
|
||||||
|
{
|
||||||
|
loc.reset(first);
|
||||||
|
return err(rslt.unwrap_err());
|
||||||
|
}
|
||||||
|
reg += rslt.unwrap(); // concat regions
|
||||||
|
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>
|
||||||
|
struct sequence<Head>
|
||||||
|
{
|
||||||
|
// would be called from sequence<T ...>::invoke only.
|
||||||
|
template<typename Cont, typename Iterator>
|
||||||
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
||||||
|
{
|
||||||
|
const auto rslt = Head::invoke(loc);
|
||||||
|
if(rslt.is_err())
|
||||||
|
{
|
||||||
|
loc.reset(first);
|
||||||
|
return err(rslt.unwrap_err());
|
||||||
|
}
|
||||||
|
reg += rslt.unwrap(); // concat regions
|
||||||
|
return ok(reg);
|
||||||
|
}
|
||||||
|
static std::string pattern() {return Head::pattern();}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ... Ts>
|
||||||
|
struct either;
|
||||||
|
|
||||||
|
template<typename Head, typename ... Tail>
|
||||||
|
struct either<Head, Tail...>
|
||||||
|
{
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
|
const auto rslt = Head::invoke(loc);
|
||||||
|
if(rslt.is_ok()) {return rslt;}
|
||||||
|
return either<Tail...>::invoke(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string pattern()
|
||||||
|
{
|
||||||
|
return concat_to_string('(', Head::pattern(), ")|", either<Tail...>::pattern());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename Head>
|
||||||
|
struct either<Head>
|
||||||
|
{
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
|
"internal error: container::value_type should be `char`.");
|
||||||
|
return Head::invoke(loc);
|
||||||
|
}
|
||||||
|
static std::string pattern()
|
||||||
|
{
|
||||||
|
return concat_to_string('(', Head::pattern(), ')');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename N>
|
||||||
|
struct repeat;
|
||||||
|
|
||||||
|
template<std::size_t N> struct exactly{};
|
||||||
|
template<std::size_t N> struct at_least{};
|
||||||
|
struct unlimited{};
|
||||||
|
|
||||||
|
template<typename T, std::size_t N>
|
||||||
|
struct repeat<T, exactly<N>>
|
||||||
|
{
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
region<Cont> retval(loc);
|
||||||
|
const auto first = loc.iter();
|
||||||
|
for(std::size_t i=0; i<N; ++i)
|
||||||
|
{
|
||||||
|
auto rslt = T::invoke(loc);
|
||||||
|
if(rslt.is_err())
|
||||||
|
{
|
||||||
|
loc.reset(first);
|
||||||
|
return err(rslt.unwrap_err());
|
||||||
|
}
|
||||||
|
retval += rslt.unwrap();
|
||||||
|
}
|
||||||
|
return ok(std::move(retval));
|
||||||
|
}
|
||||||
|
static std::string pattern()
|
||||||
|
{
|
||||||
|
return concat_to_string('(', T::pattern(), "){", N, '}');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, std::size_t N>
|
||||||
|
struct repeat<T, at_least<N>>
|
||||||
|
{
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
region<Cont> retval(loc);
|
||||||
|
|
||||||
|
const auto first = loc.iter();
|
||||||
|
for(std::size_t i=0; i<N; ++i)
|
||||||
|
{
|
||||||
|
auto rslt = T::invoke(loc);
|
||||||
|
if(rslt.is_err())
|
||||||
|
{
|
||||||
|
loc.reset(first);
|
||||||
|
return err(rslt.unwrap_err());
|
||||||
|
}
|
||||||
|
retval += rslt.unwrap();
|
||||||
|
}
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
auto rslt = T::invoke(loc);
|
||||||
|
if(rslt.is_err())
|
||||||
|
{
|
||||||
|
return ok(std::move(retval));
|
||||||
|
}
|
||||||
|
retval += rslt.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static std::string pattern()
|
||||||
|
{
|
||||||
|
return concat_to_string('(',T::pattern(), "){", N, ",}");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct repeat<T, unlimited>
|
||||||
|
{
|
||||||
|
template<typename Cont>
|
||||||
|
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
||||||
|
{
|
||||||
|
region<Cont> retval(loc);
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
auto rslt = T::invoke(loc);
|
||||||
|
if(rslt.is_err())
|
||||||
|
{
|
||||||
|
return ok(std::move(retval));
|
||||||
|
}
|
||||||
|
retval += rslt.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static std::string pattern() {return concat_to_string('(', T::pattern(), ")*");}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // toml
|
||||||
|
#endif// TOML11_COMBINATOR_HPP
|
||||||
@@ -1,231 +1,557 @@
|
|||||||
#ifndef TOML11_DATETIME
|
// Copyright Toru Niina 2017.
|
||||||
#define TOML11_DATETIME
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_DATETIME_HPP
|
||||||
|
#define TOML11_DATETIME_HPP
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <tuple>
|
||||||
|
#include <array>
|
||||||
|
#include <ostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename unsignedT, typename intT>
|
// To avoid non-threadsafe std::localtime. In C11 (not C++11!), localtime_s is
|
||||||
struct basic_datetime
|
// 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
|
||||||
{
|
{
|
||||||
typedef unsignedT number_type;
|
// TODO: find more sophisticated way to handle this
|
||||||
typedef intT offset_type;
|
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE
|
||||||
constexpr static unsignedT undef = std::numeric_limits<unsignedT>::max();
|
inline std::tm localtime_s(const std::time_t* src)
|
||||||
constexpr static intT nooffset = std::numeric_limits<intT>::max();
|
{
|
||||||
|
std::tm dst;
|
||||||
|
const auto result = ::localtime_r(src, &dst);
|
||||||
|
if(!result)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("localtime_r failed.");
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// XXX: On Windows, std::localtime is thread-safe because they uses thread-local
|
||||||
|
// storage to store the instance of std::tm. On the other platforms, it may not
|
||||||
|
// be thread-safe.
|
||||||
|
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
|
||||||
|
|
||||||
unsignedT year;
|
enum class month_t : std::int8_t
|
||||||
unsignedT month;
|
{
|
||||||
unsignedT day;
|
Jan = 0,
|
||||||
unsignedT hour;
|
Feb = 1,
|
||||||
unsignedT minute;
|
Mar = 2,
|
||||||
unsignedT second;
|
Apr = 3,
|
||||||
unsignedT millisecond;
|
May = 4,
|
||||||
unsignedT microsecond;
|
Jun = 5,
|
||||||
intT offset_hour;
|
Jul = 6,
|
||||||
intT offset_minute;
|
Aug = 7,
|
||||||
|
Sep = 8,
|
||||||
|
Oct = 9,
|
||||||
|
Nov = 10,
|
||||||
|
Dec = 11
|
||||||
|
};
|
||||||
|
|
||||||
basic_datetime() = default;
|
struct local_date
|
||||||
~basic_datetime() = default;
|
{
|
||||||
basic_datetime(const basic_datetime&) = default;
|
std::int16_t year; // A.D. (like, 2018)
|
||||||
basic_datetime(basic_datetime&&) = default;
|
std::uint8_t month; // [0, 11]
|
||||||
basic_datetime& operator=(const basic_datetime&) = default;
|
std::uint8_t day; // [1, 31]
|
||||||
basic_datetime& operator=(basic_datetime&&) = default;
|
|
||||||
|
|
||||||
basic_datetime(unsignedT y, unsignedT m, unsignedT d)
|
local_date(int y, month_t m, int d)
|
||||||
: year(y), month(m), day(d), hour(undef), minute(undef), second(undef),
|
: year (static_cast<std::int16_t>(y)),
|
||||||
millisecond(undef), microsecond(undef),
|
month(static_cast<std::uint8_t>(m)),
|
||||||
offset_hour(nooffset), offset_minute(nooffset)
|
day (static_cast<std::uint8_t>(d))
|
||||||
{}
|
|
||||||
basic_datetime(unsignedT h, unsignedT m, unsignedT s,
|
|
||||||
unsignedT ms, unsignedT us)
|
|
||||||
: year(undef), month(undef), day(undef), hour(h), minute(m), second(s),
|
|
||||||
millisecond(ms), microsecond(us),
|
|
||||||
offset_hour(nooffset), offset_minute(nooffset)
|
|
||||||
{}
|
|
||||||
basic_datetime(unsignedT y, unsignedT mth, unsignedT d,
|
|
||||||
unsignedT h, unsignedT min, unsignedT s,
|
|
||||||
unsignedT ms, unsignedT us)
|
|
||||||
: year(y), month(mth), day(d), hour(h), minute(min), second(s),
|
|
||||||
millisecond(ms), microsecond(us),
|
|
||||||
offset_hour(nooffset), offset_minute(nooffset)
|
|
||||||
{}
|
|
||||||
basic_datetime(unsignedT y, unsignedT mth, unsignedT d,
|
|
||||||
unsignedT h, unsignedT min, unsignedT s,
|
|
||||||
unsignedT ss, unsignedT us, intT oh, intT om)
|
|
||||||
: year(y), month(mth), day(d), hour(h), minute(min), second(s),
|
|
||||||
millisecond(ss), microsecond(us), offset_hour(oh), offset_minute(om)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
basic_datetime(std::chrono::system_clock::time_point tp);
|
explicit local_date(const std::tm& t)
|
||||||
basic_datetime(std::time_t t);
|
: year (static_cast<std::int16_t>(t.tm_year + 1900)),
|
||||||
|
month(static_cast<std::uint8_t>(t.tm_mon)),
|
||||||
|
day (static_cast<std::uint8_t>(t.tm_mday))
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit local_date(const std::chrono::system_clock::time_point& tp)
|
||||||
|
{
|
||||||
|
const auto t = std::chrono::system_clock::to_time_t(tp);
|
||||||
|
const auto time = detail::localtime_s(&t);
|
||||||
|
*this = local_date(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit local_date(const std::time_t t)
|
||||||
|
: local_date(std::chrono::system_clock::from_time_t(t))
|
||||||
|
{}
|
||||||
|
|
||||||
operator std::chrono::system_clock::time_point() const
|
operator std::chrono::system_clock::time_point() const
|
||||||
{
|
{
|
||||||
std::tm time;
|
// std::mktime returns date as local time zone. no conversion needed
|
||||||
if(this->year == undef || this->month == undef || this->day == undef)
|
std::tm t;
|
||||||
{
|
t.tm_sec = 0;
|
||||||
const auto now = std::chrono::system_clock::now();
|
t.tm_min = 0;
|
||||||
const auto t = std::chrono::system_clock::to_time_t(now);
|
t.tm_hour = 0;
|
||||||
std::tm* t_ = std::localtime(&t);
|
t.tm_mday = this->day;
|
||||||
time.tm_year = t_->tm_year;
|
t.tm_mon = this->month;
|
||||||
time.tm_mon = t_->tm_mon;
|
t.tm_year = this->year - 1900;
|
||||||
time.tm_mday = t_->tm_mday;
|
t.tm_wday = 0; // the value will be ignored
|
||||||
|
t.tm_yday = 0; // the value will be ignored
|
||||||
|
t.tm_isdst = -1;
|
||||||
|
return std::chrono::system_clock::from_time_t(std::mktime(&t));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
time.tm_year = this->year - 1900;
|
|
||||||
time.tm_mon = this->month - 1;
|
|
||||||
time.tm_mday = this->day;
|
|
||||||
}
|
|
||||||
time.tm_hour = (this->hour == undef) ? 0 : this->hour;
|
|
||||||
time.tm_min = (this->minute == undef) ? 0 : this->minute;
|
|
||||||
time.tm_sec = (this->second == undef) ? 0 : this->second;
|
|
||||||
|
|
||||||
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&time));
|
|
||||||
tp += std::chrono::milliseconds(this->millisecond);
|
|
||||||
tp += std::chrono::microseconds(this->microsecond);
|
|
||||||
// mktime regards the tm struct as localtime. so adding offset is not needed.
|
|
||||||
|
|
||||||
return tp;
|
|
||||||
}
|
|
||||||
operator std::time_t() const
|
operator std::time_t() const
|
||||||
{
|
{
|
||||||
return std::chrono::system_clock::to_time_t(
|
return std::chrono::system_clock::to_time_t(
|
||||||
std::chrono::system_clock::time_point(*this));
|
std::chrono::system_clock::time_point(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_date() = default;
|
||||||
|
~local_date() = default;
|
||||||
|
local_date(local_date const&) = default;
|
||||||
|
local_date(local_date&&) = default;
|
||||||
|
local_date& operator=(local_date const&) = default;
|
||||||
|
local_date& operator=(local_date&&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename uT, typename iT>
|
inline bool operator==(const local_date& lhs, const local_date& rhs)
|
||||||
basic_datetime<uT, iT>::basic_datetime(std::chrono::system_clock::time_point tp)
|
|
||||||
{
|
{
|
||||||
const auto t = std::chrono::system_clock::to_time_t(tp);
|
return std::make_tuple(lhs.year, lhs.month, lhs.day) ==
|
||||||
std::tm *time = std::localtime(&t);
|
std::make_tuple(rhs.year, rhs.month, rhs.day);
|
||||||
this->year = time->tm_year + 1900;
|
}
|
||||||
this->month = time->tm_mon + 1;
|
inline bool operator!=(const local_date& lhs, const local_date& rhs)
|
||||||
this->day = time->tm_mday;
|
{
|
||||||
this->hour = time->tm_hour;
|
return !(lhs == rhs);
|
||||||
this->minute = time->tm_min;
|
}
|
||||||
this->second = time->tm_sec;
|
inline bool operator< (const local_date& lhs, const local_date& rhs)
|
||||||
auto t_ = std::chrono::system_clock::from_time_t(std::mktime(time));
|
{
|
||||||
auto diff = tp - t_;
|
return std::make_tuple(lhs.year, lhs.month, lhs.day) <
|
||||||
this->millisecond = std::chrono::duration_cast<std::chrono::milliseconds
|
std::make_tuple(rhs.year, rhs.month, rhs.day);
|
||||||
>(diff).count() % 1000;
|
}
|
||||||
this->microsecond = std::chrono::duration_cast<std::chrono::microseconds
|
inline bool operator<=(const local_date& lhs, const local_date& rhs)
|
||||||
>(diff).count() % 1000;
|
{
|
||||||
|
return (lhs < rhs) || (lhs == rhs);
|
||||||
std::tm *utc = std::gmtime(&t);
|
}
|
||||||
int total_offset = (this->hour - utc->tm_hour) * 60 +
|
inline bool operator> (const local_date& lhs, const local_date& rhs)
|
||||||
(this->minute - utc->tm_min);
|
{
|
||||||
if(total_offset > 720) total_offset -= 1440;
|
return !(lhs <= rhs);
|
||||||
else if(total_offset < -720) total_offset += 1440;
|
}
|
||||||
offset_hour = total_offset / 60;
|
inline bool operator>=(const local_date& lhs, const local_date& rhs)
|
||||||
offset_minute = total_offset - (offset_hour * 60);
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename uT, typename iT>
|
template<typename charT, typename traits>
|
||||||
basic_datetime<uT, iT>::basic_datetime(std::time_t t)
|
|
||||||
{
|
|
||||||
*this = basic_datetime(std::chrono::system_clock::from_time_t(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename charT, typename traits, typename uT, typename iT>
|
|
||||||
std::basic_ostream<charT, traits>&
|
std::basic_ostream<charT, traits>&
|
||||||
operator<<(std::basic_ostream<charT, traits>& os, basic_datetime<uT, iT> const& dt)
|
operator<<(std::basic_ostream<charT, traits>& os, const local_date& date)
|
||||||
{
|
{
|
||||||
bool date = false;
|
os << std::setfill('0') << std::setw(4) << static_cast<int>(date.year ) << '-';
|
||||||
if(dt.year != basic_datetime<uT, iT>::undef &&
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.month + 1) << '-';
|
||||||
dt.month != basic_datetime<uT, iT>::undef &&
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(date.day );
|
||||||
dt.day != basic_datetime<uT, iT>::undef)
|
return os;
|
||||||
{
|
|
||||||
os << std::setfill('0') << std::setw(4) << dt.year << '-'
|
|
||||||
<< std::setfill('0') << std::setw(2) << dt.month << '-'
|
|
||||||
<< std::setfill('0') << std::setw(2) << dt.day;
|
|
||||||
date = true;
|
|
||||||
}
|
}
|
||||||
if(dt.hour != basic_datetime<uT, iT>::undef &&
|
|
||||||
dt.minute != basic_datetime<uT, iT>::undef &&
|
struct local_time
|
||||||
dt.second != basic_datetime<uT, iT>::undef)
|
|
||||||
{
|
{
|
||||||
if(date) os << 'T';
|
std::uint8_t hour; // [0, 23]
|
||||||
os << std::setfill('0') << std::setw(2) << dt.hour << ':'
|
std::uint8_t minute; // [0, 59]
|
||||||
<< std::setfill('0') << std::setw(2) << dt.minute << ':'
|
std::uint8_t second; // [0, 60]
|
||||||
<< std::setfill('0') << std::setw(2) << dt.second << '.'
|
std::uint16_t millisecond; // [0, 999]
|
||||||
<< std::setfill('0') << std::setw(3) << dt.millisecond
|
std::uint16_t microsecond; // [0, 999]
|
||||||
<< std::setfill('0') << std::setw(3) << dt.microsecond;
|
std::uint16_t nanosecond; // [0, 999]
|
||||||
|
|
||||||
|
local_time(int h, int m, int s,
|
||||||
|
int ms = 0, int us = 0, int ns = 0)
|
||||||
|
: hour (static_cast<std::uint8_t>(h)),
|
||||||
|
minute(static_cast<std::uint8_t>(m)),
|
||||||
|
second(static_cast<std::uint8_t>(s)),
|
||||||
|
millisecond(static_cast<std::uint16_t>(ms)),
|
||||||
|
microsecond(static_cast<std::uint16_t>(us)),
|
||||||
|
nanosecond (static_cast<std::uint16_t>(ns))
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit local_time(const std::tm& t)
|
||||||
|
: hour (static_cast<std::uint8_t>(t.tm_hour)),
|
||||||
|
minute(static_cast<std::uint8_t>(t.tm_min)),
|
||||||
|
second(static_cast<std::uint8_t>(t.tm_sec)),
|
||||||
|
millisecond(0), microsecond(0), nanosecond(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename Rep, typename Period>
|
||||||
|
explicit local_time(const std::chrono::duration<Rep, Period>& t)
|
||||||
|
{
|
||||||
|
const auto h = std::chrono::duration_cast<std::chrono::hours>(t);
|
||||||
|
this->hour = h.count();
|
||||||
|
const auto t2 = t - h;
|
||||||
|
const auto m = std::chrono::duration_cast<std::chrono::minutes>(t2);
|
||||||
|
this->minute = m.count();
|
||||||
|
const auto t3 = t2 - m;
|
||||||
|
const auto s = std::chrono::duration_cast<std::chrono::seconds>(t3);
|
||||||
|
this->second = s.count();
|
||||||
|
const auto t4 = t3 - s;
|
||||||
|
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t4);
|
||||||
|
this->millisecond = ms.count();
|
||||||
|
const auto t5 = t4 - ms;
|
||||||
|
const auto us = std::chrono::duration_cast<std::chrono::microseconds>(t5);
|
||||||
|
this->microsecond = us.count();
|
||||||
|
const auto t6 = t5 - us;
|
||||||
|
const auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t6);
|
||||||
|
this->nanosecond = ns.count();
|
||||||
}
|
}
|
||||||
if(dt.offset_hour != basic_datetime<uT, iT>::nooffset &&
|
|
||||||
dt.offset_minute != basic_datetime<uT, iT>::nooffset)
|
operator std::chrono::nanoseconds() const
|
||||||
{
|
{
|
||||||
if(dt.offset_hour == 0 && dt.offset_minute == 0)
|
return std::chrono::nanoseconds (this->nanosecond) +
|
||||||
{
|
std::chrono::microseconds(this->microsecond) +
|
||||||
os << 'Z';
|
std::chrono::milliseconds(this->millisecond) +
|
||||||
|
std::chrono::seconds(this->second) +
|
||||||
|
std::chrono::minutes(this->minute) +
|
||||||
|
std::chrono::hours(this->hour);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
local_time() = default;
|
||||||
|
~local_time() = default;
|
||||||
|
local_time(local_time const&) = default;
|
||||||
|
local_time(local_time&&) = default;
|
||||||
|
local_time& operator=(local_time const&) = default;
|
||||||
|
local_time& operator=(local_time&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const local_time& lhs, const local_time& rhs)
|
||||||
{
|
{
|
||||||
char sign = ' ';
|
return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) ==
|
||||||
iT oh = dt.offset_hour;
|
std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond);
|
||||||
iT om = dt.offset_minute;
|
}
|
||||||
om += oh * 60;
|
inline bool operator!=(const local_time& lhs, const local_time& rhs)
|
||||||
if(om > 0) sign = '+'; else sign='-';
|
{
|
||||||
oh = om / 60;
|
return !(lhs == rhs);
|
||||||
om -= oh * 60;
|
}
|
||||||
os << sign << std::setfill('0') << std::setw(2) << std::abs(oh) << ':'
|
inline bool operator< (const local_time& lhs, const local_time& rhs)
|
||||||
<< std::setfill('0') << std::setw(2) << std::abs(om);
|
{
|
||||||
|
return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) <
|
||||||
|
std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond);
|
||||||
|
}
|
||||||
|
inline bool operator<=(const local_time& lhs, const local_time& rhs)
|
||||||
|
{
|
||||||
|
return (lhs < rhs) || (lhs == rhs);
|
||||||
|
}
|
||||||
|
inline bool operator> (const local_time& lhs, const local_time& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs <= rhs);
|
||||||
|
}
|
||||||
|
inline bool operator>=(const local_time& lhs, const local_time& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, const local_time& time)
|
||||||
|
{
|
||||||
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(time.hour ) << ':';
|
||||||
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(time.minute) << ':';
|
||||||
|
os << std::setfill('0') << std::setw(2) << static_cast<int>(time.second);
|
||||||
|
if(time.millisecond != 0 || time.microsecond != 0 || time.nanosecond != 0)
|
||||||
|
{
|
||||||
|
os << '.';
|
||||||
|
os << std::setfill('0') << std::setw(3) << static_cast<int>(time.millisecond);
|
||||||
|
if(time.microsecond != 0 || time.nanosecond != 0)
|
||||||
|
{
|
||||||
|
os << std::setfill('0') << std::setw(3) << static_cast<int>(time.microsecond);
|
||||||
|
if(time.nanosecond != 0)
|
||||||
|
{
|
||||||
|
os << std::setfill('0') << std::setw(3) << static_cast<int>(time.nanosecond);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename uT, typename iT>
|
struct time_offset
|
||||||
inline bool
|
|
||||||
operator==(basic_datetime<uT, iT> const& lhs, basic_datetime<uT, iT> const& rhs)
|
|
||||||
{
|
{
|
||||||
return lhs.year == rhs.year && lhs.month == rhs.month &&
|
std::int8_t hour; // [-12, 12]
|
||||||
lhs.day == rhs.day && lhs.minute == rhs.minute &&
|
std::int8_t minute; // [-59, 59]
|
||||||
lhs.second == rhs.second && lhs.millisecond == rhs.millisecond &&
|
|
||||||
lhs.microsecond == rhs.microsecond &&
|
time_offset(int h, int m)
|
||||||
lhs.offset_hour == rhs.offset_hour &&
|
: hour (static_cast<std::int8_t>(h)),
|
||||||
lhs.offset_minute == rhs.offset_minute;
|
minute(static_cast<std::int8_t>(m))
|
||||||
|
{}
|
||||||
|
|
||||||
|
operator std::chrono::minutes() const
|
||||||
|
{
|
||||||
|
return std::chrono::minutes(this->minute) +
|
||||||
|
std::chrono::hours(this->hour);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename uT, typename iT>
|
time_offset() = default;
|
||||||
inline bool
|
~time_offset() = default;
|
||||||
operator!=(basic_datetime<uT, iT> const& lhs, basic_datetime<uT, iT> const& rhs)
|
time_offset(time_offset const&) = default;
|
||||||
|
time_offset(time_offset&&) = default;
|
||||||
|
time_offset& operator=(time_offset const&) = default;
|
||||||
|
time_offset& operator=(time_offset&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const time_offset& lhs, const time_offset& rhs)
|
||||||
|
{
|
||||||
|
return std::make_tuple(lhs.hour, lhs.minute) ==
|
||||||
|
std::make_tuple(rhs.hour, rhs.minute);
|
||||||
|
}
|
||||||
|
inline bool operator!=(const time_offset& lhs, const time_offset& rhs)
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
inline bool operator< (const time_offset& lhs, const time_offset& rhs)
|
||||||
template<typename uT, typename iT>
|
|
||||||
inline bool
|
|
||||||
operator<(basic_datetime<uT, iT> const& lhs, basic_datetime<uT, iT> const& rhs)
|
|
||||||
{
|
{
|
||||||
return std::time_t(lhs) < std::time_t(rhs);
|
return std::make_tuple(lhs.hour, lhs.minute) <
|
||||||
|
std::make_tuple(rhs.hour, rhs.minute);
|
||||||
|
}
|
||||||
|
inline bool operator<=(const time_offset& lhs, const time_offset& rhs)
|
||||||
|
{
|
||||||
|
return (lhs < rhs) || (lhs == rhs);
|
||||||
|
}
|
||||||
|
inline bool operator> (const time_offset& lhs, const time_offset& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs <= rhs);
|
||||||
|
}
|
||||||
|
inline bool operator>=(const time_offset& lhs, const time_offset& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename uT, typename iT>
|
template<typename charT, typename traits>
|
||||||
inline bool
|
std::basic_ostream<charT, traits>&
|
||||||
operator<=(basic_datetime<uT, iT> const& lhs, basic_datetime<uT, iT> const& rhs)
|
operator<<(std::basic_ostream<charT, traits>& os, const time_offset& offset)
|
||||||
{
|
{
|
||||||
return std::time_t(lhs) <= std::time_t(rhs);
|
if(offset.hour == 0 && offset.minute == 0)
|
||||||
|
{
|
||||||
|
os << 'Z';
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
int minute = static_cast<int>(offset.hour) * 60 + offset.minute;
|
||||||
|
if(minute < 0){os << '-'; minute = std::abs(minute);} else {os << '+';}
|
||||||
|
os << std::setfill('0') << std::setw(2) << minute / 60 << ':';
|
||||||
|
os << std::setfill('0') << std::setw(2) << minute % 60;
|
||||||
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename uT, typename iT>
|
struct local_datetime
|
||||||
inline bool
|
|
||||||
operator>(basic_datetime<uT, iT> const& lhs, basic_datetime<uT, iT> const& rhs)
|
|
||||||
{
|
{
|
||||||
return std::time_t(lhs) > std::time_t(rhs);
|
local_date date;
|
||||||
|
local_time time;
|
||||||
|
|
||||||
|
local_datetime(local_date d, local_time t): date(d), time(t) {}
|
||||||
|
|
||||||
|
explicit local_datetime(const std::tm& t): date(t), time(t){}
|
||||||
|
|
||||||
|
explicit local_datetime(const std::chrono::system_clock::time_point& tp)
|
||||||
|
{
|
||||||
|
const auto t = std::chrono::system_clock::to_time_t(tp);
|
||||||
|
std::tm time = detail::localtime_s(&t);
|
||||||
|
|
||||||
|
this->date = local_date(time);
|
||||||
|
this->time = local_time(time);
|
||||||
|
|
||||||
|
// std::tm lacks subsecond information, so diff between tp and tm
|
||||||
|
// can be used to get millisecond & microsecond information.
|
||||||
|
const auto t_diff = tp -
|
||||||
|
std::chrono::system_clock::from_time_t(std::mktime(&time));
|
||||||
|
this->time.millisecond = std::chrono::duration_cast<
|
||||||
|
std::chrono::milliseconds>(t_diff).count();
|
||||||
|
this->time.microsecond = std::chrono::duration_cast<
|
||||||
|
std::chrono::microseconds>(t_diff).count();
|
||||||
|
this->time.nanosecond = std::chrono::duration_cast<
|
||||||
|
std::chrono::nanoseconds >(t_diff).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename uT, typename iT>
|
explicit local_datetime(const std::time_t t)
|
||||||
inline bool
|
: local_datetime(std::chrono::system_clock::from_time_t(t))
|
||||||
operator>=(basic_datetime<uT, iT> const& lhs, basic_datetime<uT, iT> const& rhs)
|
{}
|
||||||
|
|
||||||
|
operator std::chrono::system_clock::time_point() const
|
||||||
{
|
{
|
||||||
return std::time_t(lhs) >= std::time_t(rhs);
|
using internal_duration =
|
||||||
|
typename std::chrono::system_clock::time_point::duration;
|
||||||
|
// std::mktime returns date as local time zone. no conversion needed
|
||||||
|
auto dt = std::chrono::system_clock::time_point(this->date);
|
||||||
|
dt += std::chrono::duration_cast<internal_duration>(
|
||||||
|
std::chrono::nanoseconds(this->time));
|
||||||
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator std::time_t() const
|
||||||
|
{
|
||||||
|
return std::chrono::system_clock::to_time_t(
|
||||||
|
std::chrono::system_clock::time_point(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
local_datetime() = default;
|
||||||
|
~local_datetime() = default;
|
||||||
|
local_datetime(local_datetime const&) = default;
|
||||||
|
local_datetime(local_datetime&&) = default;
|
||||||
|
local_datetime& operator=(local_datetime const&) = default;
|
||||||
|
local_datetime& operator=(local_datetime&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const local_datetime& lhs, const local_datetime& rhs)
|
||||||
|
{
|
||||||
|
return std::make_tuple(lhs.date, lhs.time) ==
|
||||||
|
std::make_tuple(rhs.date, rhs.time);
|
||||||
|
}
|
||||||
|
inline bool operator!=(const local_datetime& lhs, const local_datetime& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
inline bool operator< (const local_datetime& lhs, const local_datetime& rhs)
|
||||||
|
{
|
||||||
|
return std::make_tuple(lhs.date, lhs.time) <
|
||||||
|
std::make_tuple(rhs.date, rhs.time);
|
||||||
|
}
|
||||||
|
inline bool operator<=(const local_datetime& lhs, const local_datetime& rhs)
|
||||||
|
{
|
||||||
|
return (lhs < rhs) || (lhs == rhs);
|
||||||
|
}
|
||||||
|
inline bool operator> (const local_datetime& lhs, const local_datetime& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs <= rhs);
|
||||||
|
}
|
||||||
|
inline bool operator>=(const local_datetime& lhs, const local_datetime& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, const local_datetime& dt)
|
||||||
|
{
|
||||||
|
os << dt.date << 'T' << dt.time;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct offset_datetime
|
||||||
|
{
|
||||||
|
local_date date;
|
||||||
|
local_time time;
|
||||||
|
time_offset offset;
|
||||||
|
|
||||||
|
offset_datetime(local_date d, local_time t, time_offset o)
|
||||||
|
: date(d), time(t), offset(o)
|
||||||
|
{}
|
||||||
|
offset_datetime(const local_datetime& dt, time_offset o)
|
||||||
|
: date(dt.date), time(dt.time), offset(o)
|
||||||
|
{}
|
||||||
|
explicit offset_datetime(const local_datetime& ld)
|
||||||
|
: date(ld.date), time(ld.time), offset(get_local_offset())
|
||||||
|
{}
|
||||||
|
explicit offset_datetime(const std::chrono::system_clock::time_point& tp)
|
||||||
|
: offset_datetime(local_datetime(tp))
|
||||||
|
{}
|
||||||
|
explicit offset_datetime(const std::time_t& t)
|
||||||
|
: offset_datetime(local_datetime(t))
|
||||||
|
{}
|
||||||
|
explicit offset_datetime(const std::tm& t)
|
||||||
|
: offset_datetime(local_datetime(t))
|
||||||
|
{}
|
||||||
|
|
||||||
|
operator std::chrono::system_clock::time_point() const
|
||||||
|
{
|
||||||
|
// get date-time
|
||||||
|
using internal_duration =
|
||||||
|
typename std::chrono::system_clock::time_point::duration;
|
||||||
|
std::chrono::system_clock::time_point tp =
|
||||||
|
std::chrono::system_clock::time_point(this->date) +
|
||||||
|
std::chrono::duration_cast<internal_duration>(
|
||||||
|
std::chrono::nanoseconds(this->time));
|
||||||
|
|
||||||
|
// get date-time in UTC. let's say we are in +09:00 (JPN).
|
||||||
|
// writing 12:00:00 in +09:00 means 03:00:00Z. to represent
|
||||||
|
// 12:00:00Z, first we need to add +09:00.
|
||||||
|
const auto ofs = get_local_offset();
|
||||||
|
tp += std::chrono::hours (ofs.hour);
|
||||||
|
tp += std::chrono::minutes(ofs.minute);
|
||||||
|
|
||||||
|
// here, tp represents 12:00:00 in UTC but we have offset information.
|
||||||
|
// we need to subtract it. For example, let's say the input is
|
||||||
|
// 12:00:00-08:00. now we have tp = 12:00:00Z as a result of the above
|
||||||
|
// conversion. But the actual time we need to return is 20:00:00Z
|
||||||
|
// because of -08:00.
|
||||||
|
tp -= std::chrono::minutes(this->offset);
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator std::time_t() const
|
||||||
|
{
|
||||||
|
return std::chrono::system_clock::to_time_t(
|
||||||
|
std::chrono::system_clock::time_point(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
offset_datetime() = default;
|
||||||
|
~offset_datetime() = default;
|
||||||
|
offset_datetime(offset_datetime const&) = default;
|
||||||
|
offset_datetime(offset_datetime&&) = default;
|
||||||
|
offset_datetime& operator=(offset_datetime const&) = default;
|
||||||
|
offset_datetime& operator=(offset_datetime&&) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static time_offset get_local_offset()
|
||||||
|
{
|
||||||
|
// get current timezone
|
||||||
|
const auto tmp1 = std::time(nullptr);
|
||||||
|
const auto t = detail::localtime_s(&tmp1);
|
||||||
|
|
||||||
|
std::array<char, 6> buf;
|
||||||
|
const auto result = std::strftime(buf.data(), 6, "%z", &t); // +hhmm\0
|
||||||
|
if(result != 5)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("toml::offset_datetime: cannot obtain "
|
||||||
|
"timezone information of current env");
|
||||||
|
}
|
||||||
|
const int ofs = std::atoi(buf.data());
|
||||||
|
const int ofs_h = ofs / 100;
|
||||||
|
const int ofs_m = ofs - (ofs_h * 100);
|
||||||
|
return time_offset(ofs_h, ofs_m);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const offset_datetime& lhs, const offset_datetime& rhs)
|
||||||
|
{
|
||||||
|
return std::make_tuple(lhs.date, lhs.time, lhs.offset) ==
|
||||||
|
std::make_tuple(rhs.date, rhs.time, rhs.offset);
|
||||||
|
}
|
||||||
|
inline bool operator!=(const offset_datetime& lhs, const offset_datetime& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
inline bool operator< (const offset_datetime& lhs, const offset_datetime& rhs)
|
||||||
|
{
|
||||||
|
return std::make_tuple(lhs.date, lhs.time, lhs.offset) <
|
||||||
|
std::make_tuple(rhs.date, rhs.time, rhs.offset);
|
||||||
|
}
|
||||||
|
inline bool operator<=(const offset_datetime& lhs, const offset_datetime& rhs)
|
||||||
|
{
|
||||||
|
return (lhs < rhs) || (lhs == rhs);
|
||||||
|
}
|
||||||
|
inline bool operator> (const offset_datetime& lhs, const offset_datetime& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs <= rhs);
|
||||||
|
}
|
||||||
|
inline bool operator>=(const offset_datetime& lhs, const offset_datetime& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, const offset_datetime& dt)
|
||||||
|
{
|
||||||
|
os << dt.date << 'T' << dt.time << dt.offset;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
}//toml
|
}//toml
|
||||||
#endif// TOML11_DATETIME
|
#endif// TOML11_DATETIME
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#ifndef TOML11_EXCEPTION
|
// Copyright Toru Niina 2017.
|
||||||
#define TOML11_EXCEPTION
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_EXCEPTION_HPP
|
||||||
|
#define TOML11_EXCEPTION_HPP
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|||||||
386
toml/format.hpp
386
toml/format.hpp
@@ -1,386 +0,0 @@
|
|||||||
#ifndef TOML11_FORMAT
|
|
||||||
#define TOML11_FORMAT
|
|
||||||
#include "value.hpp"
|
|
||||||
#include <type_traits>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <locale>
|
|
||||||
|
|
||||||
namespace toml
|
|
||||||
{
|
|
||||||
|
|
||||||
// synopsis
|
|
||||||
// toml::format("key", value, toml::make_inline(80))
|
|
||||||
// toml::format("key", value, toml::forceinline)
|
|
||||||
// std::cout << toml::make_inline(80) << value;
|
|
||||||
// std::cout << toml::forceinline << value;
|
|
||||||
|
|
||||||
template<typename traits = std::char_traits<toml::character>,
|
|
||||||
typename alloc = std::allocator<toml::character>>
|
|
||||||
std::basic_string<toml::character, traits, alloc>
|
|
||||||
format(const value& v);
|
|
||||||
|
|
||||||
template<typename traits = std::char_traits<toml::character>,
|
|
||||||
typename alloc = std::allocator<toml::character>>
|
|
||||||
std::basic_string<toml::character, traits, alloc>
|
|
||||||
format(const value& v, std::size_t mk);
|
|
||||||
|
|
||||||
template<typename traits = std::char_traits<toml::character>,
|
|
||||||
typename alloc = std::allocator<toml::character>>
|
|
||||||
std::basic_string<toml::character, traits, alloc>
|
|
||||||
format(const toml::key& k, const value& v);
|
|
||||||
|
|
||||||
template<typename traits = std::char_traits<toml::character>,
|
|
||||||
typename alloc = std::allocator<toml::character>>
|
|
||||||
std::basic_string<toml::character, traits, alloc>
|
|
||||||
format(const toml::key& k, const value& v, std::size_t mk);
|
|
||||||
|
|
||||||
template<value_t Type>
|
|
||||||
struct format_impl;
|
|
||||||
|
|
||||||
template<> struct format_impl<value_t::Boolean>
|
|
||||||
{
|
|
||||||
typedef detail::toml_default_type<value_t::Boolean>::type type;
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
operator()(const type& val)
|
|
||||||
{
|
|
||||||
return val ? "true" : "false";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> struct format_impl<value_t::Integer>
|
|
||||||
{
|
|
||||||
typedef detail::toml_default_type<value_t::Integer>::type type;
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
operator()(const type& val)
|
|
||||||
{
|
|
||||||
return std::to_string(val);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> struct format_impl<value_t::Float>
|
|
||||||
{
|
|
||||||
typedef detail::toml_default_type<value_t::Float>::type type;
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
operator()(const type& val)
|
|
||||||
{
|
|
||||||
std::basic_ostringstream<toml::character> oss;
|
|
||||||
oss << std::showpoint << val;
|
|
||||||
if(oss.str().back() == '.') oss << '0';
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> struct format_impl<value_t::String>
|
|
||||||
{
|
|
||||||
typedef detail::toml_default_type<value_t::String>::type type;
|
|
||||||
|
|
||||||
std::size_t max_length;
|
|
||||||
|
|
||||||
format_impl() : max_length(80){}
|
|
||||||
format_impl(std::size_t mx) : max_length(mx){}
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
operator()(const type& val)
|
|
||||||
{
|
|
||||||
auto tmp = make_inline(val);
|
|
||||||
if(max_length == std::numeric_limits<std::size_t>::max() ||
|
|
||||||
tmp.size() <= max_length) return tmp;
|
|
||||||
return convert_multiline(std::move(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
make_inline(const std::basic_string<toml::character>& val)
|
|
||||||
{
|
|
||||||
std::basic_string<toml::character> str;
|
|
||||||
str += '"';
|
|
||||||
for(const auto& c : val)
|
|
||||||
{
|
|
||||||
if('\0' < c && c < '\31')
|
|
||||||
{
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case '\b': str += "\\b"; break;
|
|
||||||
case '\t': str += "\\t"; break;
|
|
||||||
case '\n': str += "\\n"; break;
|
|
||||||
case '\f': str += "\\f"; break;
|
|
||||||
case '\r': str += "\\r"; break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
str += 'u';
|
|
||||||
std::basic_ostringstream<toml::character> oss;
|
|
||||||
oss << std::setw(4) << std::setfill('0') << std::hex
|
|
||||||
<< static_cast<std::int8_t>(c);
|
|
||||||
auto hexdig = oss.str();
|
|
||||||
std::transform(hexdig.begin(), hexdig.end(), hexdig.begin(), ::toupper);
|
|
||||||
str += oss.str();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(c == '"')
|
|
||||||
{
|
|
||||||
str += "\\\"";
|
|
||||||
}
|
|
||||||
else if(c == '\\')
|
|
||||||
{
|
|
||||||
str += "\\\\";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
str += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str += '"';
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
convert_multiline(std::basic_string<toml::character>&& val)
|
|
||||||
{
|
|
||||||
std::basic_string<toml::character> str; str.reserve(val.size() + 6);
|
|
||||||
str += "\"\"\"\n";
|
|
||||||
std::size_t current = 0;
|
|
||||||
for(auto iter = val.begin()+1; iter != val.end()-1; ++iter)
|
|
||||||
{
|
|
||||||
if(*iter != '\\')
|
|
||||||
{
|
|
||||||
if(current + 1 == max_length) str += "\\\n";
|
|
||||||
str += *iter; continue;
|
|
||||||
}
|
|
||||||
assert(std::next(iter) < val.end()-1);
|
|
||||||
if(*std::next(iter) == 'u')
|
|
||||||
{
|
|
||||||
if(current + 5 == max_length) str += "\\\n";
|
|
||||||
assert(iter + 5 < val.end()-1);
|
|
||||||
str += *iter; ++iter; // u
|
|
||||||
str += *iter; ++iter; // 0
|
|
||||||
str += *iter; ++iter; // 1
|
|
||||||
str += *iter; ++iter; // 2
|
|
||||||
str += *iter; continue;// 3
|
|
||||||
}
|
|
||||||
if(current + 2 == max_length) str += "\\\n";
|
|
||||||
str += *iter; ++iter; str += *iter;
|
|
||||||
}
|
|
||||||
str += "\"\"\"";
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> struct format_impl<value_t::Datetime>
|
|
||||||
{
|
|
||||||
typedef detail::toml_default_type<value_t::Datetime>::type type;
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
operator()(const type& val)
|
|
||||||
{
|
|
||||||
std::basic_ostringstream<toml::character> oss;
|
|
||||||
oss << val;
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO max length!
|
|
||||||
template<> struct format_impl<value_t::Array>
|
|
||||||
{
|
|
||||||
typedef detail::toml_default_type<value_t::Array>::type type;
|
|
||||||
|
|
||||||
std::size_t max_length;
|
|
||||||
|
|
||||||
format_impl() : max_length(80){}
|
|
||||||
format_impl(std::size_t mx) : max_length(mx){}
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
operator()(const type& val)
|
|
||||||
{
|
|
||||||
std::basic_string<toml::character> retval;
|
|
||||||
retval += '[';
|
|
||||||
for(const auto& item : val)
|
|
||||||
{
|
|
||||||
auto tmp = format(val, max_length - 1);
|
|
||||||
retval += tmp;
|
|
||||||
retval += ", ";
|
|
||||||
if(tmp.size() * 2 > max_length) retval += '\n';
|
|
||||||
}
|
|
||||||
retval += ']';
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO max length && inline!
|
|
||||||
template<> struct format_impl<value_t::Table>
|
|
||||||
{
|
|
||||||
typedef detail::toml_default_type<value_t::Table>::type type;
|
|
||||||
|
|
||||||
std::size_t max_length;
|
|
||||||
|
|
||||||
format_impl() : max_length(80){}
|
|
||||||
format_impl(std::size_t mx) : max_length(mx){}
|
|
||||||
|
|
||||||
std::basic_string<toml::character>
|
|
||||||
operator()(const type& val)
|
|
||||||
{
|
|
||||||
std::basic_string<toml::character> retval;
|
|
||||||
for(const auto& item : val)
|
|
||||||
{
|
|
||||||
retval += item.first;
|
|
||||||
retval += " = ";
|
|
||||||
retval += format(item.second);
|
|
||||||
retval += '\n';
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename traits, typename alloc>
|
|
||||||
std::basic_string<toml::character, traits, alloc>
|
|
||||||
format(const value& v)
|
|
||||||
{
|
|
||||||
switch(v.type())
|
|
||||||
{
|
|
||||||
case value_t::Boolean : return format_impl<value_t::Boolean >{}(v.template cast<value_t::Boolean >());
|
|
||||||
case value_t::Integer : return format_impl<value_t::Integer >{}(v.template cast<value_t::Integer >());
|
|
||||||
case value_t::Float : return format_impl<value_t::Float >{}(v.template cast<value_t::Float >());
|
|
||||||
case value_t::String : return format_impl<value_t::String >{}(v.template cast<value_t::String >());
|
|
||||||
case value_t::Datetime: return format_impl<value_t::Datetime>{}(v.template cast<value_t::Datetime>());
|
|
||||||
case value_t::Array : return format_impl<value_t::Array >{}(v.template cast<value_t::Array >());
|
|
||||||
case value_t::Table : return format_impl<value_t::Table >{}(v.template cast<value_t::Table >());
|
|
||||||
case value_t::Empty : throw std::runtime_error("toml::format: empty value");
|
|
||||||
case value_t::Unknown : throw std::runtime_error("toml::format: unknown value");
|
|
||||||
default: throw std::logic_error("toml::format: unknown enum value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename traits, typename alloc>
|
|
||||||
std::basic_string<toml::character, traits, alloc>
|
|
||||||
format(const value& v, std::size_t inl)
|
|
||||||
{
|
|
||||||
switch(v.type())
|
|
||||||
{
|
|
||||||
case value_t::Boolean : return format_impl<value_t::Boolean >{}(v.template cast<value_t::Boolean>());
|
|
||||||
case value_t::Integer : return format_impl<value_t::Integer >{}(v.template cast<value_t::Integer>());
|
|
||||||
case value_t::Float : return format_impl<value_t::Float >{}(v.template cast<value_t::Float>());
|
|
||||||
case value_t::String : return format_impl<value_t::String >{inl}(v.template cast<value_t::String>());
|
|
||||||
case value_t::Datetime: return format_impl<value_t::Datetime>{}(v.template cast<value_t::Datetime>());
|
|
||||||
case value_t::Array : return format_impl<value_t::Array >{inl}(v.template cast<value_t::Array>());
|
|
||||||
case value_t::Table : return format_impl<value_t::Table >{inl}(v.template cast<value_t::Table>());
|
|
||||||
case value_t::Empty : throw std::runtime_error("toml::format: empty value");
|
|
||||||
case value_t::Unknown : throw std::runtime_error("toml::format: unknown value");
|
|
||||||
default: throw std::logic_error("toml::format: unknown enum value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename traits, typename alloc>
|
|
||||||
std::basic_string<toml::character, traits, alloc>
|
|
||||||
format(std::basic_string<toml::character, traits, alloc> key, const value& val)
|
|
||||||
{
|
|
||||||
std::basic_string<toml::character, traits, alloc> retval(std::move(key));
|
|
||||||
retval += " = ";
|
|
||||||
retval += format(val);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename traits, typename alloc>
|
|
||||||
std::basic_string<toml::character, traits, alloc>
|
|
||||||
format(std::basic_string<toml::character, traits, alloc> key, const value& val, std::size_t mk)
|
|
||||||
{
|
|
||||||
std::basic_string<toml::character, traits, alloc> retval(std::move(key));
|
|
||||||
retval += " = ";
|
|
||||||
retval += format(val, mk);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------- stream operators -----------------------------
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename T = std::size_t>
|
|
||||||
struct inline_limit
|
|
||||||
{
|
|
||||||
static_assert(std::is_same<T, std::size_t>::value, "do not instantiate this");
|
|
||||||
static const int index;
|
|
||||||
T limit;
|
|
||||||
inline_limit() = default;
|
|
||||||
~inline_limit() = default;
|
|
||||||
constexpr inline_limit(T i): limit(i){}
|
|
||||||
constexpr operator T() const {return limit;}
|
|
||||||
|
|
||||||
static void callback(std::ios_base::event ev, std::ios_base& ios, int idx)
|
|
||||||
{
|
|
||||||
void*& info = ios.pword(idx);
|
|
||||||
switch (ev)
|
|
||||||
{
|
|
||||||
case std::ios_base::erase_event:
|
|
||||||
{
|
|
||||||
delete static_cast<std::size_t*>(info);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case std::ios_base::copyfmt_event:
|
|
||||||
{
|
|
||||||
info = new std::size_t(*static_cast<std::size_t*>(info));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case std::ios_base::imbue_event:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
const int inline_limit<T>::index = std::ios_base::xalloc();
|
|
||||||
|
|
||||||
} //detail
|
|
||||||
|
|
||||||
template<typename sizeT, typename traits = std::char_traits<toml::character>>
|
|
||||||
std::basic_ostream<toml::character, traits>&
|
|
||||||
operator<<(std::basic_ostream<toml::character, traits>& os,
|
|
||||||
const detail::inline_limit<sizeT>& inl)
|
|
||||||
{
|
|
||||||
void*& info = os.pword(detail::inline_limit<sizeT>::index);
|
|
||||||
if(!os.bad())
|
|
||||||
{
|
|
||||||
if(info == nullptr)
|
|
||||||
{
|
|
||||||
os.register_callback(detail::inline_limit<sizeT>::callback,
|
|
||||||
detail::inline_limit<sizeT>::index);
|
|
||||||
info = new std::size_t(inl.limit);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*static_cast<std::size_t*>(info) = inl.limit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr static detail::inline_limit<std::size_t> forceinline(
|
|
||||||
std::numeric_limits<std::size_t>::max());
|
|
||||||
|
|
||||||
inline detail::inline_limit<std::size_t> make_inline(std::size_t sz)
|
|
||||||
{
|
|
||||||
return detail::inline_limit<std::size_t>(sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename traits = std::char_traits<toml::character>>
|
|
||||||
std::basic_ostream<toml::character, traits>&
|
|
||||||
operator<<(std::basic_ostream<toml::character, traits>& os,
|
|
||||||
const toml::value& v)
|
|
||||||
{
|
|
||||||
std::size_t* info =
|
|
||||||
static_cast<std::size_t*>(os.pword(detail::inline_limit<std::size_t>::index));
|
|
||||||
return os << (info == nullptr ? toml::format(v) : toml::format(v, *info));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif // TOML11_FORMAT
|
|
||||||
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,66 +1,16 @@
|
|||||||
#ifndef TOML11_FROM_TOML
|
// Copyright Toru Niina 2017.
|
||||||
#define TOML11_FROM_TOML
|
// Distributed under the MIT License.
|
||||||
#include "value.hpp"
|
#ifndef TOML11_FROM_TOML_HPP
|
||||||
|
#define TOML11_FROM_TOML_HPP
|
||||||
|
#include "get.hpp"
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
template<typename T>
|
||||||
typename std::enable_if<(vT != toml::value_t::Unknown &&
|
|
||||||
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
|
|
||||||
void from_toml(T& x, const toml::value& v)
|
void from_toml(T& x, const toml::value& v)
|
||||||
{
|
{
|
||||||
if(v.type() != vT)
|
x = toml::get<typename std::remove_reference<T>::type>(v);
|
||||||
throw type_error("from_toml: value type: " + stringize(v.type()) +
|
|
||||||
std::string(" is not arguemnt type: ") + stringize(vT));
|
|
||||||
x = v.cast<vT>();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
|
||||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
|
||||||
(!toml::detail::is_map<T>::value) &&
|
|
||||||
toml::detail::is_container<T>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
void from_toml(T& x, const toml::value& v)
|
|
||||||
{
|
|
||||||
// TODO the case of x is not dynamic container case
|
|
||||||
if(v.type() != value_t::Array)
|
|
||||||
throw type_error("from_toml: value type: " + stringize(v.type()) +
|
|
||||||
std::string(" is not argument type: Array"));
|
|
||||||
const auto& ar = v.cast<value_t::Array>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
toml::resize(x, ar.size());
|
|
||||||
}
|
|
||||||
catch(std::invalid_argument& iv)
|
|
||||||
{
|
|
||||||
throw toml::type_error("toml::from_toml: static array size is not enough");
|
|
||||||
}
|
|
||||||
auto iter = x.begin();
|
|
||||||
for(const auto& val : ar)
|
|
||||||
{
|
|
||||||
typename T::value_type v;
|
|
||||||
from_toml(v, val);
|
|
||||||
*iter = std::move(v);
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
|
||||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
|
||||||
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
void from_toml(T& x, const toml::value& v)
|
|
||||||
{
|
|
||||||
if(v.type() != value_t::Table)
|
|
||||||
throw type_error("from_toml: value type: " + stringize(v.type()) +
|
|
||||||
std::string(" is not argument type: Table"));
|
|
||||||
x.clear();
|
|
||||||
const auto& tb = v.cast<value_t::Table>();
|
|
||||||
for(const auto& kv : tb)
|
|
||||||
{
|
|
||||||
x.insert(kv);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,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;
|
||||||
}
|
}
|
||||||
|
|||||||
838
toml/get.hpp
838
toml/get.hpp
@@ -1,69 +1,821 @@
|
|||||||
#ifndef TOML11_GET
|
// Copyright Toru Niina 2017.
|
||||||
#define TOML11_GET
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_GET_HPP
|
||||||
|
#define TOML11_GET_HPP
|
||||||
|
#include "from.hpp"
|
||||||
|
#include "result.hpp"
|
||||||
#include "value.hpp"
|
#include "value.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
// ============================================================================
|
||||||
typename std::enable_if<(vT != toml::value_t::Unknown &&
|
// exact toml::* type
|
||||||
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
|
|
||||||
inline T get(const toml::value& v)
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline T& get(value& v)
|
||||||
{
|
{
|
||||||
return static_cast<T>(v.cast<vT>());
|
return v.cast<detail::toml_value_t<T>::value>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// array-like type
|
template<typename T, typename std::enable_if<
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
inline T const& get(const value& v)
|
||||||
(!toml::detail::is_map<T>::value) &&
|
|
||||||
toml::detail::is_container<T>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
T get(const toml::value& v)
|
|
||||||
{
|
{
|
||||||
if(v.type() != value_t::Array)
|
return v.cast<detail::toml_value_t<T>::value>();
|
||||||
throw type_error("get: value type: " + stringize(v.type()) +
|
}
|
||||||
std::string(" is not argument type: Array"));
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline T&& get(value&& v)
|
||||||
|
{
|
||||||
|
return std::move(v.cast<detail::toml_value_t<T>::value>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// T == toml::value; identity transformation.
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, ::toml::value>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline T& get(value& v)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, ::toml::value>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline T const& get(const value& v)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, ::toml::value>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline T&& get(value&& v)
|
||||||
|
{
|
||||||
|
return std::move(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// integer convertible from toml::Integer
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
std::is_integral<T>, // T is integral
|
||||||
|
detail::negation<std::is_same<T, bool>>, // but not bool
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // but not toml::integer
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline T get(const value& v)
|
||||||
|
{
|
||||||
|
return static_cast<T>(v.cast<value_t::Integer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// floating point convertible from toml::Float
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
std::is_floating_point<T>, // T is floating_point
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // but not toml::Float
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline T get(const value& v)
|
||||||
|
{
|
||||||
|
return static_cast<T>(v.cast<value_t::Float>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// std::string; toml uses its own toml::string, but it should be convertible to
|
||||||
|
// std::string seamlessly
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline std::string& get(value& v)
|
||||||
|
{
|
||||||
|
return v.cast<value_t::String>().str;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline std::string const& get(const value& v)
|
||||||
|
{
|
||||||
|
return v.cast<value_t::String>().str;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline std::string get(value&& v)
|
||||||
|
{
|
||||||
|
return std::move(v.cast<value_t::String>().str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// std::chrono::duration from toml::local_time.
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_chrono_duration<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline T get(const value& v)
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<T>(
|
||||||
|
std::chrono::nanoseconds(v.cast<value_t::LocalTime>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// std::chrono::system_clock::time_point from toml::datetime variants
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<std::chrono::system_clock::time_point, T>::value,
|
||||||
|
std::nullptr_t>::type = nullptr>
|
||||||
|
inline T get(const value& v)
|
||||||
|
{
|
||||||
|
switch(v.type())
|
||||||
|
{
|
||||||
|
case value_t::LocalDate:
|
||||||
|
{
|
||||||
|
return std::chrono::system_clock::time_point(
|
||||||
|
v.cast<value_t::LocalDate>());
|
||||||
|
}
|
||||||
|
case value_t::LocalDatetime:
|
||||||
|
{
|
||||||
|
return std::chrono::system_clock::time_point(
|
||||||
|
v.cast<value_t::LocalDatetime>());
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return std::chrono::system_clock::time_point(
|
||||||
|
v.cast<value_t::OffsetDatetime>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// forward declaration to use this recursively. ignore this and go ahead.
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::is_container<T>, // T is container
|
||||||
|
detail::has_resize_method<T>, // T::resize(N) works
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // but not toml::array
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T get(const value& v);
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::is_container<T>, // T is container
|
||||||
|
detail::negation<detail::has_resize_method<T>>, // no T::resize() exists
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // not toml::array
|
||||||
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T get(const value& v);
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_std_pair<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T get(const value& v);
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_std_tuple<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T get(const value& v);
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::is_map<T>, // T is map
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // but not toml::table
|
||||||
|
>::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
|
||||||
|
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.
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::is_container<T>, // T is container
|
||||||
|
detail::has_resize_method<T>, // T::resize(N) works
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // but not toml::array
|
||||||
|
>::value, std::nullptr_t>::type>
|
||||||
|
T get(const value& v)
|
||||||
|
{
|
||||||
|
using value_type = typename T::value_type;
|
||||||
|
const auto& ar = v.cast<value_t::Array>();
|
||||||
|
|
||||||
|
T container; container.resize(ar.size());
|
||||||
|
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
||||||
|
[](const value& x){return ::toml::get<value_type>(x);});
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// array-like types; but does not have resize(); most likely std::array.
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::is_container<T>, // T is container
|
||||||
|
detail::negation<detail::has_resize_method<T>>, // no T::resize() exists
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // not toml::array
|
||||||
|
>::value, std::nullptr_t>::type>
|
||||||
|
T get(const value& v)
|
||||||
|
{
|
||||||
|
using value_type = typename T::value_type;
|
||||||
|
const auto& ar = v.cast<value_t::Array>();
|
||||||
|
|
||||||
|
T container;
|
||||||
|
if(ar.size() != container.size())
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"[erorr] toml::get specified container size is ", container.size(),
|
||||||
|
" but there are ", ar.size(), " elements in toml array."), {
|
||||||
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
||||||
|
[](const value& x){return ::toml::get<value_type>(x);});
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// std::pair.
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_std_pair<T>::value, std::nullptr_t>::type>
|
||||||
|
T get(const value& v)
|
||||||
|
{
|
||||||
|
using first_type = typename T::first_type;
|
||||||
|
using second_type = typename T::second_type;
|
||||||
|
|
||||||
const auto& ar = v.cast<value_t::Array>();
|
const auto& ar = v.cast<value_t::Array>();
|
||||||
T tmp;
|
if(ar.size() != 2)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
toml::resize(tmp, ar.size());
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"[erorr] toml::get specified std::pair but there are ", ar.size(),
|
||||||
|
" elements in toml array."), {
|
||||||
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
catch(std::invalid_argument& iv)
|
return std::make_pair(::toml::get<first_type >(ar.at(0)),
|
||||||
{
|
::toml::get<second_type>(ar.at(1)));
|
||||||
throw toml::type_error("toml::get: static array size is not enough");
|
|
||||||
}
|
|
||||||
std::transform(ar.cbegin(), ar.cend(), tmp.begin(),
|
|
||||||
[](toml::value const& elem){return get<typename T::value_type>(elem);});
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// table-like case
|
// ============================================================================
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
// std::tuple.
|
||||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
|
||||||
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T, std::size_t ...I>
|
||||||
|
T get_tuple_impl(const toml::Array& a, index_sequence<I...>)
|
||||||
|
{
|
||||||
|
return std::make_tuple(
|
||||||
|
::toml::get<typename std::tuple_element<I, T>::type>(a.at(I))...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_std_tuple<T>::value, std::nullptr_t>::type>
|
||||||
|
T get(const value& v)
|
||||||
|
{
|
||||||
|
const auto& ar = v.cast<value_t::Array>();
|
||||||
|
if(ar.size() != std::tuple_size<T>::value)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"[erorr] toml::get specified std::tuple with ",
|
||||||
|
std::tuple_size<T>::value, "elements, but there are ", ar.size(),
|
||||||
|
" elements in toml array."), {
|
||||||
|
{std::addressof(detail::get_region(v)), "here"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return detail::get_tuple_impl<T>(ar,
|
||||||
|
detail::make_index_sequence<std::tuple_size<T>::value>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// map-like types; most likely STL map, like std::map or std::unordered_map.
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
|
detail::is_map<T>, // T is map
|
||||||
|
detail::negation<detail::is_exact_toml_type<T>> // but not toml::table
|
||||||
|
>::value, std::nullptr_t>::type>
|
||||||
T get(const toml::value& v)
|
T get(const toml::value& v)
|
||||||
{
|
{
|
||||||
if(v.type() != value_t::Table)
|
using key_type = typename T::key_type;
|
||||||
throw type_error("get: value type: " + stringize(v.type()) +
|
using mapped_type = typename T::mapped_type;
|
||||||
std::string(" is not argument type: Table"));
|
static_assert(std::is_convertible<std::string, key_type>::value,
|
||||||
T tmp;
|
"toml::get only supports map type of which key_type is "
|
||||||
const auto& tb = v.cast<value_t::Table>();
|
"convertible from std::string.");
|
||||||
for(const auto& kv : tb){tmp.insert(kv);}
|
T map;
|
||||||
return tmp;
|
for(const auto& kv : v.cast<value_t::Table>())
|
||||||
|
{
|
||||||
|
map[key_type(kv.first)] = ::toml::get<mapped_type>(kv.second);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get_or -----------------------------------------------------------------
|
|
||||||
|
// ============================================================================
|
||||||
|
// 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
|
||||||
|
|
||||||
|
template<typename T = ::toml::value>
|
||||||
|
decltype(::toml::get<T>(std::declval<const ::toml::value&>()))
|
||||||
|
find(const toml::table& tab, const toml::key& ky,
|
||||||
|
std::string tablename = "unknown table")
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(concat_to_string("[error] key \"", ky,
|
||||||
|
"\" not found in ", tablename));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(tab.at(ky));
|
||||||
|
}
|
||||||
|
template<typename T = ::toml::value>
|
||||||
|
decltype(::toml::get<T>(std::declval<::toml::value&>()))
|
||||||
|
find(toml::table& tab, const toml::key& ky,
|
||||||
|
std::string tablename = "unknown table")
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(concat_to_string("[error] key \"", ky,
|
||||||
|
"\" not found in ", tablename));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(tab[ky]);
|
||||||
|
}
|
||||||
|
template<typename T = ::toml::value>
|
||||||
|
decltype(::toml::get<T>(std::declval<::toml::value&&>()))
|
||||||
|
find(toml::table&& tab, const toml::key& ky,
|
||||||
|
std::string tablename = "unknown table")
|
||||||
|
{
|
||||||
|
if(tab.count(ky) == 0)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(concat_to_string("[error] key \"", ky,
|
||||||
|
"\" not found in ", tablename));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(std::move(tab[ky]));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T = ::toml::value>
|
||||||
|
decltype(::toml::get<T>(std::declval<const ::toml::value&>()))
|
||||||
|
find(const toml::value& v, const toml::key& ky)
|
||||||
|
{
|
||||||
|
const auto& tab = ::toml::get<toml::table>(v);
|
||||||
|
if(tab.count(ky) == 0)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"[error] key \"", ky, "\" not found"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(tab.at(ky));
|
||||||
|
}
|
||||||
|
template<typename T = ::toml::value>
|
||||||
|
decltype(::toml::get<T>(std::declval<::toml::value&>()))
|
||||||
|
find(toml::value& v, const toml::key& ky)
|
||||||
|
{
|
||||||
|
auto& tab = ::toml::get<toml::table>(v);
|
||||||
|
if(tab.count(ky) == 0)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"[error] key \"", ky, "\" not found"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(tab.at(ky));
|
||||||
|
}
|
||||||
|
template<typename T = ::toml::value>
|
||||||
|
decltype(::toml::get<T>(std::declval<::toml::value&&>()))
|
||||||
|
find(toml::value&& v, const toml::key& ky)
|
||||||
|
{
|
||||||
|
auto tab = ::toml::get<toml::table>(std::move(v));
|
||||||
|
if(tab.count(ky) == 0)
|
||||||
|
{
|
||||||
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
|
"[error] key \"", ky, "\" not found"), {
|
||||||
|
{std::addressof(detail::get_region(v)), "in this table"}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return ::toml::get<T>(std::move(tab[ky]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// get_or(value, fallback)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// specialization for the exact toml types (return type becomes lvalue ref)
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T const& get_or(const toml::value& v, const T& opt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return get<typename std::remove_cv<
|
||||||
|
typename std::remove_reference<T>::type>::type>(v);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T& get_or(toml::value& v, T& opt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return get<typename std::remove_cv<
|
||||||
|
typename std::remove_reference<T>::type>::type>(v);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
T&& get_or(toml::value&& v, T&& opt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return get<typename std::remove_cv<
|
||||||
|
typename std::remove_reference<T>::type>::type>(v);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// specialization for std::string (return type becomes lvalue ref)
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
std::string const& get_or(const toml::value& v, const T& opt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
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<
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// 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 get_or(const toml::value& v, T&& opt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return get<typename std::remove_cv<
|
||||||
|
typename std::remove_reference<T>::type>::type>(v);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
// get_or(table, key, fallback)
|
||||||
|
//
|
||||||
|
// DEPRECATED: use find_or instead.
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline typename std::remove_cv<typename std::remove_reference<T>::type>::type
|
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
|
||||||
get_or(const toml::Table& tab, const toml::key& ky, T&& opt)
|
auto get_or(const toml::table& tab, const toml::key& ky, T&& opt)
|
||||||
|
-> decltype(get_or(std::declval<value const&>(), std::forward<T>(opt)))
|
||||||
{
|
{
|
||||||
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
return get<typename std::remove_cv<
|
return ::toml::get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
typename std::remove_reference<T>::type>::type>(tab.find(ky)->second);
|
}
|
||||||
|
template<typename T>
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
|
||||||
|
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 opt;}
|
||||||
|
return ::toml::get_or(tab[ky], std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
|
||||||
|
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 opt;}
|
||||||
|
return ::toml::get_or(std::move(tab[ky]), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
|
||||||
|
auto get_or(const toml::value& v, const toml::key& ky, T&& opt)
|
||||||
|
-> decltype(get_or(std::declval<value const&>(), std::forward<T>(opt)))
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
const auto& tab = toml::get<toml::table>(v);
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return ::toml::get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
|
||||||
|
auto get_or(toml::value& v, const toml::key& ky, T&& opt)
|
||||||
|
-> decltype(get_or(std::declval<value&>(), std::forward<T>(opt)))
|
||||||
|
{
|
||||||
|
if(!v.is_table()) {return opt;}
|
||||||
|
auto& tab = toml::get<toml::table>(v);
|
||||||
|
if(tab.count(ky) == 0) {return opt;}
|
||||||
|
return ::toml::get_or(tab[ky], std::forward<T>(opt));
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
|
||||||
|
auto get_or(toml::value&& v, const toml::key& ky, T&& opt)
|
||||||
|
-> decltype(get_or(std::declval<value&&>(), std::forward<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 ::toml::get_or(std::move(tab[ky]), std::forward<T>(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);
|
||||||
|
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::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<
|
||||||
|
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.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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// expect
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
result<T, std::string> expect(const toml::value& v) noexcept
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ok(get<T>(v));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
return err(e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
result<T, std::string> expect(const toml::value& v, const toml::key& k) noexcept
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ok(find<T>(v, k));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
return err(e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
result<T, std::string> expect(const toml::table& t, const toml::key& k,
|
||||||
|
std::string tablename = "unknown table") noexcept
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ok(find<T>(t, k, std::move(tablename)));
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
return err(e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // toml
|
} // toml
|
||||||
|
|||||||
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
|
||||||
222
toml/lexer.hpp
Normal file
222
toml/lexer.hpp
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
// Copyright Toru Niina 2017.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_LEXER_HPP
|
||||||
|
#define TOML11_LEXER_HPP
|
||||||
|
#include "combinator.hpp"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <istream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// these scans contents from current location in a container of char
|
||||||
|
// and extract a region that matches their own pattern.
|
||||||
|
// to see the implementation of each component, see combinator.hpp.
|
||||||
|
|
||||||
|
using lex_wschar = either<character<' '>, character<'\t'>>;
|
||||||
|
using lex_ws = repeat<lex_wschar, at_least<1>>;
|
||||||
|
using lex_newline = either<character<'\n'>,
|
||||||
|
sequence<character<'\r'>, character<'\n'>>>;
|
||||||
|
using lex_lower = in_range<'a', 'z'>;
|
||||||
|
using lex_upper = in_range<'A', 'Z'>;
|
||||||
|
using lex_alpha = either<lex_lower, lex_upper>;
|
||||||
|
using lex_digit = in_range<'0', '9'>;
|
||||||
|
using lex_nonzero = in_range<'1', '9'>;
|
||||||
|
using lex_oct_dig = in_range<'0', '7'>;
|
||||||
|
using lex_bin_dig = in_range<'0', '1'>;
|
||||||
|
using lex_hex_dig = either<lex_digit, in_range<'A', 'F'>, in_range<'a', 'f'>>;
|
||||||
|
|
||||||
|
using lex_hex_prefix = sequence<character<'0'>, character<'x'>>;
|
||||||
|
using lex_oct_prefix = sequence<character<'0'>, character<'o'>>;
|
||||||
|
using lex_bin_prefix = sequence<character<'0'>, character<'b'>>;
|
||||||
|
using lex_underscore = character<'_'>;
|
||||||
|
using lex_plus = character<'+'>;
|
||||||
|
using lex_minus = character<'-'>;
|
||||||
|
using lex_sign = either<lex_plus, lex_minus>;
|
||||||
|
|
||||||
|
// digit | nonzero 1*(digit | _ digit)
|
||||||
|
using lex_unsigned_dec_int = either<sequence<lex_nonzero, repeat<
|
||||||
|
either<lex_digit, sequence<lex_underscore, lex_digit>>, at_least<1>>>,
|
||||||
|
lex_digit>;
|
||||||
|
// (+|-)? unsigned_dec_int
|
||||||
|
using lex_dec_int = sequence<maybe<lex_sign>, lex_unsigned_dec_int>;
|
||||||
|
|
||||||
|
// hex_prefix hex_dig *(hex_dig | _ hex_dig)
|
||||||
|
using lex_hex_int = sequence<lex_hex_prefix, sequence<lex_hex_dig, repeat<
|
||||||
|
either<lex_hex_dig, sequence<lex_underscore, lex_hex_dig>>, unlimited>>>;
|
||||||
|
// oct_prefix oct_dig *(oct_dig | _ oct_dig)
|
||||||
|
using lex_oct_int = sequence<lex_oct_prefix, sequence<lex_oct_dig, repeat<
|
||||||
|
either<lex_oct_dig, sequence<lex_underscore, lex_oct_dig>>, unlimited>>>;
|
||||||
|
// bin_prefix bin_dig *(bin_dig | _ bin_dig)
|
||||||
|
using lex_bin_int = sequence<lex_bin_prefix, sequence<lex_bin_dig, repeat<
|
||||||
|
either<lex_bin_dig, sequence<lex_underscore, lex_bin_dig>>, unlimited>>>;
|
||||||
|
|
||||||
|
// (dec_int | hex_int | oct_int | bin_int)
|
||||||
|
using lex_integer = either<lex_bin_int, lex_oct_int, lex_hex_int, lex_dec_int>;
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
|
||||||
|
using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
|
||||||
|
using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
|
||||||
|
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>, lex_dec_int>;
|
||||||
|
|
||||||
|
using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
|
||||||
|
sequence<lex_underscore, lex_digit>>, unlimited>>;
|
||||||
|
using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;
|
||||||
|
|
||||||
|
using lex_float = either<lex_special_float,
|
||||||
|
sequence<lex_dec_int, either<lex_exponent_part,
|
||||||
|
sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
using lex_true = sequence<character<'t'>, character<'r'>,
|
||||||
|
character<'u'>, character<'e'>>;
|
||||||
|
using lex_false = sequence<character<'f'>, character<'a'>, character<'l'>,
|
||||||
|
character<'s'>, character<'e'>>;
|
||||||
|
using lex_boolean = either<lex_true, lex_false>;
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
using lex_date_fullyear = repeat<lex_digit, exactly<4>>;
|
||||||
|
using lex_date_month = repeat<lex_digit, exactly<2>>;
|
||||||
|
using lex_date_mday = repeat<lex_digit, exactly<2>>;
|
||||||
|
using lex_time_delim = either<character<'T'>, character<'t'>, character<' '>>;
|
||||||
|
using lex_time_hour = repeat<lex_digit, exactly<2>>;
|
||||||
|
using lex_time_minute = repeat<lex_digit, exactly<2>>;
|
||||||
|
using lex_time_second = repeat<lex_digit, exactly<2>>;
|
||||||
|
using lex_time_secfrac = sequence<character<'.'>,
|
||||||
|
repeat<lex_digit, at_least<1>>>;
|
||||||
|
|
||||||
|
using lex_time_numoffset = sequence<either<character<'+'>, character<'-'>>,
|
||||||
|
sequence<lex_time_hour, character<':'>,
|
||||||
|
lex_time_minute>>;
|
||||||
|
using lex_time_offset = either<character<'Z'>, character<'z'>,
|
||||||
|
lex_time_numoffset>;
|
||||||
|
|
||||||
|
using lex_partial_time = sequence<lex_time_hour, character<':'>,
|
||||||
|
lex_time_minute, character<':'>,
|
||||||
|
lex_time_second, maybe<lex_time_secfrac>>;
|
||||||
|
using lex_full_date = sequence<lex_date_fullyear, character<'-'>,
|
||||||
|
lex_date_month, character<'-'>,
|
||||||
|
lex_date_mday>;
|
||||||
|
using lex_full_time = sequence<lex_partial_time, lex_time_offset>;
|
||||||
|
|
||||||
|
using lex_offset_date_time = sequence<lex_full_date, lex_time_delim, lex_full_time>;
|
||||||
|
using lex_local_date_time = sequence<lex_full_date, lex_time_delim, lex_partial_time>;
|
||||||
|
using lex_local_date = lex_full_date;
|
||||||
|
using lex_local_time = lex_partial_time;
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
using lex_quotation_mark = character<'"'>;
|
||||||
|
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
|
||||||
|
character<0x22>, character<0x5C>,
|
||||||
|
character<0x7F>>>;
|
||||||
|
using lex_escape = character<'\\'>;
|
||||||
|
using lex_escape_unicode_short = sequence<character<'u'>,
|
||||||
|
repeat<lex_hex_dig, exactly<4>>>;
|
||||||
|
using lex_escape_unicode_long = sequence<character<'U'>,
|
||||||
|
repeat<lex_hex_dig, exactly<8>>>;
|
||||||
|
using lex_escape_seq_char = either<character<'"'>, character<'\\'>,
|
||||||
|
character<'b'>, character<'f'>,
|
||||||
|
character<'n'>, character<'r'>,
|
||||||
|
character<'t'>,
|
||||||
|
lex_escape_unicode_short,
|
||||||
|
lex_escape_unicode_long
|
||||||
|
>;
|
||||||
|
using lex_escaped = sequence<lex_escape, lex_escape_seq_char>;
|
||||||
|
using lex_basic_char = either<lex_basic_unescaped, lex_escaped>;
|
||||||
|
using lex_basic_string = sequence<lex_quotation_mark,
|
||||||
|
repeat<lex_basic_char, unlimited>,
|
||||||
|
lex_quotation_mark>;
|
||||||
|
|
||||||
|
using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
|
||||||
|
using lex_ml_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
|
||||||
|
character<0x5C>,
|
||||||
|
character<0x7F>,
|
||||||
|
lex_ml_basic_string_delim>>;
|
||||||
|
|
||||||
|
using lex_ml_basic_escaped_newline = sequence<
|
||||||
|
lex_escape, maybe<lex_ws>, lex_newline,
|
||||||
|
repeat<either<lex_ws, lex_newline>, unlimited>>;
|
||||||
|
|
||||||
|
using lex_ml_basic_char = either<lex_ml_basic_unescaped, lex_escaped>;
|
||||||
|
using lex_ml_basic_body = repeat<either<lex_ml_basic_char, lex_newline,
|
||||||
|
lex_ml_basic_escaped_newline>,
|
||||||
|
unlimited>;
|
||||||
|
using lex_ml_basic_string = sequence<lex_ml_basic_string_delim,
|
||||||
|
lex_ml_basic_body,
|
||||||
|
lex_ml_basic_string_delim>;
|
||||||
|
|
||||||
|
using lex_literal_char = exclude<either<in_range<0x00, 0x08>,
|
||||||
|
in_range<0x10, 0x19>, character<0x27>>>;
|
||||||
|
using lex_apostrophe = character<'\''>;
|
||||||
|
using lex_literal_string = sequence<lex_apostrophe,
|
||||||
|
repeat<lex_literal_char, unlimited>,
|
||||||
|
lex_apostrophe>;
|
||||||
|
|
||||||
|
using lex_ml_literal_string_delim = repeat<lex_apostrophe, exactly<3>>;
|
||||||
|
|
||||||
|
using lex_ml_literal_char = exclude<either<in_range<0x00, 0x08>,
|
||||||
|
in_range<0x10, 0x1F>,
|
||||||
|
character<0x7F>,
|
||||||
|
lex_ml_literal_string_delim>>;
|
||||||
|
using lex_ml_literal_body = repeat<either<lex_ml_literal_char, lex_newline>,
|
||||||
|
unlimited>;
|
||||||
|
using lex_ml_literal_string = sequence<lex_ml_literal_string_delim,
|
||||||
|
lex_ml_literal_body,
|
||||||
|
lex_ml_literal_string_delim>;
|
||||||
|
|
||||||
|
using lex_string = either<lex_ml_basic_string, lex_basic_string,
|
||||||
|
lex_ml_literal_string, lex_literal_string>;
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
using lex_comment_start_symbol = character<'#'>;
|
||||||
|
using lex_non_eol = either<character<'\t'>, exclude<in_range<0x00, 0x19>>>;
|
||||||
|
using lex_comment = sequence<lex_comment_start_symbol,
|
||||||
|
repeat<lex_non_eol, unlimited>>;
|
||||||
|
|
||||||
|
using lex_dot_sep = sequence<maybe<lex_ws>, character<'.'>, maybe<lex_ws>>;
|
||||||
|
|
||||||
|
using lex_unquoted_key = repeat<either<lex_alpha, lex_digit,
|
||||||
|
character<'-'>, character<'_'>>,
|
||||||
|
at_least<1>>;
|
||||||
|
using lex_quoted_key = either<lex_basic_string, lex_literal_string>;
|
||||||
|
using lex_simple_key = either<lex_unquoted_key, lex_quoted_key>;
|
||||||
|
using lex_dotted_key = sequence<lex_simple_key,
|
||||||
|
repeat<sequence<lex_dot_sep, lex_simple_key>,
|
||||||
|
at_least<1>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
using lex_key = either<lex_dotted_key, lex_simple_key>;
|
||||||
|
|
||||||
|
using lex_keyval_sep = sequence<maybe<lex_ws>,
|
||||||
|
character<'='>,
|
||||||
|
maybe<lex_ws>>;
|
||||||
|
|
||||||
|
using lex_std_table_open = character<'['>;
|
||||||
|
using lex_std_table_close = character<']'>;
|
||||||
|
using lex_std_table = sequence<lex_std_table_open,
|
||||||
|
maybe<lex_ws>,
|
||||||
|
lex_key,
|
||||||
|
maybe<lex_ws>,
|
||||||
|
lex_std_table_close>;
|
||||||
|
|
||||||
|
using lex_array_table_open = sequence<lex_std_table_open, lex_std_table_open>;
|
||||||
|
using lex_array_table_close = sequence<lex_std_table_close, lex_std_table_close>;
|
||||||
|
using lex_array_table = sequence<lex_array_table_open,
|
||||||
|
maybe<lex_ws>,
|
||||||
|
lex_key,
|
||||||
|
maybe<lex_ws>,
|
||||||
|
lex_array_table_close>;
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // toml
|
||||||
|
#endif // TOML_LEXER_HPP
|
||||||
55
toml/literal.hpp
Normal file
55
toml/literal.hpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// 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);
|
||||||
|
|
||||||
|
// literal may be a bare value. try them first.
|
||||||
|
if(auto data = ::toml::detail::parse_value(loc))
|
||||||
|
{
|
||||||
|
return data.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// literal is a TOML file (i.e. multiline table).
|
||||||
|
if(auto data = ::toml::detail::parse_toml_file(loc))
|
||||||
|
{
|
||||||
|
loc.reset(loc.begin()); // rollback to the top of the literal
|
||||||
|
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
|
||||||
2616
toml/parser.hpp
2616
toml/parser.hpp
File diff suppressed because it is too large
Load Diff
370
toml/region.hpp
Normal file
370
toml/region.hpp
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
// Copyright Toru Niina 2017.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_REGION_HPP
|
||||||
|
#define TOML11_REGION_HPP
|
||||||
|
#include "exception.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <iterator>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// helper function to avoid std::string(0, 'c') or std::string(iter, iter)
|
||||||
|
template<typename Iterator>
|
||||||
|
std::string make_string(Iterator first, Iterator last)
|
||||||
|
{
|
||||||
|
if(first == last) {return "";}
|
||||||
|
return std::string(first, last);
|
||||||
|
}
|
||||||
|
inline std::string make_string(std::size_t len, char c)
|
||||||
|
{
|
||||||
|
if(len == 0) {return "";}
|
||||||
|
return std::string(len, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// region_base is a base class of location and region that are defined below.
|
||||||
|
// it will be used to generate better error messages.
|
||||||
|
struct region_base
|
||||||
|
{
|
||||||
|
region_base() = default;
|
||||||
|
virtual ~region_base() = default;
|
||||||
|
region_base(const region_base&) = default;
|
||||||
|
region_base(region_base&& ) = default;
|
||||||
|
region_base& operator=(const region_base&) = default;
|
||||||
|
region_base& operator=(region_base&& ) = default;
|
||||||
|
|
||||||
|
virtual bool is_ok() const noexcept {return false;}
|
||||||
|
|
||||||
|
virtual std::string str() const {return std::string("unknown region");}
|
||||||
|
virtual std::string name() const {return std::string("unknown file");}
|
||||||
|
virtual std::string line() const {return std::string("unknown line");}
|
||||||
|
virtual std::string line_num() const {return std::string("?");}
|
||||||
|
|
||||||
|
// length of the region
|
||||||
|
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;}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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_(0),
|
||||||
|
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 At first, `location::line_num()` is 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 and returns a negative
|
||||||
|
// value if `first` is ahead from `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>
|
||||||
|
struct region 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");
|
||||||
|
|
||||||
|
// delete default constructor. source_ never be null.
|
||||||
|
region() = delete;
|
||||||
|
|
||||||
|
region(const location<Container>& loc)
|
||||||
|
: source_(loc.source()), source_name_(loc.name()),
|
||||||
|
first_(loc.iter()), last_(loc.iter())
|
||||||
|
{}
|
||||||
|
region(location<Container>&& loc)
|
||||||
|
: source_(loc.source()), source_name_(loc.name()),
|
||||||
|
first_(loc.iter()), last_(loc.iter())
|
||||||
|
{}
|
||||||
|
|
||||||
|
region(const location<Container>& loc, const_iterator f, const_iterator l)
|
||||||
|
: source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
|
||||||
|
{}
|
||||||
|
region(location<Container>&& loc, const_iterator f, const_iterator l)
|
||||||
|
: source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
|
||||||
|
{}
|
||||||
|
|
||||||
|
region(const region&) = default;
|
||||||
|
region(region&&) = default;
|
||||||
|
region& operator=(const region&) = default;
|
||||||
|
region& operator=(region&&) = default;
|
||||||
|
~region() = default;
|
||||||
|
|
||||||
|
region& operator+=(const region& other)
|
||||||
|
{
|
||||||
|
if(this->begin() != other.begin() || this->end() != other.end() ||
|
||||||
|
this->last_ != other.first_)
|
||||||
|
{
|
||||||
|
throw internal_error("invalid region concatenation");
|
||||||
|
}
|
||||||
|
this->last_ = other.last_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ok() const noexcept override {return static_cast<bool>(source_);}
|
||||||
|
|
||||||
|
std::string str() const override {return make_string(first_, last_);}
|
||||||
|
std::string line() const override
|
||||||
|
{
|
||||||
|
if(this->contain_newline())
|
||||||
|
{
|
||||||
|
return make_string(this->line_begin(),
|
||||||
|
std::find(this->line_begin(), this->last(), '\n'));
|
||||||
|
}
|
||||||
|
return make_string(this->line_begin(), this->line_end());
|
||||||
|
}
|
||||||
|
std::string line_num() const override
|
||||||
|
{
|
||||||
|
return std::to_string(1 + std::count(this->begin(), this->first(), '\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const noexcept override
|
||||||
|
{
|
||||||
|
return std::distance(first_, last_);
|
||||||
|
}
|
||||||
|
std::size_t before() const noexcept override
|
||||||
|
{
|
||||||
|
return std::distance(this->line_begin(), this->first());
|
||||||
|
}
|
||||||
|
std::size_t after() const noexcept override
|
||||||
|
{
|
||||||
|
return std::distance(this->last(), this->line_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contain_newline() const noexcept
|
||||||
|
{
|
||||||
|
return std::find(this->first(), this->last(), '\n') != this->last();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator line_begin() const noexcept
|
||||||
|
{
|
||||||
|
using reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
return std::find(reverse_iterator(this->first()),
|
||||||
|
reverse_iterator(this->begin()), '\n').base();
|
||||||
|
}
|
||||||
|
const_iterator line_end() const noexcept
|
||||||
|
{
|
||||||
|
return std::find(this->last(), this->end(), '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const noexcept {return source_->cbegin();}
|
||||||
|
const_iterator end() const noexcept {return source_->cend();}
|
||||||
|
const_iterator first() const noexcept {return first_;}
|
||||||
|
const_iterator last() const noexcept {return last_;}
|
||||||
|
|
||||||
|
source_ptr const& source() const& noexcept {return source_;}
|
||||||
|
source_ptr&& source() && noexcept {return std::move(source_);}
|
||||||
|
|
||||||
|
std::string name() const override {return source_name_;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
source_ptr source_;
|
||||||
|
std::string source_name_;
|
||||||
|
const_iterator first_, last_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// to show a better error message.
|
||||||
|
inline std::string format_underline(const std::string& message,
|
||||||
|
std::vector<std::pair<region_base const*, std::string>> reg_com,
|
||||||
|
std::vector<std::string> helps = {})
|
||||||
|
{
|
||||||
|
assert(!reg_com.empty());
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
const auto newline = "\r\n";
|
||||||
|
#else
|
||||||
|
const char newline = '\n';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const auto line_num_width = std::max_element(reg_com.begin(), reg_com.end(),
|
||||||
|
[](std::pair<region_base const*, std::string> const& lhs,
|
||||||
|
std::pair<region_base const*, std::string> const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.first->line_num().size() < rhs.first->line_num().size();
|
||||||
|
}
|
||||||
|
)->first->line_num().size();
|
||||||
|
|
||||||
|
std::ostringstream retval;
|
||||||
|
retval << message << newline;
|
||||||
|
|
||||||
|
for(std::size_t i=0; i<reg_com.size(); ++i)
|
||||||
|
{
|
||||||
|
if(i!=0 && reg_com.at(i-1).first->name() == reg_com.at(i).first->name())
|
||||||
|
{
|
||||||
|
retval << newline << " ..." << newline;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(i != 0) {retval << newline;}
|
||||||
|
retval << " --> " << reg_com.at(i).first->name() << 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(reg->before(), ' ');
|
||||||
|
|
||||||
|
if(reg->size() == 1)
|
||||||
|
{
|
||||||
|
// invalid
|
||||||
|
// ^------
|
||||||
|
retval << '^';
|
||||||
|
retval << make_string(reg->after(), '-');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// invalid
|
||||||
|
// ~~~~~~~
|
||||||
|
retval << make_string(reg->size(), '~');
|
||||||
|
}
|
||||||
|
|
||||||
|
retval << ' ';
|
||||||
|
retval << comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(helps.size() != 0)
|
||||||
|
{
|
||||||
|
retval << newline;
|
||||||
|
retval << make_string(line_num_width + 1, ' ');
|
||||||
|
retval << " | ";
|
||||||
|
for(const auto help : helps)
|
||||||
|
{
|
||||||
|
retval << newline;
|
||||||
|
retval << "Hint: ";
|
||||||
|
retval << help;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // toml
|
||||||
|
#endif// TOML11_REGION_H
|
||||||
664
toml/result.hpp
Normal file
664
toml/result.hpp
Normal file
@@ -0,0 +1,664 @@
|
|||||||
|
// Copyright Toru Niina 2017.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_RESULT_HPP
|
||||||
|
#define TOML11_RESULT_HPP
|
||||||
|
#include "traits.hpp"
|
||||||
|
#include <type_traits>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
#include <new>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct success
|
||||||
|
{
|
||||||
|
using value_type = T;
|
||||||
|
value_type value;
|
||||||
|
|
||||||
|
explicit success(const value_type& v)
|
||||||
|
noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||||
|
: value(v)
|
||||||
|
{}
|
||||||
|
explicit success(value_type&& v)
|
||||||
|
noexcept(std::is_nothrow_move_constructible<value_type>::value)
|
||||||
|
: value(std::move(v))
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
explicit success(U&& v): value(std::forward<U>(v)) {}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
explicit success(const success<U>& v): value(v.value) {}
|
||||||
|
template<typename U>
|
||||||
|
explicit success(success<U>&& v): value(std::move(v.value)) {}
|
||||||
|
|
||||||
|
~success() = default;
|
||||||
|
success(const success&) = default;
|
||||||
|
success(success&&) = default;
|
||||||
|
success& operator=(const success&) = default;
|
||||||
|
success& operator=(success&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct failure
|
||||||
|
{
|
||||||
|
using value_type = T;
|
||||||
|
value_type value;
|
||||||
|
|
||||||
|
explicit failure(const value_type& v)
|
||||||
|
noexcept(std::is_nothrow_copy_constructible<value_type>::value)
|
||||||
|
: value(v)
|
||||||
|
{}
|
||||||
|
explicit failure(value_type&& v)
|
||||||
|
noexcept(std::is_nothrow_move_constructible<value_type>::value)
|
||||||
|
: value(std::move(v))
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
explicit failure(U&& v): value(std::forward<U>(v)) {}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
explicit failure(const failure<U>& v): value(v.value) {}
|
||||||
|
template<typename U>
|
||||||
|
explicit failure(failure<U>&& v): value(std::move(v.value)) {}
|
||||||
|
|
||||||
|
~failure() = default;
|
||||||
|
failure(const failure&) = default;
|
||||||
|
failure(failure&&) = default;
|
||||||
|
failure& operator=(const failure&) = default;
|
||||||
|
failure& operator=(failure&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
success<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
|
||||||
|
ok(T&& v)
|
||||||
|
{
|
||||||
|
return success<
|
||||||
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type
|
||||||
|
>(std::forward<T>(v));
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
failure<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
|
||||||
|
err(T&& v)
|
||||||
|
{
|
||||||
|
return failure<
|
||||||
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type
|
||||||
|
>(std::forward<T>(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline success<std::string> ok(const char* literal)
|
||||||
|
{
|
||||||
|
return success<std::string>(std::string(literal));
|
||||||
|
}
|
||||||
|
inline failure<std::string> err(const char* literal)
|
||||||
|
{
|
||||||
|
return failure<std::string>(std::string(literal));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T, typename E>
|
||||||
|
struct result
|
||||||
|
{
|
||||||
|
using value_type = T;
|
||||||
|
using error_type = E;
|
||||||
|
using success_type = success<value_type>;
|
||||||
|
using failure_type = failure<error_type>;
|
||||||
|
|
||||||
|
result(const success_type& s): is_ok_(true)
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
result(const failure_type& f): is_ok_(false)
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
result(success_type&& s): is_ok_(true)
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
result(failure_type&& f): is_ok_(false)
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
result(const success<U>& s): is_ok_(true)
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
result(const failure<U>& f): is_ok_(false)
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
result(success<U>&& s): is_ok_(true)
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
result(failure<U>&& f): is_ok_(false)
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
|
||||||
|
result& operator=(const success_type& s)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->is_ok_ = true;
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
result& operator=(const failure_type& f)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->is_ok_ = false;
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
result& operator=(success_type&& s)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->is_ok_ = true;
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
result& operator=(failure_type&& f)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->is_ok_ = false;
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
result& operator=(const success<U>& s)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->is_ok_ = true;
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
result& operator=(const failure<U>& f)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->is_ok_ = false;
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
result& operator=(success<U>&& s)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->is_ok_ = true;
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
result& operator=(failure<U>&& f)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->is_ok_ = false;
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~result() noexcept {this->cleanup();}
|
||||||
|
|
||||||
|
result(const result& other): is_ok_(other.is_ok())
|
||||||
|
{
|
||||||
|
if(other.is_ok())
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result(result&& other): is_ok_(other.is_ok())
|
||||||
|
{
|
||||||
|
if(other.is_ok())
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U, typename F>
|
||||||
|
result(const result<U, F>& other): is_ok_(other.is_ok())
|
||||||
|
{
|
||||||
|
if(other.is_ok())
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename U, typename F>
|
||||||
|
result(result<U, F>&& other): is_ok_(other.is_ok())
|
||||||
|
{
|
||||||
|
if(other.is_ok())
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result& operator=(const result& other)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
if(other.is_ok())
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
is_ok_ = other.is_ok();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
result& operator=(result&& other)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
if(other.is_ok())
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
is_ok_ = other.is_ok();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U, typename F>
|
||||||
|
result& operator=(const result<U, F>& other)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
if(other.is_ok())
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
is_ok_ = other.is_ok();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename U, typename F>
|
||||||
|
result& operator=(result<U, F>&& other)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
if(other.is_ok())
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||||
|
assert(tmp == std::addressof(this->succ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||||
|
assert(tmp == std::addressof(this->fail));
|
||||||
|
}
|
||||||
|
is_ok_ = other.is_ok();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ok() const noexcept {return is_ok_;}
|
||||||
|
bool is_err() const noexcept {return !is_ok_;}
|
||||||
|
|
||||||
|
operator bool() const noexcept {return is_ok_;}
|
||||||
|
|
||||||
|
value_type& unwrap() &
|
||||||
|
{
|
||||||
|
if(is_err())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("toml::result: bad unwrap: " +
|
||||||
|
format_error(this->as_err()));
|
||||||
|
}
|
||||||
|
return this->succ.value;
|
||||||
|
}
|
||||||
|
value_type const& unwrap() const&
|
||||||
|
{
|
||||||
|
if(is_err())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("toml::result: bad unwrap: " +
|
||||||
|
format_error(this->as_err()));
|
||||||
|
}
|
||||||
|
return this->succ.value;
|
||||||
|
}
|
||||||
|
value_type&& unwrap() &&
|
||||||
|
{
|
||||||
|
if(is_err())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("toml::result: bad unwrap: " +
|
||||||
|
format_error(this->as_err()));
|
||||||
|
}
|
||||||
|
return std::move(this->succ.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type& unwrap_or(value_type& opt) &
|
||||||
|
{
|
||||||
|
if(is_err()) {return opt;}
|
||||||
|
return this->succ.value;
|
||||||
|
}
|
||||||
|
value_type const& unwrap_or(value_type const& opt) const&
|
||||||
|
{
|
||||||
|
if(is_err()) {return opt;}
|
||||||
|
return this->succ.value;
|
||||||
|
}
|
||||||
|
value_type unwrap_or(value_type opt) &&
|
||||||
|
{
|
||||||
|
if(is_err()) {return opt;}
|
||||||
|
return this->succ.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_type& unwrap_err() &
|
||||||
|
{
|
||||||
|
if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
|
||||||
|
return this->fail.value;
|
||||||
|
}
|
||||||
|
error_type const& unwrap_err() const&
|
||||||
|
{
|
||||||
|
if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
|
||||||
|
return this->fail.value;
|
||||||
|
}
|
||||||
|
error_type&& unwrap_err() &&
|
||||||
|
{
|
||||||
|
if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
|
||||||
|
return std::move(this->fail.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type& as_ok() & noexcept {return this->succ.value;}
|
||||||
|
value_type const& as_ok() const& noexcept {return this->succ.value;}
|
||||||
|
value_type&& as_ok() && noexcept {return std::move(this->succ.value);}
|
||||||
|
|
||||||
|
error_type& as_err() & noexcept {return this->fail.value;}
|
||||||
|
error_type const& as_err() const& noexcept {return this->fail.value;}
|
||||||
|
error_type&& as_err() && noexcept {return std::move(this->fail.value);}
|
||||||
|
|
||||||
|
|
||||||
|
// prerequisities
|
||||||
|
// F: T -> U
|
||||||
|
// retval: result<U, E>
|
||||||
|
template<typename F>
|
||||||
|
result<detail::return_type_of_t<F, value_type&>, error_type>
|
||||||
|
map(F&& f) &
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return ok(f(this->as_ok()));}
|
||||||
|
return err(this->as_err());
|
||||||
|
}
|
||||||
|
template<typename F>
|
||||||
|
result<detail::return_type_of_t<F, value_type const&>, error_type>
|
||||||
|
map(F&& f) const&
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return ok(f(this->as_ok()));}
|
||||||
|
return err(this->as_err());
|
||||||
|
}
|
||||||
|
template<typename F>
|
||||||
|
result<detail::return_type_of_t<F, value_type &&>, error_type>
|
||||||
|
map(F&& f) &&
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return ok(f(std::move(this->as_ok())));}
|
||||||
|
return err(std::move(this->as_err()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// prerequisities
|
||||||
|
// F: E -> F
|
||||||
|
// retval: result<T, F>
|
||||||
|
template<typename F>
|
||||||
|
result<value_type, detail::return_type_of_t<F, error_type&>>
|
||||||
|
map_err(F&& f) &
|
||||||
|
{
|
||||||
|
if(this->is_err()){return err(f(this->as_err()));}
|
||||||
|
return ok(this->as_ok());
|
||||||
|
}
|
||||||
|
template<typename F>
|
||||||
|
result<value_type, detail::return_type_of_t<F, error_type const&>>
|
||||||
|
map_err(F&& f) const&
|
||||||
|
{
|
||||||
|
if(this->is_err()){return err(f(this->as_err()));}
|
||||||
|
return ok(this->as_ok());
|
||||||
|
}
|
||||||
|
template<typename F>
|
||||||
|
result<value_type, detail::return_type_of_t<F, error_type&&>>
|
||||||
|
map_err(F&& f) &&
|
||||||
|
{
|
||||||
|
if(this->is_err()){return err(f(std::move(this->as_err())));}
|
||||||
|
return ok(std::move(this->as_ok()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// prerequisities
|
||||||
|
// F: T -> U
|
||||||
|
// retval: U
|
||||||
|
template<typename F, typename U>
|
||||||
|
detail::return_type_of_t<F, value_type&>
|
||||||
|
map_or_else(F&& f, U&& opt) &
|
||||||
|
{
|
||||||
|
if(this->is_err()){return std::forward<U>(opt);}
|
||||||
|
return f(this->as_ok());
|
||||||
|
}
|
||||||
|
template<typename F, typename U>
|
||||||
|
detail::return_type_of_t<F, value_type const&>
|
||||||
|
map_or_else(F&& f, U&& opt) const&
|
||||||
|
{
|
||||||
|
if(this->is_err()){return std::forward<U>(opt);}
|
||||||
|
return f(this->as_ok());
|
||||||
|
}
|
||||||
|
template<typename F, typename U>
|
||||||
|
detail::return_type_of_t<F, value_type&&>
|
||||||
|
map_or_else(F&& f, U&& opt) &&
|
||||||
|
{
|
||||||
|
if(this->is_err()){return std::forward<U>(opt);}
|
||||||
|
return f(std::move(this->as_ok()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// prerequisities
|
||||||
|
// F: E -> U
|
||||||
|
// retval: U
|
||||||
|
template<typename F, typename U>
|
||||||
|
detail::return_type_of_t<F, error_type&>
|
||||||
|
map_err_or_else(F&& f, U&& opt) &
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return std::forward<U>(opt);}
|
||||||
|
return f(this->as_err());
|
||||||
|
}
|
||||||
|
template<typename F, typename U>
|
||||||
|
detail::return_type_of_t<F, error_type const&>
|
||||||
|
map_err_or_else(F&& f, U&& opt) const&
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return std::forward<U>(opt);}
|
||||||
|
return f(this->as_err());
|
||||||
|
}
|
||||||
|
template<typename F, typename U>
|
||||||
|
detail::return_type_of_t<F, error_type&&>
|
||||||
|
map_err_or_else(F&& f, U&& opt) &&
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return std::forward<U>(opt);}
|
||||||
|
return f(std::move(this->as_err()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// prerequisities:
|
||||||
|
// F: func T -> U
|
||||||
|
// toml::err(error_type) should be convertible to U.
|
||||||
|
// normally, type U is another result<S, F> and E is convertible to F
|
||||||
|
template<typename F>
|
||||||
|
detail::return_type_of_t<F, value_type&>
|
||||||
|
and_then(F&& f) &
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return f(this->as_ok());}
|
||||||
|
return err(this->as_err());
|
||||||
|
}
|
||||||
|
template<typename F>
|
||||||
|
detail::return_type_of_t<F, value_type const&>
|
||||||
|
and_then(F&& f) const&
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return f(this->as_ok());}
|
||||||
|
return err(this->as_err());
|
||||||
|
}
|
||||||
|
template<typename F>
|
||||||
|
detail::return_type_of_t<F, value_type&&>
|
||||||
|
and_then(F&& f) &&
|
||||||
|
{
|
||||||
|
if(this->is_ok()){return f(std::move(this->as_ok()));}
|
||||||
|
return err(std::move(this->as_err()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// prerequisities:
|
||||||
|
// F: func E -> U
|
||||||
|
// toml::ok(value_type) should be convertible to U.
|
||||||
|
// normally, type U is another result<S, F> and T is convertible to S
|
||||||
|
template<typename F>
|
||||||
|
detail::return_type_of_t<F, error_type&>
|
||||||
|
or_else(F&& f) &
|
||||||
|
{
|
||||||
|
if(this->is_err()){return f(this->as_err());}
|
||||||
|
return ok(this->as_ok());
|
||||||
|
}
|
||||||
|
template<typename F>
|
||||||
|
detail::return_type_of_t<F, error_type const&>
|
||||||
|
or_else(F&& f) const&
|
||||||
|
{
|
||||||
|
if(this->is_err()){return f(this->as_err());}
|
||||||
|
return ok(this->as_ok());
|
||||||
|
}
|
||||||
|
template<typename F>
|
||||||
|
detail::return_type_of_t<F, error_type&&>
|
||||||
|
or_else(F&& f) &&
|
||||||
|
{
|
||||||
|
if(this->is_err()){return f(std::move(this->as_err()));}
|
||||||
|
return ok(std::move(this->as_ok()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if *this is error, returns *this. otherwise, returns other.
|
||||||
|
result and_other(const result& other) const&
|
||||||
|
{
|
||||||
|
return this->is_err() ? *this : other;
|
||||||
|
}
|
||||||
|
result and_other(result&& other) &&
|
||||||
|
{
|
||||||
|
return this->is_err() ? std::move(*this) : std::move(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if *this is okay, returns *this. otherwise, returns other.
|
||||||
|
result or_other(const result& other) const&
|
||||||
|
{
|
||||||
|
return this->is_ok() ? *this : other;
|
||||||
|
}
|
||||||
|
result or_other(result&& other) &&
|
||||||
|
{
|
||||||
|
return this->is_ok() ? std::move(*this) : std::move(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(result<T, E>& other)
|
||||||
|
{
|
||||||
|
result<T, E> tmp(std::move(*this));
|
||||||
|
*this = std::move(other);
|
||||||
|
other = std::move(tmp);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static std::string format_error(std::exception const& excpt)
|
||||||
|
{
|
||||||
|
return std::string(excpt.what());
|
||||||
|
}
|
||||||
|
template<typename U, typename std::enable_if<!std::is_base_of<
|
||||||
|
std::exception, U>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
static std::string format_error(U const& others)
|
||||||
|
{
|
||||||
|
std::ostringstream oss; oss << others;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup() noexcept
|
||||||
|
{
|
||||||
|
if(this->is_ok_) {this->succ.~success_type();}
|
||||||
|
else {this->fail.~failure_type();}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool is_ok_;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
success_type succ;
|
||||||
|
failure_type fail;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename E>
|
||||||
|
void swap(result<T, E>& lhs, result<T, E>& rhs)
|
||||||
|
{
|
||||||
|
lhs.swap(rhs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this might be confusing because it eagerly evaluated, while in the other
|
||||||
|
// cases operator && and || are short-circuited.
|
||||||
|
//
|
||||||
|
// template<typename T, typename E>
|
||||||
|
// inline result<T, E>
|
||||||
|
// operator&&(const result<T, E>& lhs, const result<T, E>& rhs) noexcept
|
||||||
|
// {
|
||||||
|
// return lhs.is_ok() ? rhs : lhs;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// template<typename T, typename E>
|
||||||
|
// inline result<T, E>
|
||||||
|
// operator||(const result<T, E>& lhs, const result<T, E>& rhs) noexcept
|
||||||
|
// {
|
||||||
|
// return lhs.is_ok() ? lhs : rhs;
|
||||||
|
// }
|
||||||
|
|
||||||
|
} // toml11
|
||||||
|
#endif// TOML11_RESULT_H
|
||||||
527
toml/serializer.hpp
Normal file
527
toml/serializer.hpp
Normal file
@@ -0,0 +1,527 @@
|
|||||||
|
// 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(value_t::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(value_t::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(value_t::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(value_t::Array)) {return false;}
|
||||||
|
|
||||||
|
const auto& a = v.cast<value_t::Array>();
|
||||||
|
return !a.empty() && a.front().is(value_t::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
|
||||||
44
toml/storage.hpp
Normal file
44
toml/storage.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright Toru Niina 2017.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_STORAGE_HPP
|
||||||
|
#define TOML11_STORAGE_HPP
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// this contains pointer and deep-copy the content if copied.
|
||||||
|
// to avoid recursive pointer.
|
||||||
|
template<typename T>
|
||||||
|
struct storage
|
||||||
|
{
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
|
storage(value_type const& v): ptr(toml::make_unique<T>(v)) {}
|
||||||
|
storage(value_type&& v): ptr(toml::make_unique<T>(std::move(v))) {}
|
||||||
|
~storage() = default;
|
||||||
|
|
||||||
|
storage(const storage& rhs): ptr(toml::make_unique<T>(*rhs.ptr)) {}
|
||||||
|
storage& operator=(const storage& rhs)
|
||||||
|
{
|
||||||
|
this->ptr = toml::make_unique<T>(*rhs.ptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
storage(storage&&) = default;
|
||||||
|
storage& operator=(storage&&) = default;
|
||||||
|
|
||||||
|
bool is_ok() const noexcept {return static_cast<bool>(ptr);}
|
||||||
|
|
||||||
|
value_type& value() & noexcept {return *ptr;}
|
||||||
|
value_type const& value() const& noexcept {return *ptr;}
|
||||||
|
value_type&& value() && noexcept {return std::move(*ptr);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<value_type> ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // toml
|
||||||
|
#endif// TOML11_STORAGE_HPP
|
||||||
133
toml/string.hpp
Normal file
133
toml/string.hpp
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
// Copyright Toru Niina 2017.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_STRING_HPP
|
||||||
|
#define TOML11_STRING_HPP
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class string_t : std::uint8_t
|
||||||
|
{
|
||||||
|
basic = 0,
|
||||||
|
literal = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct string
|
||||||
|
{
|
||||||
|
string() = default;
|
||||||
|
~string() = default;
|
||||||
|
string(const string& s) = default;
|
||||||
|
string(string&& s) = default;
|
||||||
|
string& operator=(const string& s) = default;
|
||||||
|
string& operator=(string&& s) = default;
|
||||||
|
|
||||||
|
string(const std::string& s): kind(string_t::basic), str(s){}
|
||||||
|
string(const std::string& s, string_t k): kind(k), str(s){}
|
||||||
|
string(const char* s): kind(string_t::basic), str(s){}
|
||||||
|
string(const char* s, string_t k): kind(k), str(s){}
|
||||||
|
|
||||||
|
string(std::string&& s): kind(string_t::basic), str(std::move(s)){}
|
||||||
|
string(std::string&& s, string_t k): kind(k), str(std::move(s)){}
|
||||||
|
|
||||||
|
string& operator=(const std::string& s)
|
||||||
|
{kind = string_t::basic; str = s; return *this;}
|
||||||
|
string& operator=(std::string&& s)
|
||||||
|
{kind = string_t::basic; str = std::move(s); return *this;}
|
||||||
|
|
||||||
|
operator std::string& () & noexcept {return str;}
|
||||||
|
operator std::string const& () const& noexcept {return str;}
|
||||||
|
operator std::string&& () && noexcept {return std::move(str);}
|
||||||
|
|
||||||
|
string_t kind;
|
||||||
|
std::string str;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const string& lhs, const string& rhs)
|
||||||
|
{
|
||||||
|
return lhs.kind == rhs.kind && lhs.str == rhs.str;
|
||||||
|
}
|
||||||
|
inline bool operator!=(const string& lhs, const string& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
inline bool operator<(const string& lhs, const string& rhs)
|
||||||
|
{
|
||||||
|
return (lhs.kind == rhs.kind) ? (lhs.str < rhs.str) : (lhs.kind < rhs.kind);
|
||||||
|
}
|
||||||
|
inline bool operator>(const string& lhs, const string& rhs)
|
||||||
|
{
|
||||||
|
return rhs < lhs;
|
||||||
|
}
|
||||||
|
inline bool operator<=(const string& lhs, const string& rhs)
|
||||||
|
{
|
||||||
|
return !(rhs < lhs);
|
||||||
|
}
|
||||||
|
inline bool operator>=(const string& lhs, const string& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
operator==(const string& lhs, const std::string& rhs) {return lhs.str == rhs;}
|
||||||
|
inline bool
|
||||||
|
operator!=(const string& lhs, const std::string& rhs) {return lhs.str != rhs;}
|
||||||
|
inline bool
|
||||||
|
operator< (const string& lhs, const std::string& rhs) {return lhs.str < rhs;}
|
||||||
|
inline bool
|
||||||
|
operator> (const string& lhs, const std::string& rhs) {return lhs.str > rhs;}
|
||||||
|
inline bool
|
||||||
|
operator<=(const string& lhs, const std::string& rhs) {return lhs.str <= rhs;}
|
||||||
|
inline bool
|
||||||
|
operator>=(const string& lhs, const std::string& rhs) {return lhs.str >= rhs;}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
operator==(const std::string& lhs, const string& rhs) {return lhs == rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator!=(const std::string& lhs, const string& rhs) {return lhs != rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator< (const std::string& lhs, const string& rhs) {return lhs < rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator> (const std::string& lhs, const string& rhs) {return lhs > rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator<=(const std::string& lhs, const string& rhs) {return lhs <= rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator>=(const std::string& lhs, const string& rhs) {return lhs >= rhs.str;}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
operator==(const string& lhs, const char* rhs) {return lhs.str == std::string(rhs);}
|
||||||
|
inline bool
|
||||||
|
operator!=(const string& lhs, const char* rhs) {return lhs.str != std::string(rhs);}
|
||||||
|
inline bool
|
||||||
|
operator< (const string& lhs, const char* rhs) {return lhs.str < std::string(rhs);}
|
||||||
|
inline bool
|
||||||
|
operator> (const string& lhs, const char* rhs) {return lhs.str > std::string(rhs);}
|
||||||
|
inline bool
|
||||||
|
operator<=(const string& lhs, const char* rhs) {return lhs.str <= std::string(rhs);}
|
||||||
|
inline bool
|
||||||
|
operator>=(const string& lhs, const char* rhs) {return lhs.str >= std::string(rhs);}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
operator==(const char* lhs, const string& rhs) {return std::string(lhs) == rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator!=(const char* lhs, const string& rhs) {return std::string(lhs) != rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator< (const char* lhs, const string& rhs) {return std::string(lhs) < rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator> (const char* lhs, const string& rhs) {return std::string(lhs) > rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator<=(const char* lhs, const string& rhs) {return std::string(lhs) <= rhs.str;}
|
||||||
|
inline bool
|
||||||
|
operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.str;}
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, const string& str)
|
||||||
|
{
|
||||||
|
os << str.str;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // toml
|
||||||
|
#endif// TOML11_STRING_H
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#ifndef TOML11_TO_TOML
|
|
||||||
#define TOML11_TO_TOML
|
|
||||||
#include "value.hpp"
|
|
||||||
|
|
||||||
namespace toml
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
|
||||||
typename std::enable_if<(vT != toml::value_t::Unknown &&
|
|
||||||
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
|
|
||||||
inline toml::value to_toml(T&& x)
|
|
||||||
{
|
|
||||||
return toml::value(std::forward<T>(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
|
||||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
|
||||||
(!toml::detail::is_map<T>::value) &&
|
|
||||||
toml::detail::is_container<T>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
toml::value to_toml(T&& x)
|
|
||||||
{
|
|
||||||
toml::Array tmp; tmp.reserve(std::distance(std::begin(x), std::end(x)));
|
|
||||||
for(auto iter = std::begin(x); iter != std::end(x); ++iter)
|
|
||||||
tmp.emplace_back(*iter);
|
|
||||||
return toml::value(std::move(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
|
||||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
|
||||||
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
|
|
||||||
toml::value to_toml(T&& x)
|
|
||||||
{
|
|
||||||
toml::Table tmp;
|
|
||||||
for(auto iter = std::begin(x); iter != std::end(x); ++iter)
|
|
||||||
tmp.emplace(iter->first, to_toml(iter->second));
|
|
||||||
return toml::value(std::move(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline toml::value to_toml(std::initializer_list<T> init)
|
|
||||||
{
|
|
||||||
return toml::value(std::move(init));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline toml::value
|
|
||||||
to_toml(std::initializer_list<std::pair<std::string, toml::value>> init)
|
|
||||||
{
|
|
||||||
return toml::value(std::move(init));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // toml
|
|
||||||
#endif // TOML11_TO_TOML
|
|
||||||
133
toml/traits.hpp
133
toml/traits.hpp
@@ -1,15 +1,26 @@
|
|||||||
#ifndef TOML11_TRAITS
|
// Copyright Toru Niina 2017.
|
||||||
#define TOML11_TRAITS
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_TRAITS_HPP
|
||||||
|
#define TOML11_TRAITS_HPP
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <chrono>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class value; // forward decl
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using unwrap_t = typename std::decay<T>::type;
|
using unwrap_t = typename std::decay<T>::type;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// check whether type T is a kind of container/map class
|
||||||
|
|
||||||
struct has_iterator_impl
|
struct has_iterator_impl
|
||||||
{
|
{
|
||||||
template<typename T> static std::true_type check(typename T::iterator*);
|
template<typename T> static std::true_type check(typename T::iterator*);
|
||||||
@@ -37,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
|
||||||
@@ -54,18 +81,108 @@ 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
|
||||||
|
|
||||||
template<typename T>
|
// ---------------------------------------------------------------------------
|
||||||
struct is_container : std::integral_constant<bool,
|
// C++17 and/or/not
|
||||||
has_iterator<T>::value && has_value_type<T>::value>{};
|
|
||||||
|
template<typename ...> struct conjunction : std::true_type{};
|
||||||
|
template<typename T> struct conjunction<T> : T{};
|
||||||
|
template<typename T, typename ... Ts>
|
||||||
|
struct conjunction<T, Ts...> :
|
||||||
|
std::conditional<static_cast<bool>(T::value), conjunction<Ts...>, T>::type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename ...> struct disjunction : std::false_type{};
|
||||||
|
template<typename T> struct disjunction<T> : T {};
|
||||||
|
template<typename T, typename ... Ts>
|
||||||
|
struct disjunction<T, Ts...> :
|
||||||
|
std::conditional<static_cast<bool>(T::value), T, disjunction<Ts...>>::type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_map : std::integral_constant<bool,
|
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
|
||||||
has_iterator<T>::value && has_key_type<T>::value &&
|
|
||||||
has_mapped_type<T>::value>{};
|
// ---------------------------------------------------------------------------
|
||||||
|
// normal type checker
|
||||||
|
|
||||||
|
template<typename T> struct is_std_pair : std::false_type{};
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
struct is_std_pair<std::pair<T1, T2>> : std::true_type{};
|
||||||
|
|
||||||
|
template<typename T> struct is_std_tuple : std::false_type{};
|
||||||
|
template<typename ... Ts>
|
||||||
|
struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};
|
||||||
|
|
||||||
|
template<typename T> struct is_chrono_duration: std::false_type{};
|
||||||
|
template<typename Rep, typename Period>
|
||||||
|
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// C++14 index_sequence
|
||||||
|
|
||||||
|
template<std::size_t ... Ns> struct index_sequence{};
|
||||||
|
|
||||||
|
template<typename IS, std::size_t N> struct push_back_index_sequence{};
|
||||||
|
template<std::size_t N, std::size_t ... Ns>
|
||||||
|
struct push_back_index_sequence<index_sequence<Ns...>, N>
|
||||||
|
{
|
||||||
|
typedef index_sequence<Ns..., N> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
struct index_sequence_maker
|
||||||
|
{
|
||||||
|
typedef typename push_back_index_sequence<
|
||||||
|
typename index_sequence_maker<N-1>::type, N>::type type;
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct index_sequence_maker<0>
|
||||||
|
{
|
||||||
|
typedef index_sequence<0> type;
|
||||||
|
};
|
||||||
|
template<std::size_t N>
|
||||||
|
using make_index_sequence = typename index_sequence_maker<N-1>::type;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// return_type_of_t
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
|
||||||
|
template<typename F, typename ... Args>
|
||||||
|
using return_type_of_t = std::invoke_result_t<F, Args...>;
|
||||||
|
|
||||||
|
#else
|
||||||
|
// result_of is deprecated after C++17
|
||||||
|
template<typename F, typename ... Args>
|
||||||
|
using return_type_of_t = typename std::result_of<F(Args...)>::type;
|
||||||
|
|
||||||
|
#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
|
||||||
|
|||||||
186
toml/types.hpp
Normal file
186
toml/types.hpp
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
// Copyright Toru Niina 2017.
|
||||||
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_TYPES_HPP
|
||||||
|
#define TOML11_TYPES_HPP
|
||||||
|
#include "datetime.hpp"
|
||||||
|
#include "string.hpp"
|
||||||
|
#include "traits.hpp"
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace toml
|
||||||
|
{
|
||||||
|
|
||||||
|
using character = char;
|
||||||
|
|
||||||
|
class value;
|
||||||
|
using key = std::string;
|
||||||
|
|
||||||
|
using Boolean = bool;
|
||||||
|
using Integer = std::int64_t;
|
||||||
|
using Float = double;
|
||||||
|
using String = ::toml::string;
|
||||||
|
using Datetime = offset_datetime;
|
||||||
|
using OffsetDatetime = offset_datetime;
|
||||||
|
using LocalDatetime = local_datetime;
|
||||||
|
using LocalDate = local_date;
|
||||||
|
using LocalTime = local_time;
|
||||||
|
using Array = std::vector<value>;
|
||||||
|
using Table = std::unordered_map<key, value>;
|
||||||
|
|
||||||
|
// alias for snake_case, consistency with STL/Boost, toml::key, toml::value
|
||||||
|
using boolean = Boolean;
|
||||||
|
using integer = Integer;
|
||||||
|
using floating = Float; // XXX `float` is keyword. we can't use it here
|
||||||
|
using array = Array;
|
||||||
|
using table = Table;
|
||||||
|
|
||||||
|
enum class value_t : std::uint8_t
|
||||||
|
{
|
||||||
|
Empty = 0,
|
||||||
|
Boolean = 1,
|
||||||
|
Integer = 2,
|
||||||
|
Float = 3,
|
||||||
|
String = 4,
|
||||||
|
OffsetDatetime = 5,
|
||||||
|
LocalDatetime = 6,
|
||||||
|
LocalDate = 7,
|
||||||
|
LocalTime = 8,
|
||||||
|
Array = 9,
|
||||||
|
Table = 10,
|
||||||
|
Unknown = 255,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename charT, typename traits>
|
||||||
|
inline std::basic_ostream<charT, traits>&
|
||||||
|
operator<<(std::basic_ostream<charT, traits>& os, value_t t)
|
||||||
|
{
|
||||||
|
switch(t)
|
||||||
|
{
|
||||||
|
case toml::value_t::Boolean : os << "boolean"; return os;
|
||||||
|
case toml::value_t::Integer : os << "integer"; return os;
|
||||||
|
case toml::value_t::Float : os << "float"; return os;
|
||||||
|
case toml::value_t::String : os << "string"; return os;
|
||||||
|
case toml::value_t::OffsetDatetime: os << "offset_datetime"; return os;
|
||||||
|
case toml::value_t::LocalDatetime : os << "local_datetime"; return os;
|
||||||
|
case toml::value_t::LocalDate : os << "local_date"; return os;
|
||||||
|
case toml::value_t::LocalTime : os << "local_time"; return os;
|
||||||
|
case toml::value_t::Array : os << "array"; return os;
|
||||||
|
case toml::value_t::Table : os << "table"; return os;
|
||||||
|
case toml::value_t::Empty : os << "empty"; return os;
|
||||||
|
case toml::value_t::Unknown : os << "unknown"; return os;
|
||||||
|
default : os << "nothing"; return os;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename charT = character, typename traits = std::char_traits<charT>,
|
||||||
|
typename alloc = std::allocator<charT>>
|
||||||
|
inline std::basic_string<charT, traits, alloc> stringize(value_t t)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << t;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr inline value_t check_type()
|
||||||
|
{
|
||||||
|
using type = typename std::remove_cv<
|
||||||
|
typename std::remove_reference<T>::type
|
||||||
|
>::type;
|
||||||
|
return std::is_same<type, toml::boolean>::value ? value_t::Boolean :
|
||||||
|
std::is_integral<type>::value ? value_t::Integer :
|
||||||
|
std::is_floating_point<type>::value ? value_t::Float :
|
||||||
|
std::is_same<type, std::string>::value ? value_t::String :
|
||||||
|
std::is_same<type, toml::string>::value ? value_t::String :
|
||||||
|
std::is_same<type, toml::local_date>::value ? value_t::LocalDate :
|
||||||
|
std::is_same<type, toml::local_time>::value ? value_t::LocalTime :
|
||||||
|
is_chrono_duration<type>::value ? value_t::LocalTime :
|
||||||
|
std::is_same<type, toml::local_datetime>::value ? value_t::LocalDatetime :
|
||||||
|
std::is_same<type, toml::offset_datetime>::value ? value_t::OffsetDatetime :
|
||||||
|
std::is_same<type, std::chrono::system_clock::time_point>::value ? value_t::OffsetDatetime :
|
||||||
|
std::is_convertible<type, toml::array>::value ? value_t::Array :
|
||||||
|
std::is_convertible<type, toml::table>::value ? value_t::Table :
|
||||||
|
value_t::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool is_valid(value_t vt)
|
||||||
|
{
|
||||||
|
return vt != value_t::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<value_t t> struct toml_default_type;
|
||||||
|
template<> struct toml_default_type<value_t::Boolean > {typedef boolean type;};
|
||||||
|
template<> struct toml_default_type<value_t::Integer > {typedef integer type;};
|
||||||
|
template<> struct toml_default_type<value_t::Float > {typedef floating type;};
|
||||||
|
template<> struct toml_default_type<value_t::String > {typedef string type;};
|
||||||
|
template<> struct toml_default_type<value_t::OffsetDatetime>{typedef offset_datetime type;};
|
||||||
|
template<> struct toml_default_type<value_t::LocalDatetime> {typedef local_datetime type;};
|
||||||
|
template<> struct toml_default_type<value_t::LocalDate> {typedef local_date type;};
|
||||||
|
template<> struct toml_default_type<value_t::LocalTime> {typedef local_time type;};
|
||||||
|
template<> struct toml_default_type<value_t::Array > {typedef array type;};
|
||||||
|
template<> struct toml_default_type<value_t::Table > {typedef table type;};
|
||||||
|
template<> struct toml_default_type<value_t::Empty > {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<> 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<Float >{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<OffsetDatetime>{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<LocalDate >{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<Array >{static constexpr value_t value = value_t::Array ;};
|
||||||
|
template<> struct toml_value_t<Table >{static constexpr value_t value = value_t::Table ;};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_exact_toml_type : disjunction<
|
||||||
|
std::is_same<T, Boolean >,
|
||||||
|
std::is_same<T, Integer >,
|
||||||
|
std::is_same<T, Float >,
|
||||||
|
std::is_same<T, String >,
|
||||||
|
std::is_same<T, offset_datetime>,
|
||||||
|
std::is_same<T, local_datetime>,
|
||||||
|
std::is_same<T, local_date>,
|
||||||
|
std::is_same<T, local_time>,
|
||||||
|
std::is_same<T, Array >,
|
||||||
|
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 const&> : is_exact_toml_type<T>{};
|
||||||
|
template<typename T> struct is_exact_toml_type<T volatile&> : is_exact_toml_type<T>{};
|
||||||
|
template<typename T> struct is_exact_toml_type<T const volatile&>: is_exact_toml_type<T>{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_map : conjunction<
|
||||||
|
has_iterator<T>,
|
||||||
|
has_value_type<T>,
|
||||||
|
has_key_type<T>,
|
||||||
|
has_mapped_type<T>
|
||||||
|
>{};
|
||||||
|
template<typename T> struct is_map<T&> : is_map<T>{};
|
||||||
|
template<typename T> struct is_map<T const&> : is_map<T>{};
|
||||||
|
template<typename T> struct is_map<T volatile&> : is_map<T>{};
|
||||||
|
template<typename T> struct is_map<T const volatile&> : is_map<T>{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_container : conjunction<
|
||||||
|
negation<is_map<T>>,
|
||||||
|
negation<std::is_same<T, std::string>>,
|
||||||
|
has_iterator<T>,
|
||||||
|
has_value_type<T>
|
||||||
|
>{};
|
||||||
|
template<typename T> struct is_container<T&> : is_container<T>{};
|
||||||
|
template<typename T> struct is_container<T const&> : is_container<T>{};
|
||||||
|
template<typename T> struct is_container<T volatile&> : is_container<T>{};
|
||||||
|
template<typename T> struct is_container<T const volatile&> : is_container<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // toml
|
||||||
|
#endif// TOML11_TYPES_H
|
||||||
@@ -1,8 +1,21 @@
|
|||||||
#ifndef TOML11_UTILITY
|
// Copyright Toru Niina 2017.
|
||||||
#define TOML11_UTILITY
|
// Distributed under the MIT License.
|
||||||
|
#ifndef TOML11_UTILITY_HPP
|
||||||
|
#define TOML11_UTILITY_HPP
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#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
|
||||||
{
|
{
|
||||||
@@ -26,17 +39,50 @@ 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
|
||||||
|
|
||||||
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
|
||||||
|
{
|
||||||
|
inline std::string concat_to_string_impl(std::ostringstream& oss)
|
||||||
|
{
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
template<typename T, typename ... Ts>
|
||||||
|
std::string concat_to_string_impl(std::ostringstream& oss, T&& head, Ts&& ... tail)
|
||||||
|
{
|
||||||
|
oss << std::forward<T>(head);
|
||||||
|
return concat_to_string_impl(oss, std::forward<Ts>(tail) ... );
|
||||||
|
}
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
template<typename ... Ts>
|
||||||
|
std::string concat_to_string(Ts&& ... args)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::boolalpha << std::fixed;
|
||||||
|
return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
T from_string(const std::string& str, U&& opt)
|
||||||
|
{
|
||||||
|
T v(std::forward<U>(opt));
|
||||||
|
std::istringstream iss(str);
|
||||||
|
iss >> v;
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
}// toml
|
}// toml
|
||||||
|
|||||||
1354
toml/value.hpp
1354
toml/value.hpp
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user