Compare commits

..

191 Commits

Author SHA1 Message Date
ToruNiina
6a251f582e refactor: remove needless code snippet 2019-06-22 17:52:01 +09:00
ToruNiina
74ef494797 feat: remove unused trait types 2019-06-22 17:35:40 +09:00
ToruNiina
3a5f8a4b88 test: rename test source file 2019-06-22 17:23:51 +09:00
ToruNiina
4d2b24b647 test: add test_find_or 2019-06-22 16:58:45 +09:00
ToruNiina
3fcb6bb20d test: fix test module name 2019-06-22 16:58:21 +09:00
ToruNiina
1e8af710a0 test: add test for get_or 2019-06-22 16:39:01 +09:00
ToruNiina
0ca8eeeb09 test: add missing include files 2019-06-21 17:11:21 +09:00
ToruNiina
a343ffd2a1 doc: update README 2019-06-21 17:02:30 +09:00
ToruNiina
b79797d2c7 refactor: replace BOOST_CHECK_EQUAL by BOOST_TEST 2019-06-21 16:01:14 +09:00
ToruNiina
90918b6d76 test: add basic_value type to serialization tests 2019-06-21 16:01:08 +09:00
ToruNiina
dd9b04ae3b fix: fix test case name 2019-06-21 16:01:04 +09:00
ToruNiina
4032b438c0 fix: time offset may change while conversion 2019-06-21 16:00:48 +09:00
ToruNiina
7b37d876ae refactor: update Boost.Test v2 to v3 2019-06-21 14:50:17 +09:00
ToruNiina
713b42e589 refactor: use CHECK_THROW macro to check it throws 2019-06-21 14:47:27 +09:00
ToruNiina
1694f74510 chore: update boost test library usage (v2->v3) 2019-06-21 14:43:13 +09:00
ToruNiina
9f69ffa993 fix: add unsigned symbol to integer literals 2019-06-21 14:42:44 +09:00
ToruNiina
0cee58b0b1 Merge branch 'v3' of github.com:ToruNiina/toml11 into v3 2019-06-21 14:31:52 +09:00
ToruNiina
ab1ef63da6 doc: add value ctor with comments to README 2019-06-21 14:31:28 +09:00
ToruNiina
e8d535e485 test: add tests for constructors with comments 2019-06-21 14:26:49 +09:00
ToruNiina
d4afed5bbb feat: construct value with a list of comments 2019-06-21 14:26:05 +09:00
ToruNiina
3ef8bddb6d doc: update README 2019-06-21 13:23:15 +09:00
ToruNiina
a68543a895 fix: detect comment in stricter way 2019-06-21 13:10:02 +09:00
ToruNiina
ec839bbd75 chore: add -Wextra when compiling tests 2019-06-21 00:29:45 +09:00
ToruNiina
ecf55f86d6 refactor: add explicit type conversion 2019-06-21 00:25:57 +09:00
ToruNiina
3b71f80652 refactor: streamsize is a signed integer 2019-06-21 00:00:37 +09:00
ToruNiina
be2d2aec52 refactor: explicitly convert difference_t to size_t 2019-06-20 23:59:16 +09:00
ToruNiina
be04bf1302 refactor: convert file size to size_t 2019-06-20 23:58:35 +09:00
ToruNiina
427706d671 fix: explicitly add float conversion 2019-06-20 23:58:15 +09:00
ToruNiina
71ff54e76c fix: rearrange internal int types in datetimes 2019-06-20 23:58:08 +09:00
ToruNiina
8208bbf236 fix: check and convert value manually
I totally have no idea when std::count returns a negative value, but the
result type of `std::count` is a differnce_type. So when it is added
with size_t value, implicit sign conversion happens. This changes check
this kind of (almost trivial but required) checking.
2019-06-20 22:27:16 +09:00
ToruNiina
f689d26294 refactor: add conversion function to utf8 encoder 2019-06-20 22:25:40 +09:00
ToruNiina
9e6d8e76d0 fix: replace null deref by terminate for safety
Since empty_iterator never points anything, so it always points null
(it returns nullptr by operator->). but dereferencing null causes UB.
Just calling std::terminate is of course better.
2019-06-20 20:56:49 +09:00
ToruNiina
0e2e4a26be ci: Revert "ci: use libstdc++ when compiling"
Ok, it already worked without this.
This reverts commit 092db50700.
2019-06-20 20:48:17 +09:00
ToruNiina
092db50700 ci: use libstdc++ when compiling
because some of the earlier versions of libc++ does not conform c++11
2019-06-20 20:43:57 +09:00
ToruNiina
295e9bb795 ci: try to update system library 2019-06-20 20:24:12 +09:00
ToruNiina
dd2238e1ad ci: change apt source on travis
clang 3.7 trusty version seems to be restricted. I don't know why, but
precise version seems to be working.
2019-06-20 20:21:06 +09:00
ToruNiina
5dfa88a1b3 ci: rename package to be installed 2019-06-20 20:13:16 +09:00
ToruNiina
37b4442d7f ci: upgrade boost on Travis Linux 2019-06-20 20:00:56 +09:00
ToruNiina
48aa0a4c67 ci: update boost version on appveyor 2019-06-20 19:53:27 +09:00
ToruNiina
86a1f7ad75 fix: add missing include files 2019-06-20 16:23:51 +09:00
ToruNiina
99c10dd6bc fix: enable to deduce what basic_value to be used 2019-06-20 16:21:01 +09:00
ToruNiina
7d087ef2a8 doc: update README 2019-06-20 15:22:20 +09:00
ToruNiina
a0d74a5542 doc: add info about breaking changes to README 2019-06-20 14:58:18 +09:00
ToruNiina
c3922c0d51 test: move some test_cases across test files 2019-06-20 14:43:31 +09:00
ToruNiina
5e5a757208 fix: conversion between different basic_value s 2019-06-20 14:35:38 +09:00
ToruNiina
f178379c07 test: add test_find 2019-06-20 14:34:42 +09:00
ToruNiina
321db42b1c Merge branch 'master' into v3 2019-06-19 23:44:09 +09:00
ToruNiina
1bf9e42835 chore: update version 2019-06-19 21:12:05 +09:00
ToruNiina
3379ed82ec refactor: remove meaningless meta conditions 2019-06-19 20:06:06 +09:00
ToruNiina
9663a6bbdb Merge branch 'master' into v3 2019-06-19 19:53:08 +09:00
ToruNiina
4a2c823d56 fix: comparison between values that has a table 2019-06-19 19:32:25 +09:00
ToruNiina
9a47c2a15a Merge branch 'v3' of gitlab.com:ToruNiina/toml11 into v3 2019-06-19 19:03:47 +09:00
ToruNiina
3311d00845 Merge branch 'v3' of gitlab.com:ToruNiina/toml11 into v3 2019-06-19 19:05:22 +09:00
ToruNiina
24c28c7f4f fix: correct some SFINAE expressions 2019-06-19 18:59:12 +09:00
ToruNiina
cab3144507 style: format CMakelists.txt 2019-06-19 16:53:45 +09:00
ToruNiina
7e5859ba73 Merge branch 'master' into v3 2019-06-19 15:36:27 +09:00
ToruNiina
dee32e7d5e style: make hint messages clearer 2019-06-19 12:58:34 +09:00
ToruNiina
53a185e7a9 fix: revert misjudgement as a bug
Probably I'm too tired.

This reverts commit adcd75e017.
2019-06-18 21:41:30 +09:00
ToruNiina
fd980a8c5d 🔀 Merge branch 'guess-type-error' 2019-06-18 21:29:45 +09:00
ToruNiina
73ac43d70c doc: add contributor 2019-06-18 21:28:50 +09:00
ToruNiina
adcd75e017 fix: correctly initialize offset 2019-06-18 21:27:16 +09:00
ToruNiina
3613580bb3 doc: update README 2019-06-18 21:26:17 +09:00
ToruNiina
d9f9df61a2 fix: fix links in README 2019-06-18 01:39:36 +09:00
ToruNiina
32d5c9e924 fix: serialize array correctly 2019-06-18 01:27:52 +09:00
ToruNiina
262f9c5fcc fix: avoid duplicating comment: array/table elems 2019-06-18 01:26:40 +09:00
ToruNiina
86e55c3bf7 test: check serialization keeps comments 2019-06-18 01:26:16 +09:00
ToruNiina
159283fdad test: check preserve_comment keep it read 2019-06-18 01:25:43 +09:00
ToruNiina
fb5834caab refactor: exchange order of test section 2019-06-18 00:45:30 +09:00
ToruNiina
ca084abe90 feat: consider the first comments as a file comment 2019-06-18 00:44:49 +09:00
ToruNiina
7b1a788e2d feat: enable to convert vector<string> to comments 2019-06-18 00:43:25 +09:00
ToruNiina
228487eafd test: fix typos in tests 2019-06-17 23:46:42 +09:00
ToruNiina
f744a792e2 fix: constructor with array-like types 2019-06-17 23:45:43 +09:00
ToruNiina
bf2dc76d5e test: add test for templatized conversions 2019-06-17 23:21:18 +09:00
ToruNiina
4d267cadf4 doc: add templatized conversion to README 2019-06-17 23:12:46 +09:00
ToruNiina
bc68a9d9ee refactor: remove needless include file 2019-06-17 23:07:14 +09:00
ToruNiina
4008c24e84 test: add test for init-list-map to value conversion 2019-06-17 22:50:38 +09:00
ToruNiina
c2b0de623f feat: enable to convert map-like to toml::value 2019-06-17 22:50:14 +09:00
ToruNiina
af11d56e79 fix: correctly move value from find_or to get_or 2019-06-17 22:40:52 +09:00
ToruNiina
5cb7c961aa fix: update README 2019-06-17 22:26:41 +09:00
ToruNiina
bf4eae0b76 test: drop test for find_or(table) 2019-06-17 22:14:26 +09:00
ToruNiina
6399d44e3b fix: consider comments while serialization 2019-06-17 22:13:58 +09:00
ToruNiina
d10c0725fd fix: consider closing bracket when collect comments
table = {key = "value"} # comment.
a value named "table" ({key = "value"}) has the above comment.
but a value named "key" ("value") does not have any comment.
2019-06-17 22:12:20 +09:00
ToruNiina
7eac3a3028 feat: support serialization of basic_value 2019-06-17 20:34:42 +09:00
ToruNiina
57b5545ba2 fix: add _type suffix to value::xxx_type 2019-06-17 20:34:13 +09:00
ToruNiina
f36b39c04f fix: consider comments while comparing values 2019-06-17 20:33:57 +09:00
Toru Niina
569341a514 Merge pull request #69 from KerstinKeller/cmake_install
Allow to install toml11 library with CMake.
2019-06-17 18:03:00 +09:00
KerstinKeller
0357d8fb57 Add newline to end of CMake files. 2019-06-17 10:04:39 +02:00
ToruNiina
00d40140ac doc: add an example of error message to README 2019-06-17 12:59:29 +09:00
ToruNiina
1bfe8f1f54 Merge branch 'master' into guess-type-error 2019-06-17 12:48:36 +09:00
ToruNiina
b3300fad2a fix: move element of map in toml::find(val&&) 2019-06-17 12:13:59 +09:00
ToruNiina
94bcf0aae9 Merge branch remote into v3 2019-06-17 12:10:45 +09:00
ToruNiina
bc143263cd Merge branch 'revert-recursive-find' 2019-06-17 11:54:52 +09:00
ToruNiina
0ef232a1e0 feat: 💥 remove toml::find_or for toml::table 2019-06-17 01:26:05 +09:00
ToruNiina
0604cf813a feat: 💥 remove toml::find for tables 2019-06-17 01:24:32 +09:00
ToruNiina
10f410a02c doc: add some notes and comments to README 2019-06-17 00:48:06 +09:00
ToruNiina
12ef0f6287 doc: add containers and comments to README 2019-06-17 00:29:43 +09:00
ToruNiina
d9ad0e4b92 doc: add source_location to README 2019-06-16 23:44:54 +09:00
ToruNiina
1b19d5f1eb doc: update README 2019-06-16 21:44:59 +09:00
ToruNiina
fd7da05798 doc: update README 2019-06-16 20:31:08 +09:00
ToruNiina
cbaaaaca7c revert recursive find function
I found that in a user-code (I'm also one of the users of this library),
this new feature sometimes causes an error. Some of my code won't
compile because of this change. Since toml::table is convertible to
toml::value *implicitly*, if toml::find(table, key, tablename) was
called, the overload resolution becomes ambiguous with toml::find(
value, key1, key2). But dropping support for toml::find(toml::table,
key, tablename) is a breaking change. So I concluded that now is not
the right time yet.
2019-06-16 19:55:40 +09:00
ToruNiina
cf1c9371b6 fix: correct example and positions in err msgs 2019-06-16 17:52:42 +09:00
ToruNiina
62e8d58d8d feat: guess possible format errors 2019-06-16 17:32:29 +09:00
ToruNiina
fec4e1db9a doc(WIP): add source_location to README 2019-06-15 20:34:20 +09:00
ToruNiina
8665272bab test: add test for custom basic_value type 2019-06-15 20:25:19 +09:00
ToruNiina
cc4a9c8d5d fix: consider identity conversion in SFINAE 2019-06-15 20:20:14 +09:00
ToruNiina
af19dfe032 fix: conversion between different basic_values 2019-06-15 20:19:51 +09:00
ToruNiina
64dc086878 doc(WIP): re-write README 2019-06-15 19:50:31 +09:00
ToruNiina
9acc55a7ac test: add test for discard_comment 2019-06-15 17:18:25 +09:00
ToruNiina
177022b2cb test: update tests for comment 2019-06-15 17:13:25 +09:00
ToruNiina
5726d10339 feat: save comment information in value 2019-06-15 17:13:02 +09:00
ToruNiina
a6706f7879 fix: templatize internal function for value 2019-06-15 17:12:30 +09:00
ToruNiina
558349170d fix: correct the order and remove last CR 2019-06-15 17:11:49 +09:00
ToruNiina
eb4eca86db feat: 💥 change comment interface in region 2019-06-15 16:11:05 +09:00
ToruNiina
d8a9ee4f72 🔀 Merge branch 'master' into v3 2019-06-15 15:17:08 +09:00
KerstinKeller
acbc2a73cb Allow to install tom11 library with CMake.
Add option to build tests.
2019-06-14 17:24:21 +02:00
ToruNiina
b2daf916b3 doc: add contributor to README 2019-06-11 22:45:46 +09:00
Toru Niina
e66bb3d359 Merge pull request #67 from ToruNiina/hotfix
suppress warnings on clang v7+
2019-06-10 10:54:54 +09:00
Toru Niina
cfaa94f072 Merge pull request #68 from khoitd1997/master
fix sign-compare warning
2019-06-10 10:49:49 +09:00
khoitd1997
2f4f3efbf0 fix sign-compare warning 2019-06-09 12:00:28 -07:00
ToruNiina
06ae67502a fix: move argument correctly 2019-06-09 21:05:46 +09:00
ToruNiina
6345910c3e 🔀 Merge branch 'master' into v3 2019-06-08 20:05:05 +09:00
ToruNiina
9948549b62 fix: add missing template parameters 2019-06-08 19:53:50 +09:00
ToruNiina
54d46f08c3 🔀 Merge branch 'master' into v3 2019-06-08 19:40:11 +09:00
ToruNiina
57cb806e14 Merge branch 'master' into throw-from-as-something 2019-06-08 19:23:32 +09:00
ToruNiina
d6f3654185 refactor: reduce test code by using CHECK_THROW 2019-06-08 19:23:12 +09:00
ToruNiina
8befe3f1ad test: add test for throw/nothrow versions of as_* 2019-06-08 19:20:09 +09:00
ToruNiina
2d43119ac7 doc: change README a bit 2019-06-07 21:05:33 +09:00
ToruNiina
436af12815 doc: update README 2019-06-07 19:43:01 +09:00
ToruNiina
4f4d4380f2 feat: throw from as_* if type differs 2019-06-07 19:34:04 +09:00
ToruNiina
31debcb8aa 🔀 Merge branch 'master' into recursive-find 2019-06-07 19:02:20 +09:00
ToruNiina
2afa0ff0c3 doc: add find(value, key1, key2, ...) to README 2019-06-07 19:01:46 +09:00
ToruNiina
46047c48bf doc: add note about is|as_float to README 2019-06-07 13:40:21 +09:00
ToruNiina
897aecf5d4 test: avoid deprecated functions in the test codes 2019-06-07 13:32:02 +09:00
ToruNiina
7db8388d17 fix: avoid deprecated stuff in the internal code 2019-06-07 13:27:10 +09:00
ToruNiina
62c993e096 feat: add as|is_floating and deprecate as|is_float
to make the function names consistent with snake_case_typenames
2019-06-07 00:10:12 +09:00
ToruNiina
014d882f8f feat: enable to find value by recursive search 2019-06-07 00:06:14 +09:00
ToruNiina
e781545c53 feat(WIP): diable test for comments once
because the interfaces would be changed a lot.
2019-06-06 22:34:08 +09:00
ToruNiina
a8b5fef827 feat(WIP): add workaround to make literal compiles 2019-06-06 22:32:51 +09:00
ToruNiina
7258c52334 feat: enable to edit comments through memfun 2019-06-03 22:17:10 +09:00
ToruNiina
407d9223f6 feat: 💥 is_float -> is_floating 2019-06-03 22:01:47 +09:00
ToruNiina
53efaed179 test: update interfaces of parse_* and value 2019-06-03 22:01:16 +09:00
ToruNiina
d7c5606dcf fix: update as_float -> floating 2019-06-03 21:46:48 +09:00
ToruNiina
761718b3b9 test: update retval of parse and related get/find 2019-06-03 21:44:47 +09:00
ToruNiina
ae2bafa907 fix: correct SFINAE conditions and types 2019-06-03 21:44:11 +09:00
ToruNiina
f19b3822bb feat: 💥 change as_float -> as_floating 2019-06-03 21:43:35 +09:00
ToruNiina
2cbb93d86e fix: #65 Merge branch 'hotfix' 2019-06-03 21:27:25 +09:00
ToruNiina
a19b94511b fix: add space between operator"" and _toml
In C++11, it is required.
2019-06-03 20:58:35 +09:00
ToruNiina
cf1114b47b test: update typenames from Camel to snake 2019-06-02 22:13:36 +09:00
ToruNiina
ad3c1950f2 test: use find instead of get<T>(v.at("")) 2019-06-02 22:12:52 +09:00
ToruNiina
296ba060ef test: update typename from CamelCase to snake_case 2019-06-02 22:11:37 +09:00
ToruNiina
fe8a909213 fix: correctly put references 2019-06-02 22:09:26 +09:00
ToruNiina
c313e1382c test: update test for multiple translation units 2019-06-02 22:00:56 +09:00
ToruNiina
5fe166e375 fix: update value_t::* names in serializer
Although currently serializer does not support basic_value, it compiles.
2019-06-02 21:51:37 +09:00
ToruNiina
319365f86b feat: update types in format_error 2019-06-02 21:50:27 +09:00
ToruNiina
89f0ace6ee fix: initialize comment container correctly 2019-06-02 21:50:01 +09:00
ToruNiina
2e34035e7a feat: 💥 update types and retval of parser
- change return value from toml::table to toml::value
- enable to change container types and comment policy by template
2019-06-02 21:47:57 +09:00
ToruNiina
7d34436535 test: update value_t::* names in the test code 2019-06-02 21:36:09 +09:00
ToruNiina
8456186eac fix: remove inclusion of removed file 2019-06-02 21:34:57 +09:00
ToruNiina
e094d6e85a refactor: move type alias from get to trait 2019-06-02 20:43:08 +09:00
ToruNiina
4664f91517 feat: remove unused meta-function alias 2019-06-02 20:40:44 +09:00
ToruNiina
c0b6ca762a feat: 💥 drop from_toml support 2019-06-02 19:27:03 +09:00
ToruNiina
5ef9890d0c feat: update find_or for basic_value 2019-06-02 19:22:17 +09:00
ToruNiina
bda337b51f feat: support conversion between basic_values 2019-06-02 19:09:56 +09:00
ToruNiina
6569c26e1b feat: make SFINAE condition strict 2019-06-02 19:04:32 +09:00
ToruNiina
6d17d5f60f feat: update expect for basic_value 2019-06-02 19:02:25 +09:00
ToruNiina
c00eeb18ef feat: add meta function that detects toml::basic_value 2019-06-02 19:02:01 +09:00
ToruNiina
3ce1aa31f3 feat: update get_or for basic_value 2019-06-02 18:55:02 +09:00
ToruNiina
cf28c3fb95 feat: update toml::find for basic_value 2019-06-02 18:36:49 +09:00
ToruNiina
6de494598a fix: remove unused argument to suppress warnings 2019-06-02 18:32:47 +09:00
ToruNiina
b06ae03deb feat: update toml::get<T> for basic_value 2019-06-02 17:53:08 +09:00
ToruNiina
725d915ba9 feat(WIP): update toml::get 2019-06-02 17:31:49 +09:00
ToruNiina
e1556183d1 refactor: remove unused include files 2019-06-02 17:12:01 +09:00
ToruNiina
9676499ab5 refactor: move file inclusion to correct position 2019-06-02 15:29:34 +09:00
ToruNiina
5792411d5e feat: add default template argument to basic_value 2019-06-02 15:15:43 +09:00
ToruNiina
44184026f9 feat: enable to convert different basic_values 2019-06-02 00:13:12 +09:00
ToruNiina
898423166f feat: enable to convert preserve/discard comments 2019-06-02 00:02:31 +09:00
ToruNiina
f9b5166c09 refactor: move default value types to value.hpp 2019-06-01 23:58:17 +09:00
ToruNiina
5c5d8b686a feat: introduce basic_value
it is capable to change comment policy, backend container of an array
and a table.
2019-06-01 20:18:57 +09:00
ToruNiina
5c3c1bd0e7 feat: add missing default array/table type 2019-06-01 20:18:15 +09:00
ToruNiina
696e5bb66f feat: extend has_from_toml_method to be generic 2019-06-01 20:16:59 +09:00
ToruNiina
65540fbb5c fix: typos 2019-06-01 19:47:10 +09:00
ToruNiina
351320491d fix: fix has_from_toml using basic_value 2019-06-01 19:46:20 +09:00
ToruNiina
d30700517d fix: add missing include file 2019-06-01 19:43:35 +09:00
ToruNiina
14ad8d0556 fix: fix typos and invalid names 2019-06-01 19:43:15 +09:00
ToruNiina
f04c97b587 refactor: simplify format_underline a bit 2019-06-01 19:06:08 +09:00
ToruNiina
b8d3038d38 feat: add meta function to detect conversions 2019-06-01 16:03:26 +09:00
ToruNiina
eaa3604dce refactor: introduce value_t_constant
as an alias for integral_constant
2019-06-01 16:01:48 +09:00
ToruNiina
8acc348106 feat: 💥 change interface around types
- change value_t::typename from CamelCase to snake_case.
- drop CamelCase typename supports.
The changes are introduced to make the interfaces uniform. For some
(historical) reasons, toml11 has both CamelCase names and snake_case
names for types. Additionally, since `float` is a keyword, snake_case
names uses `floating` to avoid collision and CamelCase name uses `Float`
because toml official calls it `Float`. This is too confusing.
Since it is a major upgrade, I think it is a big chance to make them
uniform.
2019-06-01 13:33:57 +09:00
ToruNiina
2567f2a787 feat: add source_location for error message generation. 2019-06-01 13:25:02 +09:00
ToruNiina
84b5749c6b feat: implement comment containers 2019-06-01 13:24:54 +09:00
ToruNiina
70d0049511 refactor: move some meta-funcs to traits.hpp 2019-06-01 12:35:40 +09:00
52 changed files with 7429 additions and 3599 deletions

View File

@@ -10,9 +10,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-5 - g++-5
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: gcc compiler: gcc
@@ -21,9 +22,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-6 - g++-6
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: gcc compiler: gcc
@@ -32,9 +34,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-7 - g++-7
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: gcc compiler: gcc
@@ -43,9 +46,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8 - g++-8
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: gcc compiler: gcc
@@ -54,9 +58,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8 - g++-8
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -66,9 +71,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7 - llvm-toolchain-precise-3.7
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-3.7 - clang-3.7
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -78,9 +85,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0 - llvm-toolchain-trusty-4.0
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-4.0 - clang-4.0
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -90,9 +99,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0 - llvm-toolchain-trusty-5.0
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-5.0 - clang-5.0
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -102,9 +113,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-6.0 - llvm-toolchain-trusty-6.0
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-6.0 - clang-6.0
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -114,9 +127,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7 - llvm-toolchain-trusty-7
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-7 - clang-7
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -126,9 +141,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-8 - llvm-toolchain-trusty-8
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-8 - clang-8
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -138,10 +155,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-8 - llvm-toolchain-trusty-8
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- clang-8 - clang-8
- g++-8 - g++-8
- libboost-all-dev - boost1.70
- os: osx - os: osx
language: cpp language: cpp
compiler: clang compiler: clang
@@ -151,11 +169,11 @@ script:
- | - |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
mkdir -p cmake mkdir -p cmake
travis_retry wget "https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.tar.gz" travis_retry wget "https://github.com/Kitware/CMake/releases/download/v3.14.5/cmake-3.14.5-Linux-x86_64.tar.gz"
tar xf cmake-3.11.2-Linux-x86_64.tar.gz -C cmake --strip-components=1 tar xf cmake-3.14.5-Linux-x86_64.tar.gz -C cmake --strip-components=1
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH} export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
else else
brew upgrade cmake brew upgrade cmake boost
fi fi
- cmake --version - cmake --version
- mkdir build - mkdir build

View File

@@ -1,7 +1,17 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
enable_testing() enable_testing()
project(toml11) project(toml11)
set(toml11_VERSION_MAYOR 2)
set(toml11_VERSION_MINOR 4)
set(toml11_VERSION_PATCH 0)
set(toml11_VERSION
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
)
option(toml11_BUILD_TEST "Build toml tests" ON)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
if("${CMAKE_VERSION}" VERSION_GREATER 3.1) if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
@@ -34,5 +44,62 @@ else()
endif() endif()
endif() endif()
include_directories(${PROJECT_SOURCE_DIR}) # Set some common directories
add_subdirectory(tests) include(GNUInstallDirs)
set(toml11_install_cmake_dir ${CMAKE_INSTALL_LIBDIR}/cmake/toml11)
set(toml11_install_include_dir ${CMAKE_INSTALL_INCLUDEDIR})
set(toml11_config_dir ${CMAKE_CURRENT_BINARY_DIR}/cmake/)
set(toml11_config ${toml11_config_dir}/toml11Config.cmake)
set(toml11_config_version ${toml11_config_dir}/toml11ConfigVersion.cmake)
add_library(toml11 INTERFACE)
target_include_directories(toml11 INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${toml11_install_include_dir}>
)
add_library(toml11::toml11 ALIAS toml11)
# Write config and version config files
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${toml11_config_version}
VERSION ${toml11_VERSION}
COMPATIBILITY SameMajorVersion
)
configure_package_config_file(
cmake/toml11Config.cmake.in
${toml11_config}
INSTALL_DESTINATION ${toml11_install_cmake_dir}
PATH_VARS toml11_install_cmake_dir
)
# Install config files
install(FILES ${toml11_config} ${toml11_config_version}
DESTINATION ${toml11_install_cmake_dir}
)
# Install header files
install(
FILES toml.hpp
DESTINATION "${toml11_install_include_dir}"
)
install(
DIRECTORY "toml"
DESTINATION "${toml11_install_include_dir}"
FILES_MATCHING PATTERN "*.hpp"
)
# Export targets and install them
install(TARGETS toml11
EXPORT toml11Targets
)
install(EXPORT toml11Targets
FILE toml11Targets.cmake
DESTINATION ${toml11_install_cmake_dir}
NAMESPACE toml11::
)
if (toml11_BUILD_TEST)
add_subdirectory(tests)
endif ()

1062
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ build_script:
- cd build - cd build
- git clone https://github.com/toml-lang/toml.git - git clone https://github.com/toml-lang/toml.git
- file --mime-encoding toml/tests/hard_example_unicode.toml - file --mime-encoding toml/tests/hard_example_unicode.toml
- cmake -G"%generator%" -DBOOST_ROOT=C:/Libraries/boost_1_63_0 .. - cmake -G"%generator%" -DBOOST_ROOT=C:/Libraries/boost_1_69_0 ..
- cmake --build . --config "%configuration%" - cmake --build . --config "%configuration%"
test_script: test_script:

View File

@@ -0,0 +1,2 @@
@PACKAGE_INIT@
include("@PACKAGE_toml11_install_cmake_dir@/toml11Targets.cmake")

View File

@@ -23,8 +23,10 @@ set(TEST_NAMES
test_literals test_literals
test_comments test_comments
test_get test_get
test_get_related_func test_get_or
test_from_toml test_find
test_find_or
test_expect
test_parse_file test_parse_file
test_serialize_file test_serialize_file
test_parse_unicode test_parse_unicode
@@ -34,12 +36,15 @@ set(TEST_NAMES
) )
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL) CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA)
CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC) CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
if(COMPILER_SUPPORTS_WALL) if(COMPILER_SUPPORTS_WALL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif() endif()
if(COMPILER_SUPPORTS_WEXTRA)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
endif()
if(COMPILER_SUPPORTS_WPEDANTIC) if(COMPILER_SUPPORTS_WPEDANTIC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
endif() endif()
@@ -88,7 +93,7 @@ add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST)
foreach(TEST_NAME ${TEST_NAMES}) foreach(TEST_NAME ${TEST_NAMES})
add_executable(${TEST_NAME} ${TEST_NAME}.cpp) add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS}) target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
@@ -105,3 +110,4 @@ endforeach(TEST_NAME)
add_executable(test_multiple_translation_unit add_executable(test_multiple_translation_unit
test_multiple_translation_unit_1.cpp test_multiple_translation_unit_1.cpp
test_multiple_translation_unit_2.cpp) test_multiple_translation_unit_2.cpp)
target_link_libraries(test_multiple_translation_unit toml11::toml11)

View File

@@ -84,7 +84,7 @@ struct json_serializer
{ {
if(!is_first) {std::cout << ", ";} if(!is_first) {std::cout << ", ";}
is_first = false; is_first = false;
std::cout << toml::format(toml::string(elem.first), std::cout << toml::format(toml::value(elem.first),
std::numeric_limits<std::size_t>::max()); std::numeric_limits<std::size_t>::max());
std::cout << ':'; std::cout << ':';
toml::visit(*this, elem.second); toml::visit(*this, elem.second);

View File

@@ -10,116 +10,453 @@
BOOST_AUTO_TEST_CASE(test_comment_before) BOOST_AUTO_TEST_CASE(test_comment_before)
{ {
using namespace toml::literals::toml_literals;
{ {
const toml::value v = u8R"( const std::string file = u8R"(
# comment for a. # comment for a.
a = 42 a = 42
# comment for b. # comment for b.
b = "baz" b = "baz"
)"_toml; )";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), u8"# comment for a."); const auto& a = toml::find(v, "a");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), u8"# comment for b."); const auto& b = toml::find(v, "b");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), "");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), "");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8"# comment for a."); BOOST_TEST(a.comments().size() == 1u);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b."); BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_TEST(b.comments().size() == 1u);
BOOST_TEST(b.comments().front() == u8" comment for b.");
} }
{ {
const toml::value v = u8R"( const std::string file = u8R"(
# comment for a. # comment for a.
# another comment for a. # another comment for a.
a = 42 a = 42
# comment for b. # comment for b.
# also comment for b. # also comment for b.
b = "baz" b = "baz"
)"_toml; )";
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), u8R"(# comment for a. std::istringstream iss(file);
# another comment for a.)"); const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), u8R"(# comment for b.
# also comment for b.)");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8"");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a. const auto& a = toml::find(v, "a");
# another comment for a.)"); const auto& b = toml::find(v, "b");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8R"(# comment for b.
# also comment for b.)"); BOOST_TEST(a.comments().size() == 2u);
BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_TEST(a.comments().back() == u8" another comment for a.");
BOOST_TEST(b.comments().size() == 2u);
BOOST_TEST(b.comments().front() == u8" comment for b.");
BOOST_TEST(b.comments().back() == u8" also comment for b.");
} }
} }
BOOST_AUTO_TEST_CASE(test_comment_inline) BOOST_AUTO_TEST_CASE(test_comment_inline)
{ {
using namespace toml::literals::toml_literals;
{ {
const toml::value v = u8R"( const std::string file = u8R"(
a = 42 # comment for a. a = 42 # comment for a.
b = "baz" # comment for b. b = "baz" # comment for b.
)"_toml; )";
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), ""); std::istringstream iss(file);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), ""); const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8"# comment for a.");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"# comment for b.");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8"# comment for a."); const auto& a = toml::find(v, "a");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b."); const auto& b = toml::find(v, "b");
BOOST_TEST(a.comments().size() == 1u);
BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_TEST(b.comments().size() == 1u);
BOOST_TEST(b.comments().front() == u8" comment for b.");
} }
{ {
const toml::value v = u8R"( const std::string file = u8R"(
a = [ # comment for a. a = [
42, 42,
] # this also. ] # comment for a.
b = [ # comment for b. b = [
"bar", "bar", # this is not a comment for b, but "bar"
] ] # this is a comment for b.
c = [ )";
3.14, # this is not a comment for c, but 3.14.
] # comment for c.
)"_toml;
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), ""); std::istringstream iss(file);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), ""); const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "c").comment_before(), "");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8R"(# comment for a. const auto& a = toml::find(v, "a");
# this also.)"); const auto& b = toml::find(v, "b");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"# comment for b."); const auto& b0 = b.as_array().at(0);
BOOST_CHECK_EQUAL(toml::find(v, "c").comment_inline(), u8"# comment for c.");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a. BOOST_TEST(a.comments().size() == 1u);
# this also.)"); BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b."); BOOST_TEST(b.comments().size() == 1u);
BOOST_CHECK_EQUAL(toml::find(v, "c").comment(), u8"# comment for c."); BOOST_TEST(b.comments().front() == u8" this is a comment for b.");
BOOST_TEST(b0.comments().size() == 1u);
const auto& c0 = toml::find<toml::array>(v, "c").at(0); BOOST_TEST(b0.comments().front() == u8" this is not a comment for b, but \"bar\"");
BOOST_CHECK_EQUAL(c0.comment(), u8"# this is not a comment for c, but 3.14.");
} }
} }
BOOST_AUTO_TEST_CASE(test_comment_both) BOOST_AUTO_TEST_CASE(test_comment_both)
{ {
using namespace toml::literals::toml_literals;
{ {
const toml::value v = u8R"( const std::string file = u8R"(
# comment for a. # comment for a.
a = 42 # inline comment for a. a = 42 # inline comment for a.
# comment for b. # comment for b.
b = "baz" # inline comment for b. b = "baz" # inline comment for b.
)"_toml; # comment for c.
c = [ # this comment will be ignored
# comment for the first element.
10 # this also.
] # another comment for c.
)";
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), "# comment for a."); std::istringstream iss(file);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), "# comment for b."); const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), "# inline comment for a.");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), "# inline comment for b.");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a. const auto& a = toml::find(v, "a");
# inline comment for a.)"); const auto& b = toml::find(v, "b");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8R"(# comment for b. const auto& c = toml::find(v, "c");
# inline comment for b.)"); const auto& c0 = c.as_array().at(0);
BOOST_TEST(a.comments().size() == 2u);
BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_TEST(a.comments().back() == u8" inline comment for a.");
BOOST_TEST(b.comments().size() == 2u);
BOOST_TEST(b.comments().front() == u8" comment for b.");
BOOST_TEST(b.comments().back() == u8" inline comment for b.");
BOOST_TEST(c.comments().size() == 2u);
BOOST_TEST(c.comments().front() == u8" comment for c.");
BOOST_TEST(c.comments().back() == u8" another comment for c.");
BOOST_TEST(c0.comments().size() == 2u);
BOOST_TEST(c0.comments().front() == u8" comment for the first element.");
BOOST_TEST(c0.comments().back() == u8" this also.");
}
}
BOOST_AUTO_TEST_CASE(test_discard_comment)
{
const std::string file = u8R"(
# comment for a.
a = 42 # inline comment for a.
# comment for b.
b = "baz" # inline comment for b.
# comment for c.
c = [ # this comment will be ignored
# comment for the first element.
10 # this also.
] # another comment for c.
)";
std::istringstream iss(file);
const auto v = toml::parse(iss);
const auto& a = toml::find(v, "a");
const auto& b = toml::find(v, "b");
const auto& c = toml::find(v, "c");
const auto& c0 = c.as_array().at(0);
BOOST_TEST(a.comments().empty());
BOOST_TEST(b.comments().empty());
BOOST_TEST(c.comments().empty());
BOOST_TEST(c0.comments().empty());
}
BOOST_AUTO_TEST_CASE(test_construct_value_with_comments)
{
using value_type = toml::basic_value<toml::preserve_comments>;
{
const value_type v(true, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_boolean());
BOOST_TEST(v.as_boolean() == true);
}
{
const value_type v(42, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_integer());
BOOST_TEST(v.as_integer() == 42);
}
{
const value_type v(3.14, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_floating());
BOOST_TEST(v.as_floating() == 3.14);
}
{
const value_type v(toml::string("str"), {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
const value_type v(std::string("str"), {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
const value_type v(std::string("str"), toml::string_t::literal,
{"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
const value_type v("str", {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
const value_type v("str", toml::string_t::literal,
{"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
#if __cplusplus >= 201703L
{
using namespace std::literals::string_view_literals;
const value_type v("str"sv, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
using namespace std::literals::string_view_literals;
const value_type v("str"sv, toml::string_t::literal,
{"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
#endif
const toml::local_date ld{2019, toml::month_t::Apr, 1};
const toml::local_time lt{12, 30, 45};
const toml::local_datetime ldt{ld, lt};
const toml::offset_datetime odt{ld, lt, toml::time_offset{9, 0}};
{
const value_type v(ld, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_local_date());
BOOST_TEST(v.as_local_date() == ld);
}
{
const value_type v(lt, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_local_time());
BOOST_TEST(v.as_local_time() == lt);
}
{
const toml::local_time three_hours{3,0,0};
const value_type v(std::chrono::hours(3), {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_local_time());
BOOST_TEST(v.as_local_time() == three_hours);
}
{
const value_type v(ldt, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_local_datetime());
BOOST_TEST(v.as_local_datetime() == ldt);
}
{
const value_type v(odt, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_offset_datetime());
BOOST_TEST(v.as_offset_datetime() == odt);
}
{
const auto systp = static_cast<std::chrono::system_clock::time_point>(odt);
const value_type v(systp, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_offset_datetime());
// While the conversion, the information about time offset may change.
const auto systp2 = static_cast<std::chrono::system_clock::time_point>(
v.as_offset_datetime());
const bool result = systp == systp2; // because there is no operator<<
BOOST_TEST(result);
}
{
const typename value_type::array_type a{1,2,3,4,5};
const value_type v(a, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_array());
BOOST_TEST(v.as_array().at(0).is_integer());
BOOST_TEST(v.as_array().at(1).is_integer());
BOOST_TEST(v.as_array().at(2).is_integer());
BOOST_TEST(v.as_array().at(3).is_integer());
BOOST_TEST(v.as_array().at(4).is_integer());
BOOST_TEST(v.as_array().at(0).as_integer() == 1);
BOOST_TEST(v.as_array().at(1).as_integer() == 2);
BOOST_TEST(v.as_array().at(2).as_integer() == 3);
BOOST_TEST(v.as_array().at(3).as_integer() == 4);
BOOST_TEST(v.as_array().at(4).as_integer() == 5);
}
{
const std::initializer_list<int> a = {1,2,3,4,5};
const value_type v(a, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_array());
BOOST_TEST(v.as_array().at(0).is_integer());
BOOST_TEST(v.as_array().at(1).is_integer());
BOOST_TEST(v.as_array().at(2).is_integer());
BOOST_TEST(v.as_array().at(3).is_integer());
BOOST_TEST(v.as_array().at(4).is_integer());
BOOST_TEST(v.as_array().at(0).as_integer() == 1);
BOOST_TEST(v.as_array().at(1).as_integer() == 2);
BOOST_TEST(v.as_array().at(2).as_integer() == 3);
BOOST_TEST(v.as_array().at(3).as_integer() == 4);
BOOST_TEST(v.as_array().at(4).as_integer() == 5);
}
{
const std::vector<int> a = {1,2,3,4,5};
const value_type v(a, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_array());
BOOST_TEST(v.as_array().at(0).is_integer());
BOOST_TEST(v.as_array().at(1).is_integer());
BOOST_TEST(v.as_array().at(2).is_integer());
BOOST_TEST(v.as_array().at(3).is_integer());
BOOST_TEST(v.as_array().at(4).is_integer());
BOOST_TEST(v.as_array().at(0).as_integer() == 1);
BOOST_TEST(v.as_array().at(1).as_integer() == 2);
BOOST_TEST(v.as_array().at(2).as_integer() == 3);
BOOST_TEST(v.as_array().at(3).as_integer() == 4);
BOOST_TEST(v.as_array().at(4).as_integer() == 5);
}
{
const typename value_type::table_type t{
{"key1", 42}, {"key2", "foobar"}
};
const value_type v(t, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_table());
BOOST_TEST(v.as_table().at("key1").is_integer());
BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
BOOST_TEST(v.as_table().at("key2").is_string());
BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
}
{
const std::initializer_list<std::pair<std::string, value_type>> t{
{"key1", 42}, {"key2", "foobar"}
};
const value_type v(t, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_table());
BOOST_TEST(v.as_table().at("key1").is_integer());
BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
BOOST_TEST(v.as_table().at("key2").is_string());
BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
}
{
const std::map<std::string, value_type> t{
{"key1", 42}, {"key2", "foobar"}
};
const value_type v(t, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_table());
BOOST_TEST(v.as_table().at("key1").is_integer());
BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
BOOST_TEST(v.as_table().at("key2").is_string());
BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
}
}
BOOST_AUTO_TEST_CASE(test_overwrite_comments)
{
using value_type = toml::basic_value<toml::preserve_comments>;
{
const value_type v(42, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_integer());
BOOST_TEST(v.as_integer() == 42);
const value_type u(v, {"comment3", "comment4"});
BOOST_TEST(u.comments().size() == 2u);
BOOST_TEST(u.comments().at(0) == "comment3");
BOOST_TEST(u.comments().at(1) == "comment4");
BOOST_TEST(u.is_integer());
BOOST_TEST(u.as_integer() == 42);
}
{
const value_type v(42, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_integer());
BOOST_TEST(v.as_integer() == 42);
const value_type u(v);
BOOST_TEST(u.comments().size() == 2u);
BOOST_TEST(u.comments().at(0) == "comment1");
BOOST_TEST(u.comments().at(1) == "comment2");
BOOST_TEST(u.is_integer());
BOOST_TEST(u.as_integer() == 42);
}
{
const value_type v(42, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_integer());
BOOST_TEST(v.as_integer() == 42);
const value_type u(v, {});
BOOST_TEST(u.comments().size() == 0u);
BOOST_TEST(u.is_integer());
BOOST_TEST(u.as_integer() == 42);
} }
} }

View File

@@ -11,47 +11,47 @@ BOOST_AUTO_TEST_CASE(test_local_date)
{ {
const toml::local_date date(2018, toml::month_t::Jan, 1); const toml::local_date date(2018, toml::month_t::Jan, 1);
const toml::local_date date1(date); const toml::local_date date1(date);
BOOST_CHECK_EQUAL(date, date1); BOOST_TEST(date == date1);
const std::chrono::system_clock::time_point tp(date); const std::chrono::system_clock::time_point tp(date);
const toml::local_date date2(tp); const toml::local_date date2(tp);
BOOST_CHECK_EQUAL(date, date2); BOOST_TEST(date == date2);
const toml::local_date date3(2017, toml::month_t::Dec, 31); const toml::local_date date3(2017, toml::month_t::Dec, 31);
BOOST_CHECK(date > date3); BOOST_TEST(date > date3);
std::ostringstream oss; std::ostringstream oss;
oss << date; oss << date;
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01")); BOOST_TEST(oss.str() == std::string("2018-01-01"));
} }
BOOST_AUTO_TEST_CASE(test_local_time) BOOST_AUTO_TEST_CASE(test_local_time)
{ {
const toml::local_time time(12, 30, 45); const toml::local_time time(12, 30, 45);
const toml::local_time time1(time); const toml::local_time time1(time);
BOOST_CHECK_EQUAL(time, time1); BOOST_TEST(time == time1);
const std::chrono::nanoseconds dur(time); const std::chrono::nanoseconds dur(time);
std::chrono::nanoseconds ns(0); std::chrono::nanoseconds ns(0);
ns += std::chrono::hours (12); ns += std::chrono::hours (12);
ns += std::chrono::minutes(30); ns += std::chrono::minutes(30);
ns += std::chrono::seconds(45); ns += std::chrono::seconds(45);
BOOST_CHECK_EQUAL(dur.count(), ns.count()); BOOST_TEST(dur.count() == ns.count());
const toml::local_time time3(12, 15, 45); const toml::local_time time3(12, 15, 45);
BOOST_CHECK(time > time3); BOOST_TEST(time > time3);
{ {
std::ostringstream oss; std::ostringstream oss;
oss << time; oss << time;
BOOST_CHECK_EQUAL(oss.str(), std::string("12:30:45")); BOOST_TEST(oss.str() == std::string("12:30:45"));
} }
{ {
const toml::local_time time4(12, 30, 45, 123, 456); const toml::local_time time4(12, 30, 45, 123, 456);
std::ostringstream oss; std::ostringstream oss;
oss << time4; oss << time4;
BOOST_CHECK_EQUAL(oss.str(), std::string("12:30:45.123456")); BOOST_TEST(oss.str() == std::string("12:30:45.123456"));
} }
} }
@@ -59,20 +59,20 @@ BOOST_AUTO_TEST_CASE(test_time_offset)
{ {
const toml::time_offset time(9, 30); const toml::time_offset time(9, 30);
const toml::time_offset time1(time); const toml::time_offset time1(time);
BOOST_CHECK_EQUAL(time, time1); BOOST_TEST(time == time1);
const std::chrono::minutes dur(time); const std::chrono::minutes dur(time);
std::chrono::minutes m(0); std::chrono::minutes m(0);
m += std::chrono::hours (9); m += std::chrono::hours (9);
m += std::chrono::minutes(30); m += std::chrono::minutes(30);
BOOST_CHECK_EQUAL(dur.count(), m.count()); BOOST_TEST(dur.count() == m.count());
const toml::time_offset time2(9, 0); const toml::time_offset time2(9, 0);
BOOST_CHECK(time2 < time); BOOST_TEST(time2 < time);
std::ostringstream oss; std::ostringstream oss;
oss << time; oss << time;
BOOST_CHECK_EQUAL(oss.str(), std::string("+09:30")); BOOST_TEST(oss.str() == std::string("+09:30"));
} }
BOOST_AUTO_TEST_CASE(test_local_datetime) BOOST_AUTO_TEST_CASE(test_local_datetime)
@@ -80,15 +80,15 @@ BOOST_AUTO_TEST_CASE(test_local_datetime)
const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1), const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1),
toml::local_time(12, 30, 45)); toml::local_time(12, 30, 45));
const toml::local_datetime dt1(dt); const toml::local_datetime dt1(dt);
BOOST_CHECK_EQUAL(dt, dt1); BOOST_TEST(dt == dt1);
const std::chrono::system_clock::time_point tp(dt); const std::chrono::system_clock::time_point tp(dt);
const toml::local_datetime dt2(tp); const toml::local_datetime dt2(tp);
BOOST_CHECK_EQUAL(dt, dt2); BOOST_TEST(dt == dt2);
std::ostringstream oss; std::ostringstream oss;
oss << dt; oss << dt;
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45")); BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45"));
} }
BOOST_AUTO_TEST_CASE(test_offset_datetime) BOOST_AUTO_TEST_CASE(test_offset_datetime)
@@ -97,17 +97,18 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
toml::local_time(12, 30, 45), toml::local_time(12, 30, 45),
toml::time_offset(9, 30)); toml::time_offset(9, 30));
const toml::offset_datetime dt1(dt); const toml::offset_datetime dt1(dt);
BOOST_CHECK_EQUAL(dt, dt1); BOOST_TEST(dt == dt1);
const std::chrono::system_clock::time_point tp1(dt); const std::chrono::system_clock::time_point tp1(dt);
const toml::offset_datetime dt2(tp1); const toml::offset_datetime dt2(tp1);
const std::chrono::system_clock::time_point tp2(dt2); const std::chrono::system_clock::time_point tp2(dt2);
BOOST_CHECK(tp1 == tp2); const bool tp_same = (tp1 == tp2);
BOOST_TEST(tp_same);
{ {
std::ostringstream oss; std::ostringstream oss;
oss << dt; oss << dt;
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45+09:30")); BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45+09:30"));
} }
{ {
const toml::offset_datetime dt3( const toml::offset_datetime dt3(
@@ -116,6 +117,6 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
toml::time_offset(0, 0)); toml::time_offset(0, 0));
std::ostringstream oss; std::ostringstream oss;
oss << dt3; oss << dt3;
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45Z")); BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45Z"));
} }
} }

View File

@@ -12,50 +12,19 @@
BOOST_AUTO_TEST_CASE(test_detect_empty_key) BOOST_AUTO_TEST_CASE(test_detect_empty_key)
{ {
std::istringstream stream(std::string("= \"value\"")); std::istringstream stream(std::string("= \"value\""));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_missing_value)
{ {
std::istringstream stream(std::string("a =")); std::istringstream stream(std::string("a ="));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_too_many_value)
{ {
std::istringstream stream(std::string("a = 1 = \"value\"")); std::istringstream stream(std::string("a = 1 = \"value\""));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
@@ -66,17 +35,7 @@ BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
"[table]\n" "[table]\n"
"b = 42\n" "b = 42\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
@@ -87,17 +46,7 @@ BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
"[table]\n" "[table]\n"
"b = 42\n" "b = 42\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
@@ -108,17 +57,7 @@ BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
"[[table]]\n" "[[table]]\n"
"b = 42\n" "b = 42\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
@@ -127,17 +66,7 @@ BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
"a = 1\n" "a = 1\n"
"a = 2\n" "a = 2\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
@@ -146,17 +75,7 @@ BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
"a.b = 1\n" "a.b = 1\n"
"a.b.c = 2\n" "a.b.c = 2\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
@@ -164,17 +83,7 @@ BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
std::istringstream stream(std::string( std::istringstream stream(std::string(
"a = [1, 1.0]\n" "a = [1, 1.0]\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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) BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
@@ -184,16 +93,5 @@ BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
"[[a]]\n" "[[a]]\n"
"b = 2\n" "b = 2\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
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);
} }

30
tests/test_expect.cpp Normal file
View File

@@ -0,0 +1,30 @@
#define BOOST_TEST_MODULE "test_expect"
#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_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_TEST(42 == v1_or_0);
BOOST_TEST( 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_TEST("42" == v1_or_none);
BOOST_TEST("none" == v2_or_none);
}
}

View File

@@ -6,6 +6,8 @@
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#endif #endif
#include <toml.hpp> #include <toml.hpp>
#include <deque>
#include <map>
namespace extlib namespace extlib
{ {
@@ -54,35 +56,141 @@ struct into<extlib::foo>
}; };
} // toml } // toml
// ---------------------------------------------------------------------------
namespace extlib2
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
template<typename C, template<typename ...> class M, template<typename ...> class A>
void from_toml(const toml::basic_value<C, M, A>& 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}};
}
};
} // extlib2
namespace toml
{
template<>
struct from<extlib2::foo>
{
template<typename C, template<typename ...> class M, template<typename ...> class A>
static extlib2::foo from_toml(const toml::basic_value<C, M, A>& v)
{
return extlib2::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib2::foo>
{
static toml::table into_toml(const extlib2::foo& f)
{
return toml::table{{"a", f.a}, {"b", f.b}};
}
};
} // toml
// ---------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods) BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods)
{ {
{
const toml::value v{{"a", 42}, {"b", "baz"}}; const toml::value v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib::foo>(v); const auto foo = toml::get<extlib::foo>(v);
BOOST_CHECK_EQUAL(foo.a, 42); BOOST_TEST(foo.a == 42);
BOOST_CHECK_EQUAL(foo.b, "baz"); BOOST_TEST(foo.b == "baz");
const toml::value v2(foo); const toml::value v2(foo);
BOOST_CHECK_EQUAL(v, v2); BOOST_TEST(v == v2);
}
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib2::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::value v2(foo);
BOOST_TEST(v == v2);
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib2::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v2(foo);
BOOST_TEST(v == v2);
}
} }
BOOST_AUTO_TEST_CASE(test_conversion_by_specialization) BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
{ {
{
const toml::value v{{"a", 42}, {"b", "baz"}}; const toml::value v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib::bar>(v); const auto bar = toml::get<extlib::bar>(v);
BOOST_CHECK_EQUAL(bar.a, 42); BOOST_TEST(bar.a == 42);
BOOST_CHECK_EQUAL(bar.b, "baz"); BOOST_TEST(bar.b == "baz");
const toml::value v2(bar); const toml::value v2(bar);
BOOST_CHECK_EQUAL(v, v2); BOOST_TEST(v == v2);
}
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib2::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "baz");
const toml::value v2(bar);
BOOST_TEST(v == v2);
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib2::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "baz");
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v2(bar);
BOOST_TEST(v == v2);
}
} }
BOOST_AUTO_TEST_CASE(test_recursive_conversion) BOOST_AUTO_TEST_CASE(test_recursive_conversion)
{ {
{
const toml::value v{ const toml::value v{
toml::table{{"a", 42}, {"b", "baz"}}, toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}}, toml::table{{"a", 43}, {"b", "qux"}},
@@ -91,26 +199,94 @@ BOOST_AUTO_TEST_CASE(test_recursive_conversion)
}; };
const auto foos = toml::get<std::vector<extlib::foo>>(v); const auto foos = toml::get<std::vector<extlib::foo>>(v);
BOOST_CHECK_EQUAL(foos.size() , 4ul); BOOST_TEST(foos.size() == 4ul);
BOOST_CHECK_EQUAL(foos.at(0).a , 42); BOOST_TEST(foos.at(0).a == 42);
BOOST_CHECK_EQUAL(foos.at(1).a , 43); BOOST_TEST(foos.at(1).a == 43);
BOOST_CHECK_EQUAL(foos.at(2).a , 44); BOOST_TEST(foos.at(2).a == 44);
BOOST_CHECK_EQUAL(foos.at(3).a , 45); BOOST_TEST(foos.at(3).a == 45);
BOOST_CHECK_EQUAL(foos.at(0).b , "baz"); BOOST_TEST(foos.at(0).b == "baz");
BOOST_CHECK_EQUAL(foos.at(1).b , "qux"); BOOST_TEST(foos.at(1).b == "qux");
BOOST_CHECK_EQUAL(foos.at(2).b , "quux"); BOOST_TEST(foos.at(2).b == "quux");
BOOST_CHECK_EQUAL(foos.at(3).b , "foobar"); BOOST_TEST(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib::bar>>(v); const auto bars = toml::get<std::vector<extlib::bar>>(v);
BOOST_CHECK_EQUAL(bars.size() , 4ul); BOOST_TEST(bars.size() == 4ul);
BOOST_CHECK_EQUAL(bars.at(0).a , 42); BOOST_TEST(bars.at(0).a == 42);
BOOST_CHECK_EQUAL(bars.at(1).a , 43); BOOST_TEST(bars.at(1).a == 43);
BOOST_CHECK_EQUAL(bars.at(2).a , 44); BOOST_TEST(bars.at(2).a == 44);
BOOST_CHECK_EQUAL(bars.at(3).a , 45); BOOST_TEST(bars.at(3).a == 45);
BOOST_CHECK_EQUAL(bars.at(0).b , "baz"); BOOST_TEST(bars.at(0).b == "baz");
BOOST_CHECK_EQUAL(bars.at(1).b , "qux"); BOOST_TEST(bars.at(1).b == "qux");
BOOST_CHECK_EQUAL(bars.at(2).b , "quux"); BOOST_TEST(bars.at(2).b == "quux");
BOOST_CHECK_EQUAL(bars.at(3).b , "foobar"); BOOST_TEST(bars.at(3).b == "foobar");
}
{
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<extlib2::foo>>(v);
BOOST_TEST(foos.size() == 4ul);
BOOST_TEST(foos.at(0).a == 42);
BOOST_TEST(foos.at(1).a == 43);
BOOST_TEST(foos.at(2).a == 44);
BOOST_TEST(foos.at(3).a == 45);
BOOST_TEST(foos.at(0).b == "baz");
BOOST_TEST(foos.at(1).b == "qux");
BOOST_TEST(foos.at(2).b == "quux");
BOOST_TEST(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib2::bar>>(v);
BOOST_TEST(bars.size() == 4ul);
BOOST_TEST(bars.at(0).a == 42);
BOOST_TEST(bars.at(1).a == 43);
BOOST_TEST(bars.at(2).a == 44);
BOOST_TEST(bars.at(3).a == 45);
BOOST_TEST(bars.at(0).b == "baz");
BOOST_TEST(bars.at(1).b == "qux");
BOOST_TEST(bars.at(2).b == "quux");
BOOST_TEST(bars.at(3).b == "foobar");
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}}
};
const auto foos = toml::get<std::vector<extlib2::foo>>(v);
BOOST_TEST(foos.size() == 4ul);
BOOST_TEST(foos.at(0).a == 42);
BOOST_TEST(foos.at(1).a == 43);
BOOST_TEST(foos.at(2).a == 44);
BOOST_TEST(foos.at(3).a == 45);
BOOST_TEST(foos.at(0).b == "baz");
BOOST_TEST(foos.at(1).b == "qux");
BOOST_TEST(foos.at(2).b == "quux");
BOOST_TEST(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib2::bar>>(v);
BOOST_TEST(bars.size() == 4ul);
BOOST_TEST(bars.at(0).a == 42);
BOOST_TEST(bars.at(1).a == 43);
BOOST_TEST(bars.at(2).a == 44);
BOOST_TEST(bars.at(3).a == 45);
BOOST_TEST(bars.at(0).b == "baz");
BOOST_TEST(bars.at(1).b == "qux");
BOOST_TEST(bars.at(2).b == "quux");
BOOST_TEST(bars.at(3).b == "foobar");
}
} }

432
tests/test_find.cpp Normal file
View File

@@ -0,0 +1,432 @@
#define BOOST_TEST_MODULE "test_find"
#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>
#if __cplusplus >= 201703L
#include <string_view>
#endif
#include <tuple>
using test_value_types = std::tuple<
toml::value,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
BOOST_AUTO_TEST_CASE(test_find_throws)
{
{
// value is not a table
toml::value v(true);
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
}
{
// the value corresponding to the key is not the expected type
toml::value v{{"key", 42}};
BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
}
{
// the value corresponding to the key is not found
toml::value v{{"key", 42}};
BOOST_CHECK_THROW(toml::find<toml::integer>(v, "different_key"),
std::out_of_range);
}
{
// the positive control.
toml::value v{{"key", 42}};
BOOST_TEST(42 == toml::find<int>(v, "key"));
}
}
BOOST_AUTO_TEST_CASE(test_find_recursive)
{
// recursively search tables
{
toml::value v{
{"a", {
{"b", {
{"c", {
{"d", 42}
}}
}}
}}
};
BOOST_TEST(42 == toml::find<int>(v, "a", "b", "c", "d"));
// reference that can be used to modify the content
auto& num = toml::find<toml::integer>(v, "a", "b", "c", "d");
num = 54;
BOOST_TEST(54 == toml::find<int>(v, "a", "b", "c", "d"));
const std::string a("a"), b("b"), c("c"), d("d");
auto& num2 = toml::find<toml::integer>(v, a, b, c, d);
num2 = 42;
BOOST_TEST(42 == toml::find<int>(v, a, b, c, d));
}
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
{
{
value_type v{{"key", true}};
BOOST_TEST(true == toml::find<toml::boolean>(v, "key"));
toml::find<toml::boolean>(v, "key") = false;
BOOST_TEST(false == toml::find<toml::boolean>(v, "key"));
}
{
value_type v{{"key", 42}};
BOOST_TEST(toml::integer(42) == toml::find<toml::integer>(v, "key"));
toml::find<toml::integer>(v, "key") = 54;
BOOST_TEST(toml::integer(54) == toml::find<toml::integer>(v, "key"));
}
{
value_type v{{"key", 3.14}};
BOOST_TEST(toml::floating(3.14) == toml::find<toml::floating>(v, "key"));
toml::find<toml::floating>(v, "key") = 2.71;
BOOST_TEST(toml::floating(2.71) == toml::find<toml::floating>(v, "key"));
}
{
value_type v{{"key", "foo"}};
BOOST_TEST(toml::string("foo", toml::string_t::basic) ==
toml::find<toml::string>(v, "key"));
toml::find<toml::string>(v, "key").str += "bar";
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
toml::find<toml::string>(v, "key"));
}
{
value_type v{{"key", value_type("foo", toml::string_t::literal)}};
BOOST_TEST(toml::string("foo", toml::string_t::literal) ==
toml::find<toml::string>(v, "key"));
toml::find<toml::string>(v, "key").str += "bar";
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
toml::find<toml::string>(v, "key"));
}
{
toml::local_date d(2018, toml::month_t::Apr, 22);
value_type v{{"key", d}};
BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
toml::find<toml::local_date>(v, "key").year = 2017;
d.year = 2017;
BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
}
{
toml::local_time t(12, 30, 45);
value_type v{{"key", t}};
BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
toml::find<toml::local_time>(v, "key").hour = 9;
t.hour = 9;
BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
}
{
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45));
value_type v{{"key", dt}};
BOOST_CHECK(dt == toml::find<toml::local_datetime>(v, "key"));
toml::find<toml::local_datetime>(v, "key").date.year = 2017;
dt.date.year = 2017;
BOOST_CHECK(dt == toml::find<toml::local_datetime>(v, "key"));
}
{
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));
value_type v{{"key", dt}};
BOOST_CHECK(dt == toml::find<toml::offset_datetime>(v, "key"));
toml::find<toml::offset_datetime>(v, "key").date.year = 2017;
dt.date.year = 2017;
BOOST_CHECK(dt == toml::find<toml::offset_datetime>(v, "key"));
}
{
typename value_type::array_type vec;
vec.push_back(value_type(42));
vec.push_back(value_type(54));
value_type v{{"key", vec}};
const bool result1 = (vec == toml::find<typename value_type::array_type>(v, "key"));
BOOST_CHECK(result1);
toml::find<typename value_type::array_type>(v, "key").push_back(value_type(123));
vec.push_back(value_type(123));
const bool result2 = (vec == toml::find<typename value_type::array_type>(v, "key"));
BOOST_CHECK(result2);
}
{
typename value_type::table_type tab;
tab["key1"] = value_type(42);
tab["key2"] = value_type(3.14);
value_type v{{"key", tab}};
const bool result1 = (tab == toml::find<typename value_type::table_type>(v, "key"));
BOOST_CHECK(result1);
toml::find<typename value_type::table_type>(v, "key")["key3"] = value_type(123);
tab["key3"] = value_type(123);
const bool result2 = (tab == toml::find<typename value_type::table_type>(v, "key"));
BOOST_CHECK(result2);
}
{
value_type v1(42);
value_type v{{"key", v1}};
BOOST_CHECK(v1 == toml::find(v, "key"));
value_type v2(54);
toml::find(v, "key") = v2;
BOOST_CHECK(v2 == toml::find(v, "key"));
}
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_integer_type, value_type, test_value_types)
{
{
value_type v{{"key", 42}};
BOOST_TEST(int(42) == toml::find<int >(v, "key"));
BOOST_TEST(short(42) == toml::find<short >(v, "key"));
BOOST_TEST(char(42) == toml::find<char >(v, "key"));
BOOST_TEST(unsigned(42) == toml::find<unsigned >(v, "key"));
BOOST_TEST(long(42) == toml::find<long >(v, "key"));
BOOST_TEST(std::int64_t(42) == toml::find<std::int64_t >(v, "key"));
BOOST_TEST(std::uint64_t(42) == toml::find<std::uint64_t>(v, "key"));
BOOST_TEST(std::int16_t(42) == toml::find<std::int16_t >(v, "key"));
BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(v, "key"));
}
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_types)
{
{
value_type v{{"key", 3.14}};
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(v, "key"));
BOOST_TEST(static_cast<double >(3.14) == toml::find<double >(v, "key"));
BOOST_TEST(static_cast<long double>(3.14) == toml::find<long double>(v, "key"));
}
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_string_type, value_type, test_value_types)
{
{
value_type v{{"key", toml::string("foo", toml::string_t::basic)}};
BOOST_TEST("foo" == toml::find<std::string>(v, "key"));
toml::find<std::string>(v, "key") += "bar";
BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
}
{
value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
BOOST_TEST("foo" == toml::find<std::string>(v, "key"));
toml::find<std::string>(v, "key") += "bar";
BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
}
#if __cplusplus >= 201703L
{
value_type v{{"key", toml::string("foo", toml::string_t::basic)}};
BOOST_TEST("foo" == toml::find<std::string_view>(v, "key"));
}
{
value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
BOOST_TEST("foo" == toml::find<std::string_view>(v, "key"));
}
#endif
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array, value_type, test_value_types)
{
value_type v{{"key", {42, 54, 69, 72}}};
const std::vector<int> vec = toml::find<std::vector<int>>(v, "key");
const std::list<short> lst = toml::find<std::list<short>>(v, "key");
const std::deque<std::int64_t> deq = toml::find<std::deque<std::int64_t>>(v, "key");
BOOST_TEST(42 == vec.at(0));
BOOST_TEST(54 == vec.at(1));
BOOST_TEST(69 == vec.at(2));
BOOST_TEST(72 == vec.at(3));
std::list<short>::const_iterator iter = lst.begin();
BOOST_TEST(static_cast<short>(42) == *(iter++));
BOOST_TEST(static_cast<short>(54) == *(iter++));
BOOST_TEST(static_cast<short>(69) == *(iter++));
BOOST_TEST(static_cast<short>(72) == *(iter++));
BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
std::array<int, 4> ary = toml::find<std::array<int, 4>>(v, "key");
BOOST_TEST(static_cast<int>(42) == ary.at(0));
BOOST_TEST(static_cast<int>(54) == ary.at(1));
BOOST_TEST(static_cast<int>(69) == ary.at(2));
BOOST_TEST(static_cast<int>(72) == ary.at(3));
std::tuple<int, short, unsigned, long> tpl =
toml::find<std::tuple<int, short, unsigned, long>>(v, "key");
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
value_type p{{"key", {3.14, 2.71}}};
std::pair<double, double> pr = toml::find<std::pair<double, double> >(p, "key");
BOOST_TEST(3.14 == pr.first);
BOOST_TEST(2.71 == pr.second);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_value_types)
{
value_type v1{42, 54, 69, 72};
value_type v2{"foo", "bar", "baz"};
value_type v{{"key", {v1, v2}}};
std::pair<std::vector<int>, std::vector<std::string>> p =
toml::find<std::pair<std::vector<int>, std::vector<std::string>>>(v, "key");
BOOST_TEST(p.first.at(0) == 42);
BOOST_TEST(p.first.at(1) == 54);
BOOST_TEST(p.first.at(2) == 69);
BOOST_TEST(p.first.at(3) == 72);
BOOST_TEST(p.second.at(0) == "foo");
BOOST_TEST(p.second.at(1) == "bar");
BOOST_TEST(p.second.at(2) == "baz");
std::tuple<std::vector<int>, std::vector<std::string>> t =
toml::find<std::tuple<std::vector<int>, std::vector<std::string>>>(v, "key");
BOOST_TEST(std::get<0>(t).at(0) == 42);
BOOST_TEST(std::get<0>(t).at(1) == 54);
BOOST_TEST(std::get<0>(t).at(2) == 69);
BOOST_TEST(std::get<0>(t).at(3) == 72);
BOOST_TEST(std::get<1>(t).at(0) == "foo");
BOOST_TEST(std::get<1>(t).at(1) == "bar");
BOOST_TEST(std::get<1>(t).at(2) == "baz");
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_table, value_type, test_value_types)
{
value_type v1{{"key", {
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
}}};
const auto v = toml::find<std::map<std::string, int>>(v1, "key");
BOOST_TEST(v.at("key1") == 1);
BOOST_TEST(v.at("key2") == 2);
BOOST_TEST(v.at("key3") == 3);
BOOST_TEST(v.at("key4") == 4);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_date, value_type, test_value_types)
{
value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
const auto date = std::chrono::system_clock::to_time_t(
toml::find<std::chrono::system_clock::time_point>(v1, "key"));
std::tm t;
t.tm_year = 2018 - 1900;
t.tm_mon = 4 - 1;
t.tm_mday = 1;
t.tm_hour = 0;
t.tm_min = 0;
t.tm_sec = 0;
t.tm_isdst = -1;
const auto c = std::mktime(&t);
BOOST_TEST(c == date);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_time, value_type, test_value_types)
{
value_type v1{{"key", toml::local_time{12, 30, 45}}};
const auto time = toml::find<std::chrono::seconds>(v1, "key");
BOOST_CHECK(time == std::chrono::hours(12) +
std::chrono::minutes(30) + std::chrono::seconds(45));
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_datetime, value_type, test_value_types)
{
value_type v1{{"key", toml::local_datetime(
toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 45})}};
const auto date = std::chrono::system_clock::to_time_t(
toml::find<std::chrono::system_clock::time_point>(v1, "key"));
std::tm t;
t.tm_year = 2018 - 1900;
t.tm_mon = 4 - 1;
t.tm_mday = 1;
t.tm_hour = 12;
t.tm_min = 30;
t.tm_sec = 45;
t.tm_isdst = -1;
const auto c = std::mktime(&t);
BOOST_TEST(c == date);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types)
{
{
value_type v1{{"key", toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0},
toml::time_offset{9, 0})}};
// 2018-04-01T12:30:00+09:00
// == 2018-04-01T03:30:00Z
const auto date = toml::find<std::chrono::system_clock::time_point>(v1, "key");
const auto timet = std::chrono::system_clock::to_time_t(date);
// get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_CHECK(tmp);
const auto tm = *tmp;
BOOST_TEST(tm.tm_year + 1900 == 2018);
BOOST_TEST(tm.tm_mon + 1 == 4);
BOOST_TEST(tm.tm_mday == 1);
BOOST_TEST(tm.tm_hour == 3);
BOOST_TEST(tm.tm_min == 30);
BOOST_TEST(tm.tm_sec == 0);
}
{
value_type v1{{"key", toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0},
toml::time_offset{-8, 0})}};
// 2018-04-01T12:30:00-08:00
// == 2018-04-01T20:30:00Z
const auto date = toml::find<std::chrono::system_clock::time_point>(v1, "key");
const auto timet = std::chrono::system_clock::to_time_t(date);
// get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_CHECK(tmp);
const auto tm = *tmp;
BOOST_TEST(tm.tm_year + 1900 == 2018);
BOOST_TEST(tm.tm_mon + 1 == 4);
BOOST_TEST(tm.tm_mday == 1);
BOOST_TEST(tm.tm_hour == 20);
BOOST_TEST(tm.tm_min == 30);
BOOST_TEST(tm.tm_sec == 0);
}
}

360
tests/test_find_or.cpp Normal file
View File

@@ -0,0 +1,360 @@
#define BOOST_TEST_MODULE "test_find_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>
#include <tuple>
#if __cplusplus >= 201703L
#include <string_view>
#endif
using test_value_types = std::tuple<
toml::value,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
namespace test
{
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Comp, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::map<Key, Value, Comp, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::unordered_map<Key, Value, Hash, Eq, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
} // test
#define TOML11_TEST_FIND_OR_EXACT(toml_type, init_expr, opt_expr)\
{ \
using namespace test; \
const toml::toml_type init init_expr ; \
const toml::toml_type opt opt_expr ; \
const value_type v{{"key", init}}; \
BOOST_TEST(init != opt); \
BOOST_TEST(init == toml::find_or(v, "key", opt)); \
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types)
{
TOML11_TEST_FIND_OR_EXACT(boolean, ( true), (false))
TOML11_TEST_FIND_OR_EXACT(integer, ( 42), ( 54))
TOML11_TEST_FIND_OR_EXACT(floating, ( 3.14), ( 2.71))
TOML11_TEST_FIND_OR_EXACT(string, ("foo"), ("bar"))
TOML11_TEST_FIND_OR_EXACT(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_FIND_OR_EXACT(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_FIND_OR_EXACT(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
)
TOML11_TEST_FIND_OR_EXACT(offset_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
)
{
const typename value_type::array_type init{1,2,3,4,5};
const typename value_type::array_type opt {6,7,8,9,10};
const value_type v{{"key", init}};
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::find_or(v, "key", opt));
}
{
const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
const value_type v{{"key", init}};
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::find_or(v, "key", opt));
}
}
#undef TOML11_TEST_FIND_OR_EXACT
#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\
{ \
using namespace test; \
const toml::toml_type init init_expr ; \
toml::toml_type opt1 opt_expr ; \
toml::toml_type opt2 opt_expr ; \
value_type v{{"key", init}}; \
BOOST_TEST(init != opt1); \
toml::find_or(v, "key", opt2) = opt1; \
BOOST_TEST(opt1 == toml::find<toml::toml_type>(v, "key"));\
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_modify, value_type, test_value_types)
{
TOML11_TEST_FIND_OR_MODIFY(boolean, ( true), (false))
TOML11_TEST_FIND_OR_MODIFY(integer, ( 42), ( 54))
TOML11_TEST_FIND_OR_MODIFY(floating, ( 3.14), ( 2.71))
TOML11_TEST_FIND_OR_MODIFY(string, ("foo"), ("bar"))
TOML11_TEST_FIND_OR_MODIFY(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_FIND_OR_MODIFY(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_FIND_OR_MODIFY(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
)
TOML11_TEST_FIND_OR_MODIFY(offset_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
)
{
typename value_type::array_type init{1,2,3,4,5};
typename value_type::array_type opt1{6,7,8,9,10};
typename value_type::array_type opt2{6,7,8,9,10};
BOOST_TEST(init != opt1);
value_type v{{"key", init}};
toml::find_or(v, "key", opt2) = opt1;
BOOST_TEST(opt1 == toml::find<typename value_type::array_type>(v, "key"));
}
{
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}};
typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}};
value_type v{{"key", init}};
BOOST_TEST(init != opt1);
toml::find_or(v, "key", opt2) = opt1;
BOOST_TEST(opt1 == toml::find<typename value_type::table_type>(v, "key"));
}
}
#undef TOML11_TEST_FIND_OR_MODIFY
#define TOML11_TEST_FIND_OR_FALLBACK(init_type, opt_type) \
{ \
using namespace test; \
value_type v(init_type); \
BOOST_TEST(opt_type == toml::find_or(v, "key", opt_type));\
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_types)
{
const toml::boolean boolean (true);
const toml::integer integer (42);
const toml::floating floating (3.14);
const toml::string string ("foo");
const toml::local_time local_time (12, 30, 45);
const toml::local_date local_date (2019, toml::month_t::Apr, 1);
const toml::local_datetime local_datetime (
toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45));
const toml::offset_datetime offset_datetime(
toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45), toml::time_offset( 9, 0));
using array_type = typename value_type::array_type;
using table_type = typename value_type::table_type;
const array_type array{1, 2, 3, 4, 5};
const table_type table{{"key1", 42}, {"key2", "foo"}};
TOML11_TEST_FIND_OR_FALLBACK(boolean, integer );
TOML11_TEST_FIND_OR_FALLBACK(boolean, floating );
TOML11_TEST_FIND_OR_FALLBACK(boolean, string );
TOML11_TEST_FIND_OR_FALLBACK(boolean, local_time );
TOML11_TEST_FIND_OR_FALLBACK(boolean, local_date );
TOML11_TEST_FIND_OR_FALLBACK(boolean, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(boolean, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(boolean, array );
TOML11_TEST_FIND_OR_FALLBACK(boolean, table );
TOML11_TEST_FIND_OR_FALLBACK(integer, boolean );
TOML11_TEST_FIND_OR_FALLBACK(integer, floating );
TOML11_TEST_FIND_OR_FALLBACK(integer, string );
TOML11_TEST_FIND_OR_FALLBACK(integer, local_time );
TOML11_TEST_FIND_OR_FALLBACK(integer, local_date );
TOML11_TEST_FIND_OR_FALLBACK(integer, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(integer, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(integer, array );
TOML11_TEST_FIND_OR_FALLBACK(integer, table );
TOML11_TEST_FIND_OR_FALLBACK(floating, boolean );
TOML11_TEST_FIND_OR_FALLBACK(floating, integer );
TOML11_TEST_FIND_OR_FALLBACK(floating, string );
TOML11_TEST_FIND_OR_FALLBACK(floating, local_time );
TOML11_TEST_FIND_OR_FALLBACK(floating, local_date );
TOML11_TEST_FIND_OR_FALLBACK(floating, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(floating, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(floating, array );
TOML11_TEST_FIND_OR_FALLBACK(floating, table );
TOML11_TEST_FIND_OR_FALLBACK(string, boolean );
TOML11_TEST_FIND_OR_FALLBACK(string, integer );
TOML11_TEST_FIND_OR_FALLBACK(string, floating );
TOML11_TEST_FIND_OR_FALLBACK(string, local_time );
TOML11_TEST_FIND_OR_FALLBACK(string, local_date );
TOML11_TEST_FIND_OR_FALLBACK(string, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(string, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(string, array );
TOML11_TEST_FIND_OR_FALLBACK(string, table );
TOML11_TEST_FIND_OR_FALLBACK(local_time, boolean );
TOML11_TEST_FIND_OR_FALLBACK(local_time, integer );
TOML11_TEST_FIND_OR_FALLBACK(local_time, floating );
TOML11_TEST_FIND_OR_FALLBACK(local_time, string );
TOML11_TEST_FIND_OR_FALLBACK(local_time, local_date );
TOML11_TEST_FIND_OR_FALLBACK(local_time, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(local_time, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(local_time, array );
TOML11_TEST_FIND_OR_FALLBACK(local_time, table );
TOML11_TEST_FIND_OR_FALLBACK(local_date, boolean );
TOML11_TEST_FIND_OR_FALLBACK(local_date, integer );
TOML11_TEST_FIND_OR_FALLBACK(local_date, floating );
TOML11_TEST_FIND_OR_FALLBACK(local_date, string );
TOML11_TEST_FIND_OR_FALLBACK(local_date, local_time );
TOML11_TEST_FIND_OR_FALLBACK(local_date, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(local_date, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(local_date, array );
TOML11_TEST_FIND_OR_FALLBACK(local_date, table );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, boolean );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, integer );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, floating );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, string );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_time );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_date );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, array );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, table );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, boolean );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, integer );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, floating );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, string );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_time );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_date );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, array );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, table );
TOML11_TEST_FIND_OR_FALLBACK(array, boolean );
TOML11_TEST_FIND_OR_FALLBACK(array, integer );
TOML11_TEST_FIND_OR_FALLBACK(array, floating );
TOML11_TEST_FIND_OR_FALLBACK(array, string );
TOML11_TEST_FIND_OR_FALLBACK(array, local_time );
TOML11_TEST_FIND_OR_FALLBACK(array, local_date );
TOML11_TEST_FIND_OR_FALLBACK(array, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(array, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(array, table );
TOML11_TEST_FIND_OR_FALLBACK(table, boolean );
TOML11_TEST_FIND_OR_FALLBACK(table, integer );
TOML11_TEST_FIND_OR_FALLBACK(table, floating );
TOML11_TEST_FIND_OR_FALLBACK(table, string );
TOML11_TEST_FIND_OR_FALLBACK(table, local_time );
TOML11_TEST_FIND_OR_FALLBACK(table, local_date );
TOML11_TEST_FIND_OR_FALLBACK(table, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(table, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(table, array );
}
#undef TOML11_TEST_FIND_OR_FALLBACK
BOOST_AUTO_TEST_CASE(test_find_or_integer)
{
{
toml::value v = toml::table{{"num", 42}};
BOOST_TEST(42u == toml::find_or(v, "num", 0u));
BOOST_TEST(0u == toml::find_or(v, "foo", 0u));
}
}
BOOST_AUTO_TEST_CASE(test_find_or_floating)
{
{
toml::value v1{{"key", 42}};
toml::value v2{{"key", 3.14}};
BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f));
BOOST_TEST(static_cast<float>(double(3.14)) == toml::find_or(v2, "key", 2.71f));
}
}
BOOST_AUTO_TEST_CASE(test_find_or_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_TEST("foobar" == toml::find_or(v1, "key", s1));
BOOST_TEST("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_TEST("foobar" == v1r);
BOOST_TEST("bazqux" == s1r);
BOOST_TEST("foobar" == toml::find_or(v1, "key", s2));
BOOST_TEST("bazqux" == toml::find_or(v2, "key", s2));
BOOST_TEST("foobar" == toml::find_or(std::move(v1), "key", std::move(s1)));
s1 = "bazqux"; // restoring moved value
BOOST_TEST("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_TEST("foobar" == toml::find_or(v1, "key", "bazqux"));
BOOST_TEST("bazqux" == toml::find_or(v2, "key", "bazqux"));
const char* lit = "bazqux";
BOOST_TEST("foobar" == toml::find_or(v1, "key", lit));
BOOST_TEST("bazqux" == toml::find_or(v2, "key", lit));
}
}

View File

@@ -1,4 +1,4 @@
#define BOOST_TEST_MODULE "test_value" #define BOOST_TEST_MODULE "test_format_error"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST #ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#else #else

View File

@@ -1,63 +0,0 @@
#define BOOST_TEST_MODULE "test_from_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 <unordered_map>
#include <list>
#include <deque>
#include <array>
BOOST_AUTO_TEST_CASE(test_from_toml)
{
toml::boolean b = false;
toml::integer i = 0;
toml::floating f = 0.;
toml::string s;
toml::local_date dt;
toml::array a;
toml::table t;
{
toml::value v(true);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK_EQUAL(b, true);
}
{
toml::value v(42);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
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::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK_EQUAL(s, "foo");
}
{
toml::value v(toml::local_date(2018, toml::month_t::Apr, 22));
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK(dt == toml::local_date(2018, toml::month_t::Apr, 22));
}
{
toml::array ref{toml::value(42), toml::value(54)};
toml::value v(ref);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK(ref == a);
}
{
toml::table ref{{"key1", 42}, {"key2", 3.14}};
toml::value v(ref);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK(ref == t);
}
}

View File

@@ -5,294 +5,284 @@
#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/value.hpp> #include <toml.hpp>
#include <toml/get.hpp>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <list> #include <list>
#include <deque> #include <deque>
#include <array> #include <array>
#include <tuple>
#if __cplusplus >= 201703L #if __cplusplus >= 201703L
#include <string_view> #include <string_view>
#endif #endif
using test_value_types = std::tuple<
toml::value,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
BOOST_AUTO_TEST_CASE(test_get_exact) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
{ {
{ {
toml::value v(true); value_type v(true);
BOOST_CHECK_EQUAL(true, toml::get<toml::boolean>(v)); BOOST_TEST(true == toml::get<toml::boolean>(v));
toml::get<toml::boolean>(v) = false; toml::get<toml::boolean>(v) = false;
BOOST_CHECK_EQUAL(false, toml::get<toml::boolean>(v)); BOOST_TEST(false == toml::get<toml::boolean>(v));
} }
{ {
toml::value v(42); value_type v(42);
BOOST_CHECK_EQUAL(toml::integer(42), toml::get<toml::integer>(v)); BOOST_TEST(toml::integer(42) == toml::get<toml::integer>(v));
toml::get<toml::integer>(v) = 54; toml::get<toml::integer>(v) = 54;
BOOST_CHECK_EQUAL(toml::integer(54), toml::get<toml::integer>(v)); BOOST_TEST(toml::integer(54) == toml::get<toml::integer>(v));
} }
{ {
toml::value v(3.14); value_type v(3.14);
BOOST_CHECK_EQUAL(toml::floating(3.14), toml::get<toml::floating>(v)); BOOST_TEST(toml::floating(3.14) == toml::get<toml::floating>(v));
toml::get<toml::floating>(v) = 2.71; toml::get<toml::floating>(v) = 2.71;
BOOST_CHECK_EQUAL(toml::floating(2.71), toml::get<toml::floating>(v)); BOOST_TEST(toml::floating(2.71) == toml::get<toml::floating>(v));
} }
{ {
toml::value v("foo"); value_type v("foo");
BOOST_CHECK_EQUAL(toml::string("foo", toml::string_t::basic), BOOST_TEST(toml::string("foo", toml::string_t::basic) ==
toml::get<toml::string>(v)); toml::get<toml::string>(v));
toml::get<toml::string>(v).str += "bar"; toml::get<toml::string>(v).str += "bar";
BOOST_CHECK_EQUAL(toml::string("foobar", toml::string_t::basic), BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
toml::get<toml::string>(v)); toml::get<toml::string>(v));
} }
{ {
toml::value v("foo", toml::string_t::literal); value_type v("foo", toml::string_t::literal);
BOOST_CHECK_EQUAL(toml::string("foo", toml::string_t::literal), BOOST_TEST(toml::string("foo", toml::string_t::literal) ==
toml::get<toml::string>(v)); toml::get<toml::string>(v));
toml::get<toml::string>(v).str += "bar"; toml::get<toml::string>(v).str += "bar";
BOOST_CHECK_EQUAL(toml::string("foobar", toml::string_t::literal), BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
toml::get<toml::string>(v)); toml::get<toml::string>(v));
} }
{ {
toml::local_date d(2018, toml::month_t::Apr, 22); toml::local_date d(2018, toml::month_t::Apr, 22);
toml::value v(d); value_type v(d);
BOOST_CHECK(d == toml::get<toml::local_date>(v)); BOOST_TEST(d == toml::get<toml::local_date>(v));
toml::get<toml::local_date>(v).year = 2017; toml::get<toml::local_date>(v).year = 2017;
d.year = 2017; d.year = 2017;
BOOST_CHECK(d == toml::get<toml::local_date>(v)); BOOST_TEST(d == toml::get<toml::local_date>(v));
} }
{ {
toml::local_time t(12, 30, 45); toml::local_time t(12, 30, 45);
toml::value v(t); value_type v(t);
BOOST_CHECK(t == toml::get<toml::local_time>(v)); BOOST_TEST(t == toml::get<toml::local_time>(v));
toml::get<toml::local_time>(v).hour = 9; toml::get<toml::local_time>(v).hour = 9;
t.hour = 9; t.hour = 9;
BOOST_CHECK(t == toml::get<toml::local_time>(v)); BOOST_TEST(t == toml::get<toml::local_time>(v));
} }
{ {
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22), toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45)); toml::local_time(12, 30, 45));
toml::value v(dt); value_type v(dt);
BOOST_CHECK(dt == toml::get<toml::local_datetime>(v)); BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
toml::get<toml::local_datetime>(v).date.year = 2017; toml::get<toml::local_datetime>(v).date.year = 2017;
dt.date.year = 2017; dt.date.year = 2017;
BOOST_CHECK(dt == toml::get<toml::local_datetime>(v)); BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
} }
{ {
toml::offset_datetime dt(toml::local_datetime( toml::offset_datetime dt(toml::local_datetime(
toml::local_date(2018, toml::month_t::Apr, 22), toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45)), toml::time_offset(9, 0)); toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
toml::value v(dt); value_type v(dt);
BOOST_CHECK(dt == toml::get<toml::offset_datetime>(v)); BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
toml::get<toml::offset_datetime>(v).date.year = 2017; toml::get<toml::offset_datetime>(v).date.year = 2017;
dt.date.year = 2017; dt.date.year = 2017;
BOOST_CHECK(dt == toml::get<toml::offset_datetime>(v)); BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
} }
{ {
toml::array vec; using array_type = typename value_type::array_type;
vec.push_back(toml::value(42)); array_type vec;
vec.push_back(toml::value(54)); vec.push_back(value_type(42));
toml::value v(vec); vec.push_back(value_type(54));
BOOST_CHECK(vec == toml::get<toml::array>(v)); value_type v(vec);
BOOST_TEST(vec == toml::get<array_type>(v));
toml::get<toml::array>(v).push_back(toml::value(123)); toml::get<array_type>(v).push_back(value_type(123));
vec.push_back(toml::value(123)); vec.push_back(value_type(123));
BOOST_CHECK(vec == toml::get<toml::array>(v)); BOOST_TEST(vec == toml::get<array_type>(v));
} }
{ {
toml::table tab; using table_type = typename value_type::table_type;
tab["key1"] = toml::value(42); table_type tab;
tab["key2"] = toml::value(3.14); tab["key1"] = value_type(42);
toml::value v(tab); tab["key2"] = value_type(3.14);
BOOST_CHECK(tab == toml::get<toml::table>(v)); value_type v(tab);
BOOST_TEST(tab == toml::get<table_type>(v));
toml::get<toml::table>(v)["key3"] = toml::value(123); toml::get<table_type>(v)["key3"] = value_type(123);
tab["key3"] = toml::value(123); tab["key3"] = value_type(123);
BOOST_CHECK(tab == toml::get<toml::table>(v)); BOOST_TEST(tab == toml::get<table_type>(v));
} }
{ {
toml::value v1(42); value_type v1(42);
BOOST_CHECK(v1 == toml::get<toml::value>(v1)); BOOST_TEST(v1 == toml::get<value_type>(v1));
toml::value v2(54); value_type v2(54);
toml::get<toml::value>(v1) = v2; toml::get<value_type>(v1) = v2;
BOOST_CHECK(v2 == toml::get<toml::value>(v1)); BOOST_TEST(v2 == toml::get<value_type>(v1));
} }
} }
BOOST_AUTO_TEST_CASE(test_get_integer_type) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_integer_type, value_type, test_value_types)
{ {
{ {
toml::value v(42); value_type v(42);
BOOST_CHECK_EQUAL(int(42), toml::get<int >(v)); BOOST_TEST(int(42) == toml::get<int >(v));
BOOST_CHECK_EQUAL(short(42), toml::get<short >(v)); BOOST_TEST(short(42) == toml::get<short >(v));
BOOST_CHECK_EQUAL(char(42), toml::get<char >(v)); BOOST_TEST(char(42) == toml::get<char >(v));
BOOST_CHECK_EQUAL(unsigned(42), toml::get<unsigned >(v)); BOOST_TEST(unsigned(42) == toml::get<unsigned >(v));
BOOST_CHECK_EQUAL(long(42), toml::get<long >(v)); BOOST_TEST(long(42) == toml::get<long >(v));
BOOST_CHECK_EQUAL(std::int64_t(42), toml::get<std::int64_t >(v)); BOOST_TEST(std::int64_t(42) == toml::get<std::int64_t >(v));
BOOST_CHECK_EQUAL(std::uint64_t(42), toml::get<std::uint64_t>(v)); BOOST_TEST(std::uint64_t(42) == toml::get<std::uint64_t>(v));
BOOST_CHECK_EQUAL(std::int16_t(42), toml::get<std::int16_t >(v)); BOOST_TEST(std::int16_t(42) == toml::get<std::int16_t >(v));
BOOST_CHECK_EQUAL(std::uint16_t(42), toml::get<std::uint16_t>(v)); BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(v));
} }
} }
BOOST_AUTO_TEST_CASE(test_get_floating_type) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_types)
{ {
{ {
toml::value v(3.14); value_type v(3.14);
BOOST_CHECK_EQUAL(static_cast<float >(3.14), toml::get<float >(v)); BOOST_TEST(static_cast<float >(3.14) == toml::get<float >(v));
BOOST_CHECK_EQUAL(static_cast<double >(3.14), toml::get<double >(v)); BOOST_TEST(static_cast<double >(3.14) == toml::get<double >(v));
BOOST_CHECK_EQUAL(static_cast<long double>(3.14), toml::get<long double>(v)); BOOST_TEST(static_cast<long double>(3.14) == toml::get<long double>(v));
} }
} }
BOOST_AUTO_TEST_CASE(test_get_string_type) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types)
{ {
{ {
toml::value v("foo", toml::string_t::basic); value_type v("foo", toml::string_t::basic);
BOOST_CHECK_EQUAL("foo", toml::get<std::string>(v)); BOOST_TEST("foo" == toml::get<std::string>(v));
toml::get<std::string>(v) += "bar"; toml::get<std::string>(v) += "bar";
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v)); BOOST_TEST("foobar" == toml::get<std::string>(v));
} }
{ {
toml::value v("foo", toml::string_t::literal); value_type v("foo", toml::string_t::literal);
BOOST_CHECK_EQUAL("foo", toml::get<std::string>(v)); BOOST_TEST("foo" == toml::get<std::string>(v));
toml::get<std::string>(v) += "bar"; toml::get<std::string>(v) += "bar";
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v)); BOOST_TEST("foobar" == toml::get<std::string>(v));
} }
#if __cplusplus >= 201703L #if __cplusplus >= 201703L
{ {
toml::value v("foo", toml::string_t::basic); value_type v("foo", toml::string_t::basic);
BOOST_CHECK_EQUAL("foo", toml::get<std::string_view>(v)); BOOST_TEST("foo" == toml::get<std::string_view>(v));
} }
{ {
toml::value v("foo", toml::string_t::literal); value_type v("foo", toml::string_t::literal);
BOOST_CHECK_EQUAL("foo", toml::get<std::string_view>(v)); BOOST_TEST("foo" == toml::get<std::string_view>(v));
} }
#endif #endif
} }
BOOST_AUTO_TEST_CASE(test_get_toml_array) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
{ {
toml::value v(toml::array(0)); const value_type v{42, 54, 69, 72};
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::vector<int> vec = toml::get<std::vector<int>>(v);
const std::list<short> lst = toml::get<std::list<short>>(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); const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v);
BOOST_CHECK_EQUAL(42, vec.at(0)); BOOST_TEST(42 == vec.at(0));
BOOST_CHECK_EQUAL(54, vec.at(1)); BOOST_TEST(54 == vec.at(1));
BOOST_CHECK_EQUAL(69, vec.at(2)); BOOST_TEST(69 == vec.at(2));
BOOST_CHECK_EQUAL(72, vec.at(3)); BOOST_TEST(72 == vec.at(3));
std::list<short>::const_iterator iter = lst.begin(); std::list<short>::const_iterator iter = lst.begin();
BOOST_CHECK_EQUAL(static_cast<short>(42), *(iter++)); BOOST_TEST(static_cast<short>(42) == *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(54), *(iter++)); BOOST_TEST(static_cast<short>(54) == *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(69), *(iter++)); BOOST_TEST(static_cast<short>(69) == *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(72), *(iter++)); BOOST_TEST(static_cast<short>(72) == *(iter++));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(42), deq.at(0)); BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(54), deq.at(1)); BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(69), deq.at(2)); BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(72), deq.at(3)); BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v); std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
BOOST_CHECK_EQUAL(static_cast<int>(42), ary.at(0)); BOOST_TEST(static_cast<int>(42) == ary.at(0));
BOOST_CHECK_EQUAL(static_cast<int>(54), ary.at(1)); BOOST_TEST(static_cast<int>(54) == ary.at(1));
BOOST_CHECK_EQUAL(static_cast<int>(69), ary.at(2)); BOOST_TEST(static_cast<int>(69) == ary.at(2));
BOOST_CHECK_EQUAL(static_cast<int>(72), ary.at(3)); BOOST_TEST(static_cast<int>(72) == ary.at(3));
std::tuple<int, short, unsigned, long> tpl = std::tuple<int, short, unsigned, long> tpl =
toml::get<std::tuple<int, short, unsigned, long>>(v); toml::get<std::tuple<int, short, unsigned, long>>(v);
BOOST_CHECK_EQUAL(static_cast<int >(42), std::get<0>(tpl)); BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
BOOST_CHECK_EQUAL(static_cast<short >(54), std::get<1>(tpl)); BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
BOOST_CHECK_EQUAL(static_cast<unsigned>(69), std::get<2>(tpl)); BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
BOOST_CHECK_EQUAL(static_cast<long >(72), std::get<3>(tpl)); BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
toml::value p(toml::array{}); const value_type p{3.14, 2.71};
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); std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
BOOST_CHECK_EQUAL(3.14, pr.first); BOOST_TEST(3.14 == pr.first);
BOOST_CHECK_EQUAL(2.71, pr.second); BOOST_TEST(2.71 == pr.second);
} }
BOOST_AUTO_TEST_CASE(test_get_toml_array_of_array) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_value_types)
{ {
toml::value v1(toml::array{}); const value_type v1{42, 54, 69, 72};
toml::get<toml::array>(v1).push_back(toml::value(42)); const value_type v2{"foo", "bar", "baz"};
toml::get<toml::array>(v1).push_back(toml::value(54)); const value_type v{v1, v2};
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 = std::pair<std::vector<int>, std::vector<std::string>> p =
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v); toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
BOOST_CHECK_EQUAL(p.first.at(0), 42); BOOST_TEST(p.first.at(0) == 42);
BOOST_CHECK_EQUAL(p.first.at(1), 54); BOOST_TEST(p.first.at(1) == 54);
BOOST_CHECK_EQUAL(p.first.at(2), 69); BOOST_TEST(p.first.at(2) == 69);
BOOST_CHECK_EQUAL(p.first.at(3), 72); BOOST_TEST(p.first.at(3) == 72);
BOOST_CHECK_EQUAL(p.second.at(0), "foo"); BOOST_TEST(p.second.at(0) == "foo");
BOOST_CHECK_EQUAL(p.second.at(1), "bar"); BOOST_TEST(p.second.at(1) == "bar");
BOOST_CHECK_EQUAL(p.second.at(2), "baz"); BOOST_TEST(p.second.at(2) == "baz");
std::tuple<std::vector<int>, std::vector<std::string>> t = std::tuple<std::vector<int>, std::vector<std::string>> t =
toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v); toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v);
BOOST_CHECK_EQUAL(std::get<0>(t).at(0), 42); BOOST_TEST(std::get<0>(t).at(0) == 42);
BOOST_CHECK_EQUAL(std::get<0>(t).at(1), 54); BOOST_TEST(std::get<0>(t).at(1) == 54);
BOOST_CHECK_EQUAL(std::get<0>(t).at(2), 69); BOOST_TEST(std::get<0>(t).at(2) == 69);
BOOST_CHECK_EQUAL(std::get<0>(t).at(3), 72); BOOST_TEST(std::get<0>(t).at(3) == 72);
BOOST_CHECK_EQUAL(std::get<1>(t).at(0), "foo"); BOOST_TEST(std::get<1>(t).at(0) == "foo");
BOOST_CHECK_EQUAL(std::get<1>(t).at(1), "bar"); BOOST_TEST(std::get<1>(t).at(1) == "bar");
BOOST_CHECK_EQUAL(std::get<1>(t).at(2), "baz"); BOOST_TEST(std::get<1>(t).at(2) == "baz");
} }
BOOST_AUTO_TEST_CASE(test_get_toml_table) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types)
{ {
toml::value v1(toml::table{ const value_type v1{
{"key1", 1}, {"key1", 1},
{"key2", 2}, {"key2", 2},
{"key3", 3}, {"key3", 3},
{"key4", 4} {"key4", 4}
}); };
const auto v = toml::get<std::map<std::string, int>>(v1); const auto v = toml::get<std::map<std::string, int>>(v1);
BOOST_CHECK_EQUAL(v.at("key1"), 1); BOOST_TEST(v.at("key1") == 1);
BOOST_CHECK_EQUAL(v.at("key2"), 2); BOOST_TEST(v.at("key2") == 2);
BOOST_CHECK_EQUAL(v.at("key3"), 3); BOOST_TEST(v.at("key3") == 3);
BOOST_CHECK_EQUAL(v.at("key4"), 4); BOOST_TEST(v.at("key4") == 4);
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types)
BOOST_AUTO_TEST_CASE(test_get_toml_local_date)
{ {
toml::value v1(toml::local_date{2018, toml::month_t::Apr, 1}); value_type v1(toml::local_date{2018, toml::month_t::Apr, 1});
const auto date = std::chrono::system_clock::to_time_t( const auto date = std::chrono::system_clock::to_time_t(
toml::get<std::chrono::system_clock::time_point>(v1)); toml::get<std::chrono::system_clock::time_point>(v1));
@@ -305,20 +295,22 @@ BOOST_AUTO_TEST_CASE(test_get_toml_local_date)
t.tm_sec = 0; t.tm_sec = 0;
t.tm_isdst = -1; t.tm_isdst = -1;
const auto c = std::mktime(&t); const auto c = std::mktime(&t);
BOOST_CHECK_EQUAL(c, date); BOOST_TEST(c == date);
} }
BOOST_AUTO_TEST_CASE(test_get_toml_local_time) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_time, value_type, test_value_types)
{ {
toml::value v1(toml::local_time{12, 30, 45}); value_type v1(toml::local_time{12, 30, 45});
const auto time = toml::get<std::chrono::seconds>(v1); const auto time = toml::get<std::chrono::seconds>(v1);
BOOST_CHECK(time == std::chrono::hours(12) + const bool result = time == std::chrono::hours(12) +
std::chrono::minutes(30) + std::chrono::seconds(45)); std::chrono::minutes(30) +
std::chrono::seconds(45);
BOOST_TEST(result);
} }
BOOST_AUTO_TEST_CASE(test_get_toml_local_datetime) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_datetime, value_type, test_value_types)
{ {
toml::value v1(toml::local_datetime( value_type v1(toml::local_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 45})); toml::local_time{12, 30, 45}));
@@ -333,13 +325,13 @@ BOOST_AUTO_TEST_CASE(test_get_toml_local_datetime)
t.tm_sec = 45; t.tm_sec = 45;
t.tm_isdst = -1; t.tm_isdst = -1;
const auto c = std::mktime(&t); const auto c = std::mktime(&t);
BOOST_CHECK_EQUAL(c, date); BOOST_TEST(c == date);
} }
BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types)
{ {
{ {
toml::value v1(toml::offset_datetime( value_type v1(toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0}, toml::local_time{12, 30, 0},
toml::time_offset{9, 0})); toml::time_offset{9, 0}));
@@ -351,18 +343,18 @@ BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime)
// get time_t as gmtime (2018-04-01T03:30:00Z) // get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_CHECK(tmp); BOOST_TEST(tmp);
const auto tm = *tmp; const auto tm = *tmp;
BOOST_CHECK_EQUAL(tm.tm_year + 1900, 2018); BOOST_TEST(tm.tm_year + 1900 == 2018);
BOOST_CHECK_EQUAL(tm.tm_mon + 1, 4); BOOST_TEST(tm.tm_mon + 1 == 4);
BOOST_CHECK_EQUAL(tm.tm_mday, 1); BOOST_TEST(tm.tm_mday == 1);
BOOST_CHECK_EQUAL(tm.tm_hour, 3); BOOST_TEST(tm.tm_hour == 3);
BOOST_CHECK_EQUAL(tm.tm_min, 30); BOOST_TEST(tm.tm_min == 30);
BOOST_CHECK_EQUAL(tm.tm_sec, 0); BOOST_TEST(tm.tm_sec == 0);
} }
{ {
toml::value v1(toml::offset_datetime( value_type v1(toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0}, toml::local_time{12, 30, 0},
toml::time_offset{-8, 0})); toml::time_offset{-8, 0}));
@@ -374,14 +366,14 @@ BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime)
// get time_t as gmtime (2018-04-01T03:30:00Z) // get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_CHECK(tmp); BOOST_TEST(tmp);
const auto tm = *tmp; const auto tm = *tmp;
BOOST_CHECK_EQUAL(tm.tm_year + 1900, 2018); BOOST_TEST(tm.tm_year + 1900 == 2018);
BOOST_CHECK_EQUAL(tm.tm_mon + 1, 4); BOOST_TEST(tm.tm_mon + 1 == 4);
BOOST_CHECK_EQUAL(tm.tm_mday, 1); BOOST_TEST(tm.tm_mday == 1);
BOOST_CHECK_EQUAL(tm.tm_hour, 20); BOOST_TEST(tm.tm_hour == 20);
BOOST_CHECK_EQUAL(tm.tm_min, 30); BOOST_TEST(tm.tm_min == 30);
BOOST_CHECK_EQUAL(tm.tm_sec, 0); BOOST_TEST(tm.tm_sec == 0);
} }
} }

360
tests/test_get_or.cpp Normal file
View File

@@ -0,0 +1,360 @@
#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>
#include <tuple>
#if __cplusplus >= 201703L
#include <string_view>
#endif
using test_value_types = std::tuple<
toml::value,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
namespace test
{
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Comp, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::map<Key, Value, Comp, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::unordered_map<Key, Value, Hash, Eq, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
} // test
#define TOML11_TEST_GET_OR_EXACT(toml_type, init_expr, opt_expr)\
{ \
using namespace test; \
const toml::toml_type init init_expr ; \
const toml::toml_type opt opt_expr ; \
const value_type v(init); \
BOOST_TEST(init != opt); \
BOOST_TEST(init == toml::get_or(v, opt)); \
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_exact, value_type, test_value_types)
{
TOML11_TEST_GET_OR_EXACT(boolean, ( true), (false))
TOML11_TEST_GET_OR_EXACT(integer, ( 42), ( 54))
TOML11_TEST_GET_OR_EXACT(floating, ( 3.14), ( 2.71))
TOML11_TEST_GET_OR_EXACT(string, ("foo"), ("bar"))
TOML11_TEST_GET_OR_EXACT(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_GET_OR_EXACT(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_GET_OR_EXACT(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
)
TOML11_TEST_GET_OR_EXACT(offset_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
)
{
const typename value_type::array_type init{1,2,3,4,5};
const typename value_type::array_type opt {6,7,8,9,10};
const value_type v(init);
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::get_or(v, opt));
}
{
const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
const value_type v(init);
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::get_or(v, opt));
}
}
#undef TOML11_TEST_GET_OR_EXACT
#define TOML11_TEST_GET_OR_MODIFY(toml_type, init_expr, opt_expr)\
{ \
using namespace test; \
const toml::toml_type init init_expr ; \
toml::toml_type opt1 opt_expr ; \
toml::toml_type opt2 opt_expr ; \
value_type v(init); \
BOOST_TEST(init != opt1); \
toml::get_or(v, opt2) = opt1; \
BOOST_TEST(opt1 == toml::get<toml::toml_type>(v)); \
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_modify, value_type, test_value_types)
{
TOML11_TEST_GET_OR_MODIFY(boolean, ( true), (false))
TOML11_TEST_GET_OR_MODIFY(integer, ( 42), ( 54))
TOML11_TEST_GET_OR_MODIFY(floating, ( 3.14), ( 2.71))
TOML11_TEST_GET_OR_MODIFY(string, ("foo"), ("bar"))
TOML11_TEST_GET_OR_MODIFY(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_GET_OR_MODIFY(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_GET_OR_MODIFY(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
)
TOML11_TEST_GET_OR_MODIFY(offset_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
)
{
typename value_type::array_type init{1,2,3,4,5};
typename value_type::array_type opt1{6,7,8,9,10};
typename value_type::array_type opt2{6,7,8,9,10};
BOOST_TEST(init != opt1);
value_type v(init);
toml::get_or(v, opt2) = opt1;
BOOST_TEST(opt1 == toml::get<typename value_type::array_type>(v));
}
{
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}};
typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}};
value_type v(init);
BOOST_TEST(init != opt1);
toml::get_or(v, opt2) = opt1;
BOOST_TEST(opt1 == toml::get<typename value_type::table_type>(v));
}
}
#undef TOML11_TEST_GET_OR_MODIFY
#define TOML11_TEST_GET_OR_FALLBACK(init_type, opt_type) \
{ \
using namespace test; \
value_type v(init_type); \
BOOST_TEST(opt_type == toml::get_or(v, opt_type));\
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_fallback, value_type, test_value_types)
{
const toml::boolean boolean (true);
const toml::integer integer (42);
const toml::floating floating (3.14);
const toml::string string ("foo");
const toml::local_time local_time (12, 30, 45);
const toml::local_date local_date (2019, toml::month_t::Apr, 1);
const toml::local_datetime local_datetime (
toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45));
const toml::offset_datetime offset_datetime(
toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45), toml::time_offset( 9, 0));
using array_type = typename value_type::array_type;
using table_type = typename value_type::table_type;
const array_type array{1, 2, 3, 4, 5};
const table_type table{{"key1", 42}, {"key2", "foo"}};
TOML11_TEST_GET_OR_FALLBACK(boolean, integer );
TOML11_TEST_GET_OR_FALLBACK(boolean, floating );
TOML11_TEST_GET_OR_FALLBACK(boolean, string );
TOML11_TEST_GET_OR_FALLBACK(boolean, local_time );
TOML11_TEST_GET_OR_FALLBACK(boolean, local_date );
TOML11_TEST_GET_OR_FALLBACK(boolean, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(boolean, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(boolean, array );
TOML11_TEST_GET_OR_FALLBACK(boolean, table );
TOML11_TEST_GET_OR_FALLBACK(integer, boolean );
TOML11_TEST_GET_OR_FALLBACK(integer, floating );
TOML11_TEST_GET_OR_FALLBACK(integer, string );
TOML11_TEST_GET_OR_FALLBACK(integer, local_time );
TOML11_TEST_GET_OR_FALLBACK(integer, local_date );
TOML11_TEST_GET_OR_FALLBACK(integer, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(integer, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(integer, array );
TOML11_TEST_GET_OR_FALLBACK(integer, table );
TOML11_TEST_GET_OR_FALLBACK(floating, boolean );
TOML11_TEST_GET_OR_FALLBACK(floating, integer );
TOML11_TEST_GET_OR_FALLBACK(floating, string );
TOML11_TEST_GET_OR_FALLBACK(floating, local_time );
TOML11_TEST_GET_OR_FALLBACK(floating, local_date );
TOML11_TEST_GET_OR_FALLBACK(floating, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(floating, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(floating, array );
TOML11_TEST_GET_OR_FALLBACK(floating, table );
TOML11_TEST_GET_OR_FALLBACK(string, boolean );
TOML11_TEST_GET_OR_FALLBACK(string, integer );
TOML11_TEST_GET_OR_FALLBACK(string, floating );
TOML11_TEST_GET_OR_FALLBACK(string, local_time );
TOML11_TEST_GET_OR_FALLBACK(string, local_date );
TOML11_TEST_GET_OR_FALLBACK(string, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(string, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(string, array );
TOML11_TEST_GET_OR_FALLBACK(string, table );
TOML11_TEST_GET_OR_FALLBACK(local_time, boolean );
TOML11_TEST_GET_OR_FALLBACK(local_time, integer );
TOML11_TEST_GET_OR_FALLBACK(local_time, floating );
TOML11_TEST_GET_OR_FALLBACK(local_time, string );
TOML11_TEST_GET_OR_FALLBACK(local_time, local_date );
TOML11_TEST_GET_OR_FALLBACK(local_time, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(local_time, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(local_time, array );
TOML11_TEST_GET_OR_FALLBACK(local_time, table );
TOML11_TEST_GET_OR_FALLBACK(local_date, boolean );
TOML11_TEST_GET_OR_FALLBACK(local_date, integer );
TOML11_TEST_GET_OR_FALLBACK(local_date, floating );
TOML11_TEST_GET_OR_FALLBACK(local_date, string );
TOML11_TEST_GET_OR_FALLBACK(local_date, local_time );
TOML11_TEST_GET_OR_FALLBACK(local_date, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(local_date, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(local_date, array );
TOML11_TEST_GET_OR_FALLBACK(local_date, table );
TOML11_TEST_GET_OR_FALLBACK(local_datetime, boolean );
TOML11_TEST_GET_OR_FALLBACK(local_datetime, integer );
TOML11_TEST_GET_OR_FALLBACK(local_datetime, floating );
TOML11_TEST_GET_OR_FALLBACK(local_datetime, string );
TOML11_TEST_GET_OR_FALLBACK(local_datetime, local_time );
TOML11_TEST_GET_OR_FALLBACK(local_datetime, local_date );
TOML11_TEST_GET_OR_FALLBACK(local_datetime, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(local_datetime, array );
TOML11_TEST_GET_OR_FALLBACK(local_datetime, table );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, boolean );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, integer );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, floating );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, string );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_time );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_date );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, array );
TOML11_TEST_GET_OR_FALLBACK(offset_datetime, table );
TOML11_TEST_GET_OR_FALLBACK(array, boolean );
TOML11_TEST_GET_OR_FALLBACK(array, integer );
TOML11_TEST_GET_OR_FALLBACK(array, floating );
TOML11_TEST_GET_OR_FALLBACK(array, string );
TOML11_TEST_GET_OR_FALLBACK(array, local_time );
TOML11_TEST_GET_OR_FALLBACK(array, local_date );
TOML11_TEST_GET_OR_FALLBACK(array, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(array, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(array, table );
TOML11_TEST_GET_OR_FALLBACK(table, boolean );
TOML11_TEST_GET_OR_FALLBACK(table, integer );
TOML11_TEST_GET_OR_FALLBACK(table, floating );
TOML11_TEST_GET_OR_FALLBACK(table, string );
TOML11_TEST_GET_OR_FALLBACK(table, local_time );
TOML11_TEST_GET_OR_FALLBACK(table, local_date );
TOML11_TEST_GET_OR_FALLBACK(table, local_datetime );
TOML11_TEST_GET_OR_FALLBACK(table, offset_datetime);
TOML11_TEST_GET_OR_FALLBACK(table, array );
}
#undef TOML11_TEST_GET_OR_FALLBACK
BOOST_AUTO_TEST_CASE(test_get_or_integer)
{
{
toml::value v1(42);
toml::value v2(3.14);
BOOST_TEST(42u == toml::get_or(v1, 0u));
BOOST_TEST(0u == toml::get_or(v2, 0u));
}
}
BOOST_AUTO_TEST_CASE(test_get_or_floating)
{
{
toml::value v1(42);
toml::value v2(3.14);
BOOST_TEST(2.71f == toml::get_or(v1, 2.71f));
BOOST_TEST(static_cast<float>(v2.as_floating()) == toml::get_or(v2, 2.71f));
}
}
BOOST_AUTO_TEST_CASE(test_get_or_string)
{
{
toml::value v1("foobar");
toml::value v2(42);
std::string s1("bazqux");
const std::string s2("bazqux");
BOOST_TEST("foobar" == toml::get_or(v1, s1));
BOOST_TEST("bazqux" == toml::get_or(v2, s1));
std::string& v1r = toml::get_or(v1, s1);
std::string& s1r = toml::get_or(v2, s1);
BOOST_TEST("foobar" == v1r);
BOOST_TEST("bazqux" == s1r);
BOOST_TEST("foobar" == toml::get_or(v1, s2));
BOOST_TEST("bazqux" == toml::get_or(v2, s2));
BOOST_TEST("foobar" == toml::get_or(v1, std::move(s1)));
BOOST_TEST("bazqux" == toml::get_or(v2, std::move(s1)));
}
{
toml::value v1("foobar");
toml::value v2(42);
BOOST_TEST("foobar" == toml::get_or(v1, "bazqux"));
BOOST_TEST("bazqux" == toml::get_or(v2, "bazqux"));
const char* lit = "bazqux";
BOOST_TEST("foobar" == toml::get_or(v1, lit));
BOOST_TEST("bazqux" == toml::get_or(v2, lit));
}
}

View File

@@ -1,254 +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_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);
}
}

View File

@@ -10,13 +10,13 @@ do { \
const std::string expected(expct); \ const std::string expected(expct); \
toml::detail::location<std::string> loc("test", token); \ toml::detail::location<std::string> loc("test", token); \
const auto result = lxr::invoke(loc); \ const auto result = lxr::invoke(loc); \
BOOST_CHECK(result.is_ok()); \ BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \ if(result.is_ok()){ \
const auto region = result.unwrap(); \ const auto region = result.unwrap(); \
BOOST_CHECK_EQUAL(region.str(), expected); \ BOOST_TEST(region.str() == expected); \
BOOST_CHECK_EQUAL(region.str().size(), expected.size()); \ BOOST_TEST(region.str().size() == expected.size()); \
BOOST_CHECK_EQUAL(static_cast<std::size_t>(std::distance( \ BOOST_TEST(static_cast<std::size_t>(std::distance( \
loc.begin(), loc.iter())), region.size()); \ loc.begin(), loc.iter())) == region.size()); \
} else { \ } else { \
std::cerr << "lexer failed with input `"; \ std::cerr << "lexer failed with input `"; \
std::cerr << token << "`. expected `" << expected << "`\n"; \ std::cerr << token << "`. expected `" << expected << "`\n"; \
@@ -30,6 +30,7 @@ do { \
const std::string token (tkn); \ const std::string token (tkn); \
toml::detail::location<std::string> loc("test", token); \ toml::detail::location<std::string> loc("test", token); \
const auto result = lxr::invoke(loc); \ const auto result = lxr::invoke(loc); \
BOOST_CHECK(result.is_err()); \ BOOST_TEST(result.is_err()); \
BOOST_CHECK(loc.begin() == loc.iter()); \ const bool loc_same = (loc.begin() == loc.iter()); \
BOOST_TEST(loc_same); \
} while(false); /**/ } while(false); /**/

View File

@@ -19,7 +19,7 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
b = "baz" b = "baz"
)"_toml; )"_toml;
BOOST_CHECK_EQUAL(r, v); BOOST_TEST(r == v);
} }
{ {
const toml::value r{ const toml::value r{
@@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
b = "baz" b = "baz"
)"_toml; )"_toml;
BOOST_CHECK_EQUAL(r, v); BOOST_TEST(r == v);
} }
{ {
const toml::value r{ const toml::value r{
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
b = "baz" b = "baz"
)"_toml; )"_toml;
BOOST_CHECK_EQUAL(r, v); BOOST_TEST(r == v);
} }
} }
@@ -57,31 +57,31 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
const toml::value v1 = u8"true"_toml; const toml::value v1 = u8"true"_toml;
const toml::value v2 = u8"false"_toml; const toml::value v2 = u8"false"_toml;
BOOST_CHECK(v1.is_boolean()); BOOST_TEST(v1.is_boolean());
BOOST_CHECK(v2.is_boolean()); BOOST_TEST(v2.is_boolean());
BOOST_CHECK(toml::get<bool>(v1)); BOOST_TEST(toml::get<bool>(v1));
BOOST_CHECK(!toml::get<bool>(v2)); BOOST_TEST(!toml::get<bool>(v2));
} }
{ {
const toml::value v1 = u8"123_456"_toml; const toml::value v1 = u8"123_456"_toml;
const toml::value v2 = u8"0b0010"_toml; const toml::value v2 = u8"0b0010"_toml;
const toml::value v3 = u8"0xDEADBEEF"_toml; const toml::value v3 = u8"0xDEADBEEF"_toml;
BOOST_CHECK(v1.is_integer()); BOOST_TEST(v1.is_integer());
BOOST_CHECK(v2.is_integer()); BOOST_TEST(v2.is_integer());
BOOST_CHECK(v3.is_integer()); BOOST_TEST(v3.is_integer());
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v1), 123456); BOOST_TEST(toml::get<toml::integer>(v1) == 123456);
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v2), 2); BOOST_TEST(toml::get<toml::integer>(v2) == 2);
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v3), 0xDEADBEEF); BOOST_TEST(toml::get<toml::integer>(v3) == 0xDEADBEEF);
} }
{ {
const toml::value v1 = u8"3.1415"_toml; const toml::value v1 = u8"3.1415"_toml;
const toml::value v2 = u8"6.02e+23"_toml; const toml::value v2 = u8"6.02e+23"_toml;
BOOST_CHECK(v1.is_float()); BOOST_TEST(v1.is_floating());
BOOST_CHECK(v2.is_float()); BOOST_TEST(v2.is_floating());
BOOST_CHECK_CLOSE(toml::get<double>(v1), 3.1415, 0.00001); BOOST_TEST(toml::get<double>(v1) == 3.1415, boost::test_tools::tolerance(0.00001));
BOOST_CHECK_CLOSE(toml::get<double>(v2), 6.02e23, 0.0001); BOOST_TEST(toml::get<double>(v2) == 6.02e23, boost::test_tools::tolerance(0.0001));
} }
{ {
const toml::value v1 = u8R"("foo")"_toml; const toml::value v1 = u8R"("foo")"_toml;
@@ -89,65 +89,74 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
const toml::value v3 = u8R"("""foo""")"_toml; const toml::value v3 = u8R"("""foo""")"_toml;
const toml::value v4 = u8R"('''foo''')"_toml; const toml::value v4 = u8R"('''foo''')"_toml;
BOOST_CHECK(v1.is_string()); BOOST_TEST(v1.is_string());
BOOST_CHECK(v2.is_string()); BOOST_TEST(v2.is_string());
BOOST_CHECK(v3.is_string()); BOOST_TEST(v3.is_string());
BOOST_CHECK(v4.is_string()); BOOST_TEST(v4.is_string());
BOOST_CHECK_EQUAL(toml::get<std::string>(v1), "foo"); BOOST_TEST(toml::get<std::string>(v1) == "foo");
BOOST_CHECK_EQUAL(toml::get<std::string>(v2), "foo"); BOOST_TEST(toml::get<std::string>(v2) == "foo");
BOOST_CHECK_EQUAL(toml::get<std::string>(v3), "foo"); BOOST_TEST(toml::get<std::string>(v3) == "foo");
BOOST_CHECK_EQUAL(toml::get<std::string>(v4), "foo"); BOOST_TEST(toml::get<std::string>(v4) == "foo");
} }
{
{ {
const toml::value v1 = u8R"([1,2,3])"_toml; const toml::value v1 = u8R"([1,2,3])"_toml;
BOOST_TEST(v1.is_array());
BOOST_CHECK(v1.is_array()); const bool result = (toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3});
BOOST_CHECK((toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3})); BOOST_TEST(result);
}
{
const toml::value v2 = u8R"([1,])"_toml; const toml::value v2 = u8R"([1,])"_toml;
BOOST_TEST(v2.is_array());
BOOST_CHECK(v2.is_array()); const bool result = (toml::get<std::vector<int>>(v2) == std::vector<int>{1});
BOOST_CHECK((toml::get<std::vector<int>>(v2) == std::vector<int>{1})); BOOST_TEST(result);
}
{
const toml::value v3 = u8R"([[1,]])"_toml; const toml::value v3 = u8R"([[1,]])"_toml;
BOOST_CHECK(v3.is_array()); BOOST_TEST(v3.is_array());
BOOST_CHECK((toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1})); const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1});
BOOST_TEST(result);
}
{
const toml::value v4 = u8R"([[1],])"_toml; const toml::value v4 = u8R"([[1],])"_toml;
BOOST_CHECK(v4.is_array()); BOOST_TEST(v4.is_array());
BOOST_CHECK((toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1})); const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1});
BOOST_TEST(result);
}
} }
{ {
const toml::value v1 = u8R"({a = 42})"_toml; const toml::value v1 = u8R"({a = 42})"_toml;
BOOST_CHECK(v1.is_table()); BOOST_TEST(v1.is_table());
BOOST_CHECK((toml::get<std::map<std::string,int>>(v1) == const bool result = toml::get<std::map<std::string,int>>(v1) ==
std::map<std::string,int>{{"a", 42}})); std::map<std::string,int>{{"a", 42}};
BOOST_TEST(result);
} }
{ {
const toml::value v1 = u8"1979-05-27"_toml; const toml::value v1 = u8"1979-05-27"_toml;
BOOST_CHECK(v1.is_local_date()); BOOST_TEST(v1.is_local_date());
BOOST_CHECK_EQUAL(toml::get<toml::local_date>(v1), BOOST_TEST(toml::get<toml::local_date>(v1) ==
toml::local_date(1979, toml::month_t::May, 27)); toml::local_date(1979, toml::month_t::May, 27));
} }
{ {
const toml::value v1 = u8"12:00:00"_toml; const toml::value v1 = u8"12:00:00"_toml;
BOOST_CHECK(v1.is_local_time()); BOOST_TEST(v1.is_local_time());
BOOST_CHECK(toml::get<std::chrono::hours>(v1) == std::chrono::hours(12)); const bool result = toml::get<std::chrono::hours>(v1) == std::chrono::hours(12);
BOOST_TEST(result);
} }
{ {
const toml::value v1 = u8"1979-05-27T07:32:00"_toml; const toml::value v1 = u8"1979-05-27T07:32:00"_toml;
BOOST_CHECK(v1.is_local_datetime()); BOOST_TEST(v1.is_local_datetime());
BOOST_CHECK_EQUAL(toml::get<toml::local_datetime>(v1), BOOST_TEST(toml::get<toml::local_datetime>(v1) ==
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0))); toml::local_time(7, 32, 0)));
} }
{ {
const toml::value v1 = "1979-05-27T07:32:00Z"_toml; const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
BOOST_CHECK(v1.is_offset_datetime()); BOOST_TEST(v1.is_offset_datetime());
BOOST_CHECK_EQUAL(toml::get<toml::offset_datetime>(v1), BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0))); toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
} }

View File

@@ -7,5 +7,5 @@ int main()
const std::string content("a = 0"); const std::string content("a = 0");
std::istringstream iss(content); std::istringstream iss(content);
const auto data = toml::parse(iss, "test_multiple_translation_unit.toml"); const auto data = toml::parse(iss, "test_multiple_translation_unit.toml");
return read_a(data); return read_a(toml::get<toml::table>(data));
} }

View File

@@ -1,4 +1,4 @@
#define BOOST_TEST_MODULE "parse_array_test" #define BOOST_TEST_MODULE "parse_array<toml::value>_test"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST #ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#else #else
@@ -13,118 +13,118 @@ using namespace detail;
BOOST_AUTO_TEST_CASE(test_oneline_array) BOOST_AUTO_TEST_CASE(test_oneline_array)
{ {
TOML11_TEST_PARSE_EQUAL(parse_array, "[]", array()); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[]", array());
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,1,4,1,5]", a);
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\"]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\", \"bar\", \"baz\"]", a);
} }
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5,]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,1,4,1,5,]", a);
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\",]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\", \"bar\", \"baz\",]", a);
} }
} }
BOOST_AUTO_TEST_CASE(test_oneline_array_value) BOOST_AUTO_TEST_CASE(test_oneline_array_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[]", toml::value(array())); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[]", toml::value(array()));
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); 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)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5]", toml::value(a));
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\"]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\", \"baz\"]", toml::value(a));
} }
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); 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)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5,]", toml::value(a));
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\",]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\", \"baz\",]", toml::value(a));
} }
} }
BOOST_AUTO_TEST_CASE(test_multiline_array) BOOST_AUTO_TEST_CASE(test_multiline_array)
{ {
TOML11_TEST_PARSE_EQUAL(parse_array, "[\n#comment\n]", array()); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\n#comment\n]", array());
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,\n1,\n4,\n1,\n5]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,\n1,\n4,\n1,\n5]", a);
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",\n\"bar\",\n\"baz\"]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
} }
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); 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); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", a);
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("b#r"); a[0] = toml::value("foo"); a[1] = toml::value("b#r");
a[2] = toml::value("b#z"); a[2] = toml::value("b#z");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a);
} }
} }
BOOST_AUTO_TEST_CASE(test_multiline_array_value) BOOST_AUTO_TEST_CASE(test_multiline_array_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\n#comment\n]", toml::value(array())); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\n#comment\n]", toml::value(array()));
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); 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)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,\n1,\n4,\n1,\n5]", toml::value(a));
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",\n\"bar\",\n\"baz\"]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n\"bar\",\n\"baz\"]", toml::value(a));
} }
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); 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)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", toml::value(a));
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("b#r"); a[0] = toml::value("foo"); a[1] = toml::value("b#r");
a[2] = toml::value("b#z"); 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)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", toml::value(a));
} }
} }

View File

@@ -1,8 +1,7 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <algorithm> #include <algorithm>
#include <toml/region.hpp> #include <toml.hpp>
#include <toml/result.hpp>
// some of the parsers returns not only a value but also a region. // some of the parsers returns not only a value but also a region.
#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \ #define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \
@@ -10,9 +9,9 @@ do { \
const std::string token(tkn); \ const std::string token(tkn); \
toml::detail::location<std::string> loc("test", token); \ toml::detail::location<std::string> loc("test", token); \
const auto result = psr(loc); \ const auto result = psr(loc); \
BOOST_CHECK(result.is_ok()); \ BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \ if(result.is_ok()){ \
BOOST_CHECK(result.unwrap().first == expct); \ BOOST_TEST(result.unwrap().first == expct); \
} else { \ } else { \
std::cerr << "parser " << #psr << " failed with input `"; \ std::cerr << "parser " << #psr << " failed with input `"; \
std::cerr << token << "`.\n"; \ std::cerr << token << "`.\n"; \
@@ -26,9 +25,9 @@ do { \
const std::string token(tkn); \ const std::string token(tkn); \
toml::detail::location<std::string> loc("test", token); \ toml::detail::location<std::string> loc("test", token); \
const auto result = psr(loc); \ const auto result = psr(loc); \
BOOST_CHECK(result.is_ok()); \ BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \ if(result.is_ok()){ \
BOOST_CHECK(result.unwrap() == expct); \ BOOST_TEST(result.unwrap() == expct); \
} else { \ } else { \
std::cerr << "parse_value failed with input `"; \ std::cerr << "parse_value failed with input `"; \
std::cerr << token << "`.\n"; \ std::cerr << token << "`.\n"; \

View File

@@ -19,6 +19,6 @@ BOOST_AUTO_TEST_CASE(test_boolean)
BOOST_AUTO_TEST_CASE(test_boolean_value) 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<toml::value>, "true", toml::value( true));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "false", toml::value(false)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "false", toml::value(false));
} }

View File

@@ -21,10 +21,10 @@ BOOST_AUTO_TEST_CASE(test_time)
BOOST_AUTO_TEST_CASE(test_time_value) 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<toml::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<toml::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<toml::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))); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00.999999", toml::value(toml::local_time(7, 32, 0, 999, 999)));
} }
BOOST_AUTO_TEST_CASE(test_date) BOOST_AUTO_TEST_CASE(test_date)
@@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(test_date)
} }
BOOST_AUTO_TEST_CASE(test_date_value) BOOST_AUTO_TEST_CASE(test_date_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27",
value(toml::local_date(1979, toml::month_t::May, 27))); value(toml::local_date(1979, toml::month_t::May, 27)));
} }
@@ -64,25 +64,25 @@ BOOST_AUTO_TEST_CASE(test_datetime)
BOOST_AUTO_TEST_CASE(test_datetime_value) BOOST_AUTO_TEST_CASE(test_datetime_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
} }
@@ -111,23 +111,23 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
BOOST_AUTO_TEST_CASE(test_offset_datetime_value) BOOST_AUTO_TEST_CASE(test_offset_datetime_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00Z", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); toml::local_time(7, 32, 0), toml::time_offset(0, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.99Z", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0))));
} }

View File

@@ -8,73 +8,69 @@
#include <toml.hpp> #include <toml.hpp>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <map>
#include <deque>
BOOST_AUTO_TEST_CASE(test_example) BOOST_AUTO_TEST_CASE(test_example)
{ {
const auto data = toml::parse("toml/tests/example.toml"); const auto data = toml::parse("toml/tests/example.toml");
BOOST_CHECK_EQUAL(toml::get<std::string>(data.at("title")), "TOML Example"); BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
toml::Table owner = toml::get<toml::Table>(data.at("owner")); const auto& owner = toml::find(data, "owner");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("name")), "Tom Preston-Werner"); BOOST_TEST(toml::find<std::string>(owner, "name") == "Tom Preston-Werner");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("organization")), "GitHub"); BOOST_TEST(toml::find<std::string>(owner, "organization") == "GitHub");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")), BOOST_TEST(toml::find<std::string>(owner, "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_TEST(toml::find<toml::offset_datetime>(owner, "dob") ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0))); toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
} }
toml::Table database = toml::get<toml::Table>(data.at("database")); const auto& database = toml::find(data, "database");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(database.at("server")), "192.168.1.1"); BOOST_TEST(toml::find<std::string>(database, "server") == "192.168.1.1");
const std::vector<int> expected_ports{8001, 8001, 8002}; const std::vector<int> expected_ports{8001, 8001, 8002};
BOOST_CHECK(toml::get<std::vector<int>>(database.at("ports")) == expected_ports); BOOST_CHECK(toml::find<std::vector<int>>(database, "ports") == expected_ports);
BOOST_CHECK_EQUAL(toml::get<int>(database.at("connection_max")), 5000); BOOST_TEST(toml::find<int >(database, "connection_max") == 5000);
BOOST_CHECK_EQUAL(toml::get<bool>(database.at("enabled")), true); BOOST_TEST(toml::find<bool>(database, "enabled") == true);
} }
toml::Table servers = toml::get<toml::Table>(data.at("servers")); const auto& servers = toml::find(data, "servers");
{ {
toml::Table alpha = toml::get<toml::Table>(servers.at("alpha")); toml::table alpha = toml::find<toml::table>(servers, "alpha");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("ip")), "10.0.0.1"); BOOST_TEST(toml::get<std::string>(alpha.at("ip")) == "10.0.0.1");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("dc")), "eqdc10"); BOOST_TEST(toml::get<std::string>(alpha.at("dc")) == "eqdc10");
toml::Table beta = toml::get<toml::Table>(servers.at("beta")); toml::table beta = toml::find<toml::table>(servers, "beta");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("ip")), "10.0.0.2"); BOOST_TEST(toml::get<std::string>(beta.at("ip")) == "10.0.0.2");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("dc")), "eqdc10"); BOOST_TEST(toml::get<std::string>(beta.at("dc")) == "eqdc10");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("country")), "\xE4\xB8\xAD\xE5\x9B\xBD"); BOOST_TEST(toml::get<std::string>(beta.at("country")) == "\xE4\xB8\xAD\xE5\x9B\xBD");
} }
toml::Table clients = toml::get<toml::Table>(data.at("clients")); const auto& clients = toml::find(data, "clients");
{ {
toml::Array clients_data = toml::get<toml::Array>(clients.at("data")); toml::array clients_data = toml::find<toml::array>(clients, "data");
std::vector<std::string> expected_name{"gamma", "delta"}; std::vector<std::string> expected_name{"gamma", "delta"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) == BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) == expected_name);
expected_name);
std::vector<int> expected_number{1, 2}; std::vector<int> expected_number{1, 2};
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == expected_number);
expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"}; std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients.at("hosts")) == BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") == expected_hosts);
expected_hosts);
} }
std::vector<toml::Table> products = std::vector<toml::table> products =
toml::get<std::vector<toml::Table>>(data.at("products")); toml::find<std::vector<toml::table>>(data, "products");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(0).at("name")), BOOST_TEST(toml::get<std::string>(products.at(0).at("name")) == "Hammer");
"Hammer"); BOOST_TEST(toml::get<std::int64_t>(products.at(0).at("sku")) == 738594937);
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(0).at("sku")),
738594937);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("name")), BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) == "Nail");
"Nail"); BOOST_TEST(toml::get<std::int64_t>(products.at(1).at("sku")) == 284758393);
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(1).at("sku")), BOOST_TEST(toml::get<std::string>(products.at(1).at("color")) == "gray");
284758393);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("color")),
"gray");
} }
} }
@@ -83,42 +79,194 @@ BOOST_AUTO_TEST_CASE(test_example_stream)
std::ifstream ifs("toml/tests/example.toml"); std::ifstream ifs("toml/tests/example.toml");
const auto data = toml::parse(ifs); const auto data = toml::parse(ifs);
BOOST_CHECK_EQUAL(toml::get<std::string>(data.at("title")), "TOML Example"); BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
toml::Table owner = toml::get<toml::Table>(data.at("owner")); const auto& owner = toml::find(data, "owner");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("name")), "Tom Preston-Werner"); BOOST_TEST(toml::find<std::string>(owner, "name") == "Tom Preston-Werner");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("organization")), "GitHub"); BOOST_TEST(toml::find<std::string>(owner, "organization") == "GitHub");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")), BOOST_TEST(toml::find<std::string>(owner, "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_TEST(toml::find<toml::offset_datetime>(owner, "dob") ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0))); toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
} }
toml::Table database = toml::get<toml::Table>(data.at("database")); const auto& database = toml::find(data, "database");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(database.at("server")), "192.168.1.1"); BOOST_TEST(toml::find<std::string>(database, "server") == "192.168.1.1");
const std::vector<int> expected_ports{8001, 8001, 8002}; const std::vector<int> expected_ports{8001, 8001, 8002};
BOOST_CHECK(toml::get<std::vector<int>>(database.at("ports")) == expected_ports); BOOST_CHECK(toml::find<std::vector<int>>(database, "ports") == expected_ports);
BOOST_CHECK_EQUAL(toml::get<int>(database.at("connection_max")), 5000); BOOST_TEST(toml::find<int >(database, "connection_max") == 5000);
BOOST_CHECK_EQUAL(toml::get<bool>(database.at("enabled")), true); BOOST_TEST(toml::find<bool>(database, "enabled") == true);
} }
toml::Table servers = toml::get<toml::Table>(data.at("servers")); const auto& servers = toml::find(data, "servers");
{ {
toml::Table alpha = toml::get<toml::Table>(servers.at("alpha")); toml::table alpha = toml::find<toml::table>(servers, "alpha");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("ip")), "10.0.0.1"); BOOST_TEST(toml::get<std::string>(alpha.at("ip")) == "10.0.0.1");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("dc")), "eqdc10"); BOOST_TEST(toml::get<std::string>(alpha.at("dc")) == "eqdc10");
toml::Table beta = toml::get<toml::Table>(servers.at("beta")); toml::table beta = toml::find<toml::table>(servers, "beta");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("ip")), "10.0.0.2"); BOOST_TEST(toml::get<std::string>(beta.at("ip")) == "10.0.0.2");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("dc")), "eqdc10"); BOOST_TEST(toml::get<std::string>(beta.at("dc")) == "eqdc10");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("country")), "\xE4\xB8\xAD\xE5\x9B\xBD"); BOOST_TEST(toml::get<std::string>(beta.at("country")) == "\xE4\xB8\xAD\xE5\x9B\xBD");
} }
toml::Table clients = toml::get<toml::Table>(data.at("clients")); const auto& clients = toml::find(data, "clients");
{ {
toml::Array clients_data = toml::get<toml::Array>(clients.at("data")); toml::array clients_data = toml::find<toml::array>(clients, "data");
std::vector<std::string> expected_name{"gamma", "delta"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) == expected_name);
std::vector<int> expected_number{1, 2};
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") == expected_hosts);
}
std::vector<toml::table> products =
toml::find<std::vector<toml::table>>(data, "products");
{
BOOST_TEST(toml::get<std::string>(products.at(0).at("name")) ==
"Hammer");
BOOST_TEST(toml::get<std::int64_t>(products.at(0).at("sku")) ==
738594937);
BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) ==
"Nail");
BOOST_TEST(toml::get<std::int64_t>(products.at(1).at("sku")) ==
284758393);
BOOST_TEST(toml::get<std::string>(products.at(1).at("color")) ==
"gray");
}
}
BOOST_AUTO_TEST_CASE(test_fruit)
{
const auto data = toml::parse("toml/tests/fruit.toml");
const auto blah = toml::find<toml::array>(toml::find(data, "fruit"), "blah");
BOOST_TEST(toml::find<std::string>(blah.at(0), "name") == "apple");
BOOST_TEST(toml::find<std::string>(blah.at(1), "name") == "banana");
{
const auto physical = toml::find(blah.at(0), "physical");
BOOST_TEST(toml::find<std::string>(physical, "color") == "red");
BOOST_TEST(toml::find<std::string>(physical, "shape") == "round");
}
{
const auto physical = toml::find(blah.at(1), "physical");
BOOST_TEST(toml::find<std::string>(physical, "color") == "yellow");
BOOST_TEST(toml::find<std::string>(physical, "shape") == "bent");
}
}
BOOST_AUTO_TEST_CASE(test_hard_example)
{
const auto data = toml::parse("toml/tests/hard_example.toml");
const auto the = toml::find(data, "the");
BOOST_TEST(toml::find<std::string>(the, "test_string") ==
"You'll hate me after this - #");
const auto hard = toml::find(the, "hard");
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::find<std::vector<std::string>>(hard, "test_array") ==
expected_the_hard_test_array);
const std::vector<std::string> expected_the_hard_test_array2{
"Test #11 ]proved that", "Experiment #9 was a success"};
BOOST_CHECK(toml::find<std::vector<std::string>>(hard, "test_array2") ==
expected_the_hard_test_array2);
BOOST_TEST(toml::find<std::string>(hard, "another_test_string") ==
" Same thing, but with a string #");
BOOST_TEST(toml::find<std::string>(hard, "harder_test_string") ==
" And when \"'s are in the string, along with # \"");
const auto bit = toml::find(hard, "bit#");
BOOST_TEST(toml::find<std::string>(bit, "what?") ==
"You don't think some user won't do that?");
const std::vector<std::string> expected_multi_line_array{"]"};
BOOST_CHECK(toml::find<std::vector<std::string>>(bit, "multi_line_array") ==
expected_multi_line_array);
}
BOOST_AUTO_TEST_CASE(test_hard_example_comment)
{
const auto data = toml::parse<toml::preserve_comments>("toml/tests/hard_example.toml");
const auto the = toml::find(data, "the");
BOOST_TEST(toml::find<std::string>(the, "test_string") ==
"You'll hate me after this - #");
const auto hard = toml::find(the, "hard");
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::find<std::vector<std::string>>(hard, "test_array") ==
expected_the_hard_test_array);
const std::vector<std::string> expected_the_hard_test_array2{
"Test #11 ]proved that", "Experiment #9 was a success"};
BOOST_CHECK(toml::find<std::vector<std::string>>(hard, "test_array2") ==
expected_the_hard_test_array2);
BOOST_TEST(toml::find<std::string>(hard, "another_test_string") ==
" Same thing, but with a string #");
BOOST_TEST(toml::find<std::string>(hard, "harder_test_string") ==
" And when \"'s are in the string, along with # \"");
const auto bit = toml::find(hard, "bit#");
BOOST_TEST(toml::find<std::string>(bit, "what?") ==
"You don't think some user won't do that?");
const std::vector<std::string> expected_multi_line_array{"]"};
BOOST_CHECK(toml::find<std::vector<std::string>>(bit, "multi_line_array") ==
expected_multi_line_array);
}
BOOST_AUTO_TEST_CASE(test_example_preserve_comment)
{
const auto data = toml::parse<toml::preserve_comments>("toml/tests/example.toml");
BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
const auto& owner = toml::find(data, "owner");
{
BOOST_TEST(toml::find<std::string>(owner, "name") == "Tom Preston-Werner");
BOOST_TEST(toml::find<std::string>(owner, "organization") == "GitHub");
BOOST_TEST(toml::find<std::string>(owner, "bio") ==
"GitHub Cofounder & CEO\nLikes tater tots and beer.");
BOOST_TEST(toml::find<toml::offset_datetime>(owner, "dob") ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
BOOST_TEST(toml::find(owner, "dob").comments().at(0) ==
" First class dates? Why not?");
}
const auto& database = toml::find(data, "database");
{
BOOST_TEST(toml::find<std::string>(database, "server") == "192.168.1.1");
const std::vector<int> expected_ports{8001, 8001, 8002};
BOOST_CHECK(toml::find<std::vector<int>>(database, "ports") == expected_ports);
BOOST_TEST(toml::find<int >(database, "connection_max") == 5000);
BOOST_TEST(toml::find<bool>(database, "enabled") == true);
}
const auto& servers = toml::find(data, "servers");
{
const auto& alpha = toml::find(servers, "alpha");
BOOST_TEST(alpha.comments().at(0) ==
" You can indent as you please. Tabs or spaces. TOML don't care.");
BOOST_TEST(toml::find<std::string>(alpha, "ip") == "10.0.0.1");
BOOST_TEST(toml::find<std::string>(alpha, "dc") == "eqdc10");
const auto& beta = toml::find(servers, "beta");
BOOST_TEST(toml::find<std::string>(beta, "ip") == "10.0.0.2");
BOOST_TEST(toml::find<std::string>(beta, "dc") == "eqdc10");
BOOST_TEST(toml::find<std::string>(beta, "country") ==
"\xE4\xB8\xAD\xE5\x9B\xBD");
BOOST_TEST(toml::find(beta, "country").comments().at(0) ==
" This should be parsed as UTF-8");
}
const auto& clients = toml::find(data, "clients");
{
BOOST_TEST(toml::find(clients, "data").comments().at(0) ==
" just an update to make sure parsers support it");
toml::array clients_data = toml::find<toml::array>(clients, "data");
std::vector<std::string> expected_name{"gamma", "delta"}; std::vector<std::string> expected_name{"gamma", "delta"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) == BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) ==
expected_name); expected_name);
@@ -126,73 +274,118 @@ BOOST_AUTO_TEST_CASE(test_example_stream)
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) ==
expected_number); expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"}; std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients.at("hosts")) == BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") ==
expected_hosts); expected_hosts);
BOOST_TEST(toml::find(clients, "hosts").comments().at(0) ==
" Line breaks are OK when inside arrays");
} }
std::vector<toml::Table> products = std::vector<toml::table> products =
toml::get<std::vector<toml::Table>>(data.at("products")); toml::find<std::vector<toml::table>>(data, "products");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(0).at("name")), BOOST_TEST(toml::get<std::string>(products.at(0).at("name")) ==
"Hammer"); "Hammer");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(0).at("sku")), BOOST_TEST(toml::get<std::int64_t>(products.at(0).at("sku")) ==
738594937); 738594937);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("name")), BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) ==
"Nail"); "Nail");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(1).at("sku")), BOOST_TEST(toml::get<std::int64_t>(products.at(1).at("sku")) ==
284758393); 284758393);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("color")), BOOST_TEST(toml::get<std::string>(products.at(1).at("color")) ==
"gray"); "gray");
} }
} }
BOOST_AUTO_TEST_CASE(test_example_preserve_stdmap_stddeque)
BOOST_AUTO_TEST_CASE(test_fruit)
{ {
const auto data = toml::parse("toml/tests/fruit.toml"); const auto data = toml::parse<toml::preserve_comments, std::map, std::deque
const auto blah = toml::get<std::vector<toml::Table>>( >("toml/tests/example.toml");
toml::get<toml::Table>(data.at("fruit")).at("blah"));
BOOST_CHECK_EQUAL(toml::get<std::string>(blah.at(0).at("name")), "apple"); static_assert(std::is_same<typename decltype(data)::table_type,
BOOST_CHECK_EQUAL(toml::get<std::string>(blah.at(1).at("name")), "banana"); std::map<toml::key, typename std::remove_cv<decltype(data)>::type>
>::value, "");
static_assert(std::is_same<typename decltype(data)::array_type,
std::deque<typename std::remove_cv<decltype(data)>::type>
>::value, "");
BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
const auto& owner = toml::find(data, "owner");
{ {
const auto physical = toml::get<toml::Table>(blah.at(0).at("physical")); BOOST_TEST(toml::find<std::string>(owner, "name") == "Tom Preston-Werner");
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("color")), "red"); BOOST_TEST(toml::find<std::string>(owner, "organization") == "GitHub");
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("shape")), "round"); BOOST_TEST(toml::find<std::string>(owner, "bio") ==
"GitHub Cofounder & CEO\nLikes tater tots and beer.");
BOOST_TEST(toml::find<toml::offset_datetime>(owner, "dob") ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
BOOST_TEST(toml::find(owner, "dob").comments().at(0) ==
" First class dates? Why not?");
} }
const auto& database = toml::find(data, "database");
{ {
const auto physical = toml::get<toml::Table>(blah.at(1).at("physical")); BOOST_TEST(toml::find<std::string>(database, "server") == "192.168.1.1");
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("color")), "yellow"); const std::vector<int> expected_ports{8001, 8001, 8002};
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("shape")), "bent"); BOOST_CHECK(toml::find<std::vector<int>>(database, "ports") == expected_ports);
BOOST_TEST(toml::find<int >(database, "connection_max") == 5000);
BOOST_TEST(toml::find<bool>(database, "enabled") == true);
} }
}
BOOST_AUTO_TEST_CASE(test_hard_example) const auto& servers = toml::find(data, "servers");
{ {
const auto data = toml::parse("toml/tests/hard_example.toml"); const auto& alpha = toml::find(servers, "alpha");
const auto the = toml::get<toml::Table>(data.at("the")); BOOST_TEST(alpha.comments().at(0) ==
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")), " You can indent as you please. Tabs or spaces. TOML don't care.");
"You'll hate me after this - #"); BOOST_TEST(toml::find<std::string>(alpha, "ip") == "10.0.0.1");
BOOST_TEST(toml::find<std::string>(alpha, "dc") == "eqdc10");
const auto hard = toml::get<toml::Table>(the.at("hard")); const auto& beta = toml::find(servers, "beta");
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "}; BOOST_TEST(toml::find<std::string>(beta, "ip") == "10.0.0.2");
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) == BOOST_TEST(toml::find<std::string>(beta, "dc") == "eqdc10");
expected_the_hard_test_array); BOOST_TEST(toml::find<std::string>(beta, "country") ==
const std::vector<std::string> expected_the_hard_test_array2{ "\xE4\xB8\xAD\xE5\x9B\xBD");
"Test #11 ]proved that", "Experiment #9 was a success"}; BOOST_TEST(toml::find(beta, "country").comments().at(0) ==
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) == " This should be parsed as UTF-8");
expected_the_hard_test_array2); }
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("another_test_string")),
" Same thing, but with a string #");
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("harder_test_string")),
" And when \"'s are in the string, along with # \"");
const auto bit = toml::get<toml::Table>(hard.at("bit#")); const auto& clients = toml::find(data, "clients");
BOOST_CHECK_EQUAL(toml::get<std::string>(bit.at("what?")), {
"You don't think some user won't do that?"); BOOST_TEST(toml::find(clients, "data").comments().at(0) ==
const std::vector<std::string> expected_multi_line_array{"]"}; " just an update to make sure parsers support it");
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
expected_multi_line_array);
toml::array clients_data = toml::find<toml::array>(clients, "data");
std::vector<std::string> expected_name{"gamma", "delta"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) ==
expected_name);
std::vector<int> expected_number{1, 2};
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) ==
expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") ==
expected_hosts);
BOOST_TEST(toml::find(clients, "hosts").comments().at(0) ==
" Line breaks are OK when inside arrays");
}
std::vector<toml::table> products =
toml::find<std::vector<toml::table>>(data, "products");
{
BOOST_TEST(toml::get<std::string>(products.at(0).at("name")) ==
"Hammer");
BOOST_TEST(toml::get<std::int64_t>(products.at(0).at("sku")) ==
738594937);
BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) ==
"Nail");
BOOST_TEST(toml::get<std::int64_t>(products.at(1).at("sku")) ==
284758393);
BOOST_TEST(toml::get<std::string>(products.at(1).at("color")) ==
"gray");
}
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -210,8 +403,8 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
std::istringstream iss(table); std::istringstream iss(table);
const auto data = toml::parse(iss, "test_file_with_BOM.toml"); const auto data = toml::parse(iss, "test_file_with_BOM.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -226,8 +419,8 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
} }
const auto data = toml::parse("tmp.toml"); const auto data = toml::parse("tmp.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -239,8 +432,8 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
std::istringstream iss(table); std::istringstream iss(table);
const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml"); const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -254,12 +447,12 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
// value will be "\r\r\n". To avoid the additional "\r", use binary // value will be "\r\r\n". To avoid the additional "\r", use binary
// mode. // mode.
std::ofstream ofs("tmp.toml", std::ios_base::binary); std::ofstream ofs("tmp.toml", std::ios_base::binary);
ofs.write(table.data(), table.size()); ofs.write(table.data(), static_cast<std::streamsize>(table.size()));
} }
const auto data = toml::parse("tmp.toml"); const auto data = toml::parse("tmp.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
} }
@@ -275,8 +468,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file.toml"); "test_file_without_newline_at_the_end_of_file.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -288,8 +481,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_CRLF.toml"); "test_file_without_newline_at_the_end_of_file_CRLF.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
@@ -302,8 +495,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_comment.toml"); "test_file_without_newline_at_the_end_of_file_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -315,8 +508,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_comment.toml"); "test_file_without_newline_at_the_end_of_file_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
@@ -329,8 +522,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_ws.toml"); "test_file_without_newline_at_the_end_of_file_ws.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -342,8 +535,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_ws.toml"); "test_file_without_newline_at_the_end_of_file_ws.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
} }
@@ -362,8 +555,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -377,8 +570,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// comment w/ newline // comment w/ newline
@@ -394,8 +587,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -409,8 +602,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// CRLF version // CRLF version
@@ -426,8 +619,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -441,8 +634,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -455,8 +648,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -470,8 +663,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
} }
@@ -489,8 +682,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -504,8 +697,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// with whitespaces // with whitespaces
@@ -521,8 +714,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -536,8 +729,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -551,8 +744,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -566,8 +759,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// with whitespaces but no newline // with whitespaces but no newline
@@ -582,8 +775,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
@@ -600,8 +793,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -615,8 +808,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// with whitespaces // with whitespaces
@@ -632,8 +825,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -647,8 +840,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -662,8 +855,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -677,8 +870,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -691,7 +884,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
} }

View File

@@ -32,20 +32,20 @@ BOOST_AUTO_TEST_CASE(test_fractional)
BOOST_AUTO_TEST_CASE(test_fractional_value) 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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::value>, "+0.0", value( 0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0.0", value(-0.0)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0.0", value(-0.0));
} }
BOOST_AUTO_TEST_CASE(test_exponential) BOOST_AUTO_TEST_CASE(test_exponential)
@@ -72,24 +72,24 @@ BOOST_AUTO_TEST_CASE(test_exponential)
BOOST_AUTO_TEST_CASE(test_exponential_value) BOOST_AUTO_TEST_CASE(test_exponential_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e+10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e-10", value(1e-10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e+10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e-10", value(1e-10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e10", value(-1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e+10", value(-1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e+10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e-10", value(-1e-10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::value>, "123e-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E+10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E-10", value(1e-10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::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<toml::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<toml::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<toml::value>, "+0e0", value( 0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0e0", value(-0.0)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0e0", value(-0.0));
} }
BOOST_AUTO_TEST_CASE(test_fe) BOOST_AUTO_TEST_CASE(test_fe)
{ {
@@ -99,9 +99,9 @@ BOOST_AUTO_TEST_CASE(test_fe)
} }
BOOST_AUTO_TEST_CASE(test_fe_vaule) 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<toml::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<toml::value>, "6.02e+23", value(6.02e23));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1.112_650_06e-17", value(1.11265006e-17)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.112_650_06e-17", value(1.11265006e-17));
} }
BOOST_AUTO_TEST_CASE(test_inf) BOOST_AUTO_TEST_CASE(test_inf)

View File

@@ -13,36 +13,36 @@ using namespace detail;
BOOST_AUTO_TEST_CASE(test_inline_table) BOOST_AUTO_TEST_CASE(test_inline_table)
{ {
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{}", table()); TOML11_TEST_PARSE_EQUAL(parse_inline_table<toml::value>, "{}", table());
{ {
table t; table t;
t["foo"] = toml::value(42); t["foo"] = toml::value(42);
t["bar"] = toml::value("baz"); t["bar"] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{foo = 42, bar = \"baz\"}", t); TOML11_TEST_PARSE_EQUAL(parse_inline_table<toml::value>, "{foo = 42, bar = \"baz\"}", t);
} }
{ {
table t; table t;
table t_sub; table t_sub;
t_sub["name"] = toml::value("pug"); t_sub["name"] = toml::value("pug");
t["type"] = toml::value(t_sub); t["type"] = toml::value(t_sub);
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{type.name = \"pug\"}", t); TOML11_TEST_PARSE_EQUAL(parse_inline_table<toml::value>, "{type.name = \"pug\"}", t);
} }
} }
BOOST_AUTO_TEST_CASE(test_inline_table_value) BOOST_AUTO_TEST_CASE(test_inline_table_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{}", value(table())); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{}", value(table()));
{ {
table t; table t;
t["foo"] = toml::value(42); t["foo"] = toml::value(42);
t["bar"] = toml::value("baz"); t["bar"] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{foo = 42, bar = \"baz\"}", value(t)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{foo = 42, bar = \"baz\"}", value(t));
} }
{ {
table t; table t;
table t_sub; table t_sub;
t_sub["name"] = toml::value("pug"); t_sub["name"] = toml::value("pug");
t["type"] = toml::value(t_sub); t["type"] = toml::value(t_sub);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{type.name = \"pug\"}", value(t)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{type.name = \"pug\"}", value(t));
} }
} }

View File

@@ -25,14 +25,14 @@ BOOST_AUTO_TEST_CASE(test_decimal)
BOOST_AUTO_TEST_CASE(test_decimal_value) 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<toml::value>, "1234", toml::value( 1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1234", toml::value( 1234)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1234", toml::value( 1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1234", toml::value( -1234)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1234", toml::value( -1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0", toml::value( 0)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::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<toml::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<toml::value>, "-1_2_3_4", toml::value( -1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123_456_789", toml::value(123456789)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123_456_789", toml::value(123456789));
} }
BOOST_AUTO_TEST_CASE(test_hex) BOOST_AUTO_TEST_CASE(test_hex)
@@ -50,15 +50,15 @@ BOOST_AUTO_TEST_CASE(test_hex)
BOOST_AUTO_TEST_CASE(test_hex_value) BOOST_AUTO_TEST_CASE(test_hex_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADBEEF", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADBEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdeadbeef", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdeadbeef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADbeef", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADbeef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEAD_BEEF", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEAD_BEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_beef", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdead_beef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_BEEF", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdead_BEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xFF", value(0xFF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xFF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x00FF", value(0xFF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x00FF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x0000FF", value(0xFF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x0000FF", value(0xFF));
} }
BOOST_AUTO_TEST_CASE(test_oct) BOOST_AUTO_TEST_CASE(test_oct)
@@ -70,9 +70,9 @@ BOOST_AUTO_TEST_CASE(test_oct)
BOOST_AUTO_TEST_CASE(test_oct_value) 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<toml::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<toml::value>, "0o7_7_7", value(64*7+8*7+7));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o007", value(7)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o007", value(7));
} }
BOOST_AUTO_TEST_CASE(test_bin) BOOST_AUTO_TEST_CASE(test_bin)
@@ -85,8 +85,8 @@ BOOST_AUTO_TEST_CASE(test_bin)
BOOST_AUTO_TEST_CASE(test_bin_value) BOOST_AUTO_TEST_CASE(test_bin_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b10000", value(16)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b10000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b010000", value(16)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b010000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b01_00_00", value(16)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b01_00_00", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b111111", value(63)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b111111", value(63));
} }

View File

@@ -29,16 +29,16 @@ BOOST_AUTO_TEST_CASE(test_string)
BOOST_AUTO_TEST_CASE(test_string_value) BOOST_AUTO_TEST_CASE(test_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"The quick brown fox jumps over the lazy dog\"", "\"The quick brown fox jumps over the lazy dog\"",
toml::value("The quick brown fox jumps over the lazy dog", string_t::basic)); toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\'The quick brown fox jumps over the lazy dog\'", "\'The quick brown fox jumps over the lazy dog\'",
toml::value("The quick brown fox jumps over the lazy dog", string_t::literal)); toml::value("The quick brown fox jumps over the lazy dog", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"", "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
toml::value("The quick brown fox jumps over the lazy dog", string_t::basic)); toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'''The quick brown fox \njumps over the lazy dog'''", "'''The quick brown fox \njumps over the lazy dog'''",
toml::value("The quick brown fox \njumps over the lazy dog", string_t::literal)); toml::value("The quick brown fox \njumps over the lazy dog", string_t::literal));
} }
@@ -73,25 +73,25 @@ BOOST_AUTO_TEST_CASE(test_basic_string)
BOOST_AUTO_TEST_CASE(test_basic_string_value) BOOST_AUTO_TEST_CASE(test_basic_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"", "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic)); value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"192.168.1.1\"", "\"192.168.1.1\"",
value("192.168.1.1", string_t::basic)); value("192.168.1.1", string_t::basic));
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"", "\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic)); value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic));
#else #else
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"中国\"", "\"中国\"",
value("中国", string_t::basic)); value("中国", string_t::basic));
#endif #endif
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"You'll hate me after this - #\"", "\"You'll hate me after this - #\"",
value("You'll hate me after this - #", string_t::basic)); value("You'll hate me after this - #", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\" And when \\\"'s are in the along with # \\\"\"", "\" And when \\\"'s are in the along with # \\\"\"",
value(" And when \"'s are in the along with # \"", string_t::basic)); value(" And when \"'s are in the along with # \"", string_t::basic));
} }
@@ -108,10 +108,10 @@ BOOST_AUTO_TEST_CASE(test_ml_basic_string)
BOOST_AUTO_TEST_CASE(test_ml_basic_string_value) BOOST_AUTO_TEST_CASE(test_ml_basic_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"", "\"\"\"\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)); value("The quick brown fox jumps over the lazy dog.", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\"\"\\\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 \"\"\"",
value("The quick brown fox jumps over the lazy dog.", string_t::basic)); value("The quick brown fox jumps over the lazy dog.", string_t::basic));
} }
@@ -134,16 +134,16 @@ BOOST_AUTO_TEST_CASE(test_literal_string)
BOOST_AUTO_TEST_CASE(test_literal_string_value) BOOST_AUTO_TEST_CASE(test_literal_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'C:\\Users\\nodejs\\templates'", "'C:\\Users\\nodejs\\templates'",
value("C:\\Users\\nodejs\\templates", string_t::literal)); value("C:\\Users\\nodejs\\templates", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'\\\\ServerX\\admin$\\system32\\'", "'\\\\ServerX\\admin$\\system32\\'",
value("\\\\ServerX\\admin$\\system32\\", string_t::literal)); value("\\\\ServerX\\admin$\\system32\\", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'Tom \"Dubs\" Preston-Werner'", "'Tom \"Dubs\" Preston-Werner'",
value("Tom \"Dubs\" Preston-Werner", string_t::literal)); value("Tom \"Dubs\" Preston-Werner", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'<\\i\\c*\\s*>'", "'<\\i\\c*\\s*>'",
value("<\\i\\c*\\s*>", string_t::literal)); value("<\\i\\c*\\s*>", string_t::literal));
} }
@@ -160,10 +160,10 @@ BOOST_AUTO_TEST_CASE(test_ml_literal_string)
BOOST_AUTO_TEST_CASE(test_ml_literal_string_value) BOOST_AUTO_TEST_CASE(test_ml_literal_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'''I [dw]on't need \\d{2} apples'''", "'''I [dw]on't need \\d{2} apples'''",
value("I [dw]on't need \\d{2} apples", string_t::literal)); value("I [dw]on't need \\d{2} apples", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'''\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'''",
value("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal)); value("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal));
} }

View File

@@ -21,13 +21,13 @@ BOOST_AUTO_TEST_CASE(test_normal_table)
); );
location<std::string> loc("test", table); location<std::string> loc("test", table);
const auto result = toml::detail::parse_ml_table(loc); const auto result = toml::detail::parse_ml_table<toml::value>(loc);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
const auto data = result.unwrap(); const auto data = result.unwrap();
BOOST_CHECK_EQUAL(toml::get<std::string >(data.at("key1")), "value"); BOOST_TEST(toml::get<std::string >(data.at("key1")) == "value");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(data.at("key2")), 42); BOOST_TEST(toml::get<std::int64_t>(data.at("key2")) == 42);
BOOST_CHECK_EQUAL(toml::get<double >(data.at("key3")), 3.14); BOOST_TEST(toml::get<double >(data.at("key3")) == 3.14);
} }
BOOST_AUTO_TEST_CASE(test_nested_table) BOOST_AUTO_TEST_CASE(test_nested_table)
@@ -38,13 +38,13 @@ BOOST_AUTO_TEST_CASE(test_nested_table)
); );
location<std::string> loc("test", table); location<std::string> loc("test", table);
const auto result = toml::detail::parse_ml_table(loc); const auto result = toml::detail::parse_ml_table<toml::value>(loc);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
const auto data = result.unwrap(); const auto data = result.unwrap();
const auto a = toml::get<toml::table>(data.at("a")); const auto a = toml::get<toml::table>(data.at("a"));
const auto c = toml::get<toml::table>(a.at("c")); const auto c = toml::get<toml::table>(a.at("c"));
BOOST_CHECK_EQUAL(toml::get<std::string >(a.at("b")), "value"); BOOST_TEST(toml::get<std::string >(a.at("b")) == "value");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(c.at("d")), 42); BOOST_TEST(toml::get<std::int64_t>(c.at("d")) == 42);
} }

View File

@@ -14,11 +14,11 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
{ {
const auto data = toml::parse("toml/tests/hard_example_unicode.toml"); const auto data = toml::parse("toml/tests/hard_example_unicode.toml");
const auto the = toml::get<toml::Table>(data.at("the")); const auto the = toml::find<toml::table>(data, "the");
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")), BOOST_TEST(toml::get<std::string>(the.at("test_string")) ==
std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x27\xE2\x84\x93\xE2\x84\x93\x20\xCE\xBB\xC3\xA1\xC6\xAD\xC3\xA8\x20\xE2\x82\xA5\xC3\xA8\x20\xC3\xA1\xC6\x92\xC6\xAD\xC3\xA8\xC5\x99\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC6\xA8\x20\x2D\x20\x23")); std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x27\xE2\x84\x93\xE2\x84\x93\x20\xCE\xBB\xC3\xA1\xC6\xAD\xC3\xA8\x20\xE2\x82\xA5\xC3\xA8\x20\xC3\xA1\xC6\x92\xC6\xAD\xC3\xA8\xC5\x99\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC6\xA8\x20\x2D\x20\x23"));
const auto hard = toml::get<toml::Table>(the.at("hard")); const auto hard = toml::get<toml::table>(the.at("hard"));
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "}; const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) == BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) ==
expected_the_hard_test_array); expected_the_hard_test_array);
@@ -28,13 +28,13 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
}; };
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) == BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) ==
expected_the_hard_test_array2); expected_the_hard_test_array2);
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("another_test_string")), BOOST_TEST(toml::get<std::string>(hard.at("another_test_string")) ==
std::string("\xC2\xA7\xC3\xA1\xE2\x82\xA5\xC3\xA8\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xCE\xB2\xC3\xBA\xC6\xAD\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\xC3\xA1\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x20\x23")); std::string("\xC2\xA7\xC3\xA1\xE2\x82\xA5\xC3\xA8\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xCE\xB2\xC3\xBA\xC6\xAD\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\xC3\xA1\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x20\x23"));
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("harder_test_string")), BOOST_TEST(toml::get<std::string>(hard.at("harder_test_string")) ==
std::string("\x20\xC3\x82\xC3\xB1\xCE\xB4\x20\xCF\x89\xCE\xBB\xC3\xA8\xC3\xB1\x20\x22\x27\xC6\xA8\x20\xC3\xA1\xC5\x99\xC3\xA8\x20\xC3\xAF\xC3\xB1\x20\xC6\xAD\xCE\xBB\xC3\xA8\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xC3\xA1\xE2\x84\x93\xC3\xB4\xC3\xB1\xCF\xB1\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\x23\x20\x22")); std::string("\x20\xC3\x82\xC3\xB1\xCE\xB4\x20\xCF\x89\xCE\xBB\xC3\xA8\xC3\xB1\x20\x22\x27\xC6\xA8\x20\xC3\xA1\xC5\x99\xC3\xA8\x20\xC3\xAF\xC3\xB1\x20\xC6\xAD\xCE\xBB\xC3\xA8\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xC3\xA1\xE2\x84\x93\xC3\xB4\xC3\xB1\xCF\xB1\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\x23\x20\x22"));
// //
const auto bit = toml::get<toml::Table>(hard.at(std::string("\xCE\xB2\xC3\xAF\xC6\xAD\x23"))); const auto bit = toml::get<toml::table>(hard.at(std::string("\xCE\xB2\xC3\xAF\xC6\xAD\x23")));
BOOST_CHECK_EQUAL(toml::get<std::string>(bit.at(std::string("\xCF\x89\xCE\xBB\xC3\xA1\xC6\xAD\x3F"))), BOOST_TEST(toml::get<std::string>(bit.at(std::string("\xCF\x89\xCE\xBB\xC3\xA1\xC6\xAD\x3F"))) ==
std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x20\xCE\xB4\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xC6\x99\x20\xC6\xA8\xC3\xB4\xE2\x82\xA5\xC3\xA8\x20\xC3\xBA\xC6\xA8\xC3\xA8\xC5\x99\x20\xCF\x89\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xCE\xB4\xC3\xB4\x20\xC6\xAD\xCE\xBB\xC3\xA1\xC6\xAD\x3F")); std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x20\xCE\xB4\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xC6\x99\x20\xC6\xA8\xC3\xB4\xE2\x82\xA5\xC3\xA8\x20\xC3\xBA\xC6\xA8\xC3\xA8\xC5\x99\x20\xCF\x89\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xCE\xB4\xC3\xB4\x20\xC6\xAD\xCE\xBB\xC3\xA1\xC6\xAD\x3F"));
const std::vector<std::string> expected_multi_line_array{"]"}; const std::vector<std::string> expected_multi_line_array{"]"};
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")) ==
@@ -45,11 +45,11 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
{ {
const auto data = toml::parse("toml/tests/hard_example_unicode.toml"); const auto data = toml::parse("toml/tests/hard_example_unicode.toml");
const auto the = toml::get<toml::Table>(data.at("the")); const auto the = toml::find<toml::table>(data, "the");
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")), BOOST_TEST(toml::get<std::string>(the.at("test_string")) ==
std::string(u8"Ýôú' λáƭè ₥è áƒƭèř ƭλïƨ - #")); std::string(u8"Ýôú' λáƭè ₥è áƒƭèř ƭλïƨ - #"));
const auto hard = toml::get<toml::Table>(the.at("hard")); const auto hard = toml::get<toml::table>(the.at("hard"));
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "}; const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) == BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) ==
expected_the_hard_test_array); expected_the_hard_test_array);
@@ -58,13 +58,13 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
std::string(u8"Éжƥèřï₥èñƭ #9 ωáƨ á ƨúççèƨƨ")}; std::string(u8"Éжƥèřï₥èñƭ #9 ωáƨ á ƨúççèƨƨ")};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) == BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) ==
expected_the_hard_test_array2); expected_the_hard_test_array2);
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("another_test_string")), BOOST_TEST(toml::get<std::string>(hard.at("another_test_string")) ==
std::string(u8"§á₥è ƭλïñϱ, βúƭ ωïƭλ á ƨƭřïñϱ #")); std::string(u8"§á₥è ƭλïñϱ, βúƭ ωïƭλ á ƨƭřïñϱ #"));
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("harder_test_string")), BOOST_TEST(toml::get<std::string>(hard.at("harder_test_string")) ==
std::string(u8" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \"")); std::string(u8" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \""));
const auto bit = toml::get<toml::Table>(hard.at(std::string(u8"βïƭ#"))); const auto bit = toml::get<toml::table>(hard.at(std::string(u8"βïƭ#")));
BOOST_CHECK_EQUAL(toml::get<std::string>(bit.at(std::string(u8"ωλáƭ?"))), BOOST_TEST(toml::get<std::string>(bit.at(std::string(u8"ωλáƭ?"))) ==
std::string(u8"Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?")); std::string(u8"Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?"));
const std::vector<std::string> expected_multi_line_array{"]"}; const std::vector<std::string> expected_multi_line_array{"]"};
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")) ==

View File

@@ -8,49 +8,49 @@ BOOST_AUTO_TEST_CASE(test_construct)
{ {
auto s = toml::ok(42); auto s = toml::ok(42);
toml::result<int, std::string> result(s); toml::result<int, std::string> result(s);
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
const auto s = toml::ok(42); const auto s = toml::ok(42);
toml::result<int, std::string> result(s); toml::result<int, std::string> result(s);
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::ok(42)); toml::result<int, std::string> result(toml::ok(42));
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
auto f = toml::err<std::string>("foobar"); auto f = toml::err<std::string>("foobar");
toml::result<int, std::string> result(f); toml::result<int, std::string> result(f);
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar"); BOOST_TEST(result.unwrap_err() == "foobar");
} }
{ {
const auto f = toml::err<std::string>("foobar"); const auto f = toml::err<std::string>("foobar");
toml::result<int, std::string> result(f); toml::result<int, std::string> result(f);
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar"); BOOST_TEST(result.unwrap_err() == "foobar");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar"); BOOST_TEST(result.unwrap_err() == "foobar");
} }
} }
@@ -59,54 +59,54 @@ BOOST_AUTO_TEST_CASE(test_assignment)
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
result = toml::ok(42); result = toml::ok(42);
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
auto s = toml::ok(42); auto s = toml::ok(42);
result = s; result = s;
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
const auto s = toml::ok(42); const auto s = toml::ok(42);
result = s; result = s;
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
result = toml::err<std::string>("hoge"); result = toml::err<std::string>("hoge");
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge"); BOOST_TEST(result.unwrap_err() == "hoge");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
auto f = toml::err<std::string>("hoge"); auto f = toml::err<std::string>("hoge");
result = f; result = f;
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge"); BOOST_TEST(result.unwrap_err() == "hoge");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
const auto f = toml::err<std::string>("hoge"); const auto f = toml::err<std::string>("hoge");
result = f; result = f;
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge"); BOOST_TEST(result.unwrap_err() == "hoge");
} }
} }
@@ -119,10 +119,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return i * 2; return i * 2;
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2); BOOST_TEST(mapped.unwrap() == 42 * 2);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -132,10 +132,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return *i; return *i;
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42); BOOST_TEST(mapped.unwrap() == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -144,10 +144,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return i * 2; return i * 2;
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -157,10 +157,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return *i; return *i;
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
} }
@@ -173,10 +173,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return s + s; return s + s;
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42); BOOST_TEST(mapped.unwrap() == 42);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -186,10 +186,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return s + s; return s + s;
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(*(mapped.unwrap()), 42); BOOST_TEST(*(mapped.unwrap()) == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -197,10 +197,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
[](const std::string s) -> std::string { [](const std::string s) -> std::string {
return s + s; return s + s;
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge"); BOOST_TEST(mapped.unwrap_err() == "hogehoge");
} }
{ {
toml::result<int, std::unique_ptr<std::string>> toml::result<int, std::unique_ptr<std::string>>
@@ -210,10 +210,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return *p; return *p;
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
} }
@@ -226,7 +226,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return i * 2; return i * 2;
}, 54); }, 54);
BOOST_CHECK_EQUAL(mapped, 42 * 2); BOOST_TEST(mapped == 42 * 2);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return *i; return *i;
}, 54); }, 54);
BOOST_CHECK_EQUAL(mapped, 42); BOOST_TEST(mapped == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return i * 2; return i * 2;
}, 54); }, 54);
BOOST_CHECK_EQUAL(mapped, 54); BOOST_TEST(mapped == 54);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -255,7 +255,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return *i; return *i;
}, 54); }, 54);
BOOST_CHECK_EQUAL(mapped, 54); BOOST_TEST(mapped == 54);
} }
} }
@@ -268,7 +268,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i; return i + i;
}, "foobar"); }, "foobar");
BOOST_CHECK_EQUAL(mapped, "foobar"); BOOST_TEST(mapped == "foobar");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i; return i + i;
}, "foobar"); }, "foobar");
BOOST_CHECK_EQUAL(mapped, "foobar"); BOOST_TEST(mapped == "foobar");
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i; return i + i;
}, "foobar"); }, "foobar");
BOOST_CHECK_EQUAL(mapped, "hogehoge"); BOOST_TEST(mapped == "hogehoge");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -297,7 +297,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i; return i + i;
}, "foobar"); }, "foobar");
BOOST_CHECK_EQUAL(mapped, "hogehoge"); BOOST_TEST(mapped == "hogehoge");
} }
} }
@@ -311,10 +311,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(i * 2); return toml::ok(i * 2);
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2); BOOST_TEST(mapped.unwrap() == 42 * 2);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -324,10 +324,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(*i); return toml::ok(*i);
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42); BOOST_TEST(mapped.unwrap() == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -336,10 +336,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(i * 2); return toml::ok(i * 2);
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -349,10 +349,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(*i); return toml::ok(*i);
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
} }
@@ -365,10 +365,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s); return toml::err(s + s);
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42); BOOST_TEST(mapped.unwrap() == 42);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -378,10 +378,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s); return toml::err(s + s);
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(*mapped.unwrap(), 42); BOOST_TEST(*mapped.unwrap() == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -390,10 +390,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s); return toml::err(s + s);
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge"); BOOST_TEST(mapped.unwrap_err() == "hogehoge");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -403,10 +403,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s); return toml::err(s + s);
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge"); BOOST_TEST(mapped.unwrap_err() == "hogehoge");
} }
} }
@@ -416,10 +416,10 @@ BOOST_AUTO_TEST_CASE(test_and_or_other)
const toml::result<int, std::string> r1(toml::ok(42)); const toml::result<int, std::string> r1(toml::ok(42));
const toml::result<int, std::string> r2(toml::err<std::string>("foo")); const toml::result<int, std::string> r2(toml::err<std::string>("foo"));
BOOST_CHECK_EQUAL(r1, r1.or_other(r2)); BOOST_TEST(r1 == r1.or_other(r2));
BOOST_CHECK_EQUAL(r2, r1.and_other(r2)); BOOST_TEST(r2 == r1.and_other(r2));
BOOST_CHECK_EQUAL(42, r1.or_other(r2).unwrap()); BOOST_TEST(42 == r1.or_other(r2).unwrap());
BOOST_CHECK_EQUAL("foo", r1.and_other(r2).unwrap_err()); BOOST_TEST("foo" == r1.and_other(r2).unwrap_err());
} }
{ {
auto r1_gen = []() -> toml::result<int, std::string> { auto r1_gen = []() -> toml::result<int, std::string> {
@@ -431,10 +431,10 @@ BOOST_AUTO_TEST_CASE(test_and_or_other)
const auto r3 = r1_gen(); const auto r3 = r1_gen();
const auto r4 = r2_gen(); const auto r4 = r2_gen();
BOOST_CHECK_EQUAL(r3, r1_gen().or_other (r2_gen())); BOOST_TEST(r3 == r1_gen().or_other (r2_gen()));
BOOST_CHECK_EQUAL(r4, r1_gen().and_other(r2_gen())); BOOST_TEST(r4 == r1_gen().and_other(r2_gen()));
BOOST_CHECK_EQUAL(42, r1_gen().or_other (r2_gen()).unwrap()); BOOST_TEST(42 == r1_gen().or_other (r2_gen()).unwrap());
BOOST_CHECK_EQUAL("foo", r1_gen().and_other(r2_gen()).unwrap_err()); BOOST_TEST("foo" == r1_gen().and_other(r2_gen()).unwrap_err());
} }
} }

View File

@@ -6,10 +6,11 @@
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#endif #endif
#include <toml.hpp> #include <toml.hpp>
#include <deque>
#include <map>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
BOOST_AUTO_TEST_CASE(test_example) BOOST_AUTO_TEST_CASE(test_example)
{ {
const auto data = toml::parse("toml/tests/example.toml"); const auto data = toml::parse("toml/tests/example.toml");
@@ -20,15 +21,90 @@ BOOST_AUTO_TEST_CASE(test_example)
auto serialized = toml::parse("tmp1.toml"); auto serialized = toml::parse("tmp1.toml");
{ {
auto& owner = toml::get<toml::table>(serialized.at("owner")); auto& owner = toml::find(serialized, "owner");
auto& bio = toml::get<std::string>(owner.at("bio")); auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r'); const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end()) if(CR != bio.end())
{ {
bio.erase(CR); bio.erase(CR);
} }
} }
BOOST_CHECK(data == serialized); BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_example_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
"toml/tests/example.toml");
{
std::ofstream ofs("tmp1.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp1.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_example_with_comment)
{
const auto data = toml::parse<toml::preserve_comments>("toml/tests/example.toml");
{
std::ofstream ofs("tmp1_com.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::preserve_comments>("tmp1_com.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data == serialized);
{
std::ofstream ofs("tmp1_com1.toml");
ofs << std::setw(80) << serialized;
}
}
BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
"toml/tests/example.toml");
{
std::ofstream ofs("tmp1_com.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
"tmp1_com.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data == serialized);
{
std::ofstream ofs("tmp1_com1.toml");
ofs << std::setw(80) << serialized;
}
} }
BOOST_AUTO_TEST_CASE(test_fruit) BOOST_AUTO_TEST_CASE(test_fruit)
@@ -39,7 +115,43 @@ BOOST_AUTO_TEST_CASE(test_fruit)
ofs << std::setw(80) << data; ofs << std::setw(80) << data;
} }
const auto serialized = toml::parse("tmp2.toml"); const auto serialized = toml::parse("tmp2.toml");
BOOST_CHECK(data == serialized); BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
"toml/tests/fruit.toml");
{
std::ofstream ofs("tmp2.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp2.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_with_comments)
{
const auto data = toml::parse<toml::preserve_comments>("toml/tests/fruit.toml");
{
std::ofstream ofs("tmp2_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("tmp2_com.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_with_comments_map_dq)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
"toml/tests/fruit.toml");
{
std::ofstream ofs("tmp2_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>("tmp2_com.toml");
BOOST_TEST(data == serialized);
} }
BOOST_AUTO_TEST_CASE(test_hard_example) BOOST_AUTO_TEST_CASE(test_hard_example)
@@ -50,5 +162,35 @@ BOOST_AUTO_TEST_CASE(test_hard_example)
ofs << std::setw(80) << data; ofs << std::setw(80) << data;
} }
const auto serialized = toml::parse("tmp3.toml"); const auto serialized = toml::parse("tmp3.toml");
BOOST_CHECK(data == serialized); BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_hard_example_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
"toml/tests/hard_example.toml");
{
std::ofstream ofs("tmp3.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp3.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_hard_example_with_comment)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
"toml/tests/hard_example.toml");
{
std::ofstream ofs("tmp3_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
"tmp3_com.toml");
{
std::ofstream ofs("tmp3_com1.toml");
ofs << std::setw(80) << serialized;
}
BOOST_TEST(data == serialized);
} }

View File

@@ -37,48 +37,48 @@ typedef std::unordered_map<std::string, dummy_type> std_unordered_map_type;
BOOST_AUTO_TEST_CASE(test_has_xxx) BOOST_AUTO_TEST_CASE(test_has_xxx)
{ {
BOOST_CHECK(toml::detail::has_iterator<std::list<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::forward_list<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::deque<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::vector<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::set<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::unordered_set<std::string>>::value); BOOST_TEST(toml::detail::has_iterator<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::has_iterator<std_array_type>::value); BOOST_TEST(toml::detail::has_iterator<std_array_type>::value);
BOOST_CHECK(toml::detail::has_iterator<std_map_type>::value); BOOST_TEST(toml::detail::has_iterator<std_map_type>::value);
BOOST_CHECK(toml::detail::has_iterator<std_unordered_map_type>::value); BOOST_TEST(toml::detail::has_iterator<std_unordered_map_type>::value);
BOOST_CHECK(toml::detail::has_iterator<dummy_container<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<dummy_container<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::list<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::forward_list<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::deque<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::vector<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std_array_type>::value); BOOST_TEST(toml::detail::has_value_type<std_array_type>::value);
BOOST_CHECK(toml::detail::has_value_type<std::set<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::unordered_set<std::string>>::value); BOOST_TEST(toml::detail::has_value_type<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::has_value_type<std_map_type>::value); BOOST_TEST(toml::detail::has_value_type<std_map_type>::value);
BOOST_CHECK(toml::detail::has_value_type<std_unordered_map_type>::value); BOOST_TEST(toml::detail::has_value_type<std_unordered_map_type>::value);
BOOST_CHECK(toml::detail::has_value_type<dummy_container<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<dummy_container<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_key_type<std_map_type>::value); BOOST_TEST(toml::detail::has_key_type<std_map_type>::value);
BOOST_CHECK(toml::detail::has_key_type<std_unordered_map_type>::value); BOOST_TEST(toml::detail::has_key_type<std_unordered_map_type>::value);
BOOST_CHECK(toml::detail::has_mapped_type<std_map_type>::value); BOOST_TEST(toml::detail::has_mapped_type<std_map_type>::value);
BOOST_CHECK(toml::detail::has_mapped_type<std_unordered_map_type>::value); BOOST_TEST(toml::detail::has_mapped_type<std_unordered_map_type>::value);
} }
BOOST_AUTO_TEST_CASE(test_is_xxx) BOOST_AUTO_TEST_CASE(test_is_xxx)
{ {
BOOST_CHECK(toml::detail::is_container<std::list<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::list<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::forward_list<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::deque<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::vector<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std_array_type>::value); BOOST_TEST(toml::detail::is_container<std_array_type>::value);
BOOST_CHECK(toml::detail::is_container<std::set<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::unordered_set<std::string>>::value); BOOST_TEST(toml::detail::is_container<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::is_container<dummy_container<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<dummy_container<dummy_type>>::value);
BOOST_CHECK(!toml::detail::is_container<std_map_type>::value); BOOST_TEST(!toml::detail::is_container<std_map_type>::value);
BOOST_CHECK(!toml::detail::is_container<std_unordered_map_type>::value); BOOST_TEST(!toml::detail::is_container<std_unordered_map_type>::value);
BOOST_CHECK(toml::detail::is_map<std_map_type>::value); BOOST_TEST(toml::detail::is_map<std_map_type>::value);
BOOST_CHECK(toml::detail::is_map<std_unordered_map_type>::value); BOOST_TEST(toml::detail::is_map<std_unordered_map_type>::value);
} }

View File

@@ -14,69 +14,39 @@ BOOST_AUTO_TEST_CASE(test_resize)
{ {
typedef std::vector<int> resizable_type; typedef std::vector<int> resizable_type;
typedef std::array<int,1> non_resizable_type; typedef std::array<int,1> non_resizable_type;
BOOST_CHECK(toml::detail::has_resize_method<resizable_type>::value); BOOST_TEST(toml::detail::has_resize_method<resizable_type>::value);
BOOST_CHECK(!toml::detail::has_resize_method<non_resizable_type>::value); BOOST_TEST(!toml::detail::has_resize_method<non_resizable_type>::value);
} }
{ {
bool thrown = false;
std::vector<int> v; std::vector<int> v;
try
{
toml::resize(v, 10); toml::resize(v, 10);
BOOST_TEST(v.size() == 10u);
} }
catch(std::exception& ex)
{ {
thrown = true;
}
BOOST_CHECK(!thrown);
BOOST_CHECK_EQUAL(v.size(), 10u);
}
{
bool thrown = false;
std::array<int, 15> a; std::array<int, 15> a;
try
{
toml::resize(a, 10); toml::resize(a, 10);
BOOST_TEST(a.size() == 15u);
} }
catch(std::exception& ex)
{ {
thrown = true;
}
BOOST_CHECK(!thrown);
BOOST_CHECK_EQUAL(a.size(), 15u);
}
{
bool thrown = false;
std::array<int, 15> a; std::array<int, 15> a;
try BOOST_CHECK_THROW(toml::resize(a, 20), std::invalid_argument);
{
toml::resize(a, 20);
}
catch(std::exception& ex)
{
thrown = true;
}
BOOST_CHECK(thrown);
} }
} }
BOOST_AUTO_TEST_CASE(test_concat_to_string) BOOST_AUTO_TEST_CASE(test_concat_to_string)
{ {
const std::string cat = toml::concat_to_string("foo", "bar", 42); const std::string cat = toml::concat_to_string("foo", "bar", 42);
BOOST_CHECK(cat == "foobar42"); BOOST_TEST(cat == "foobar42");
} }
BOOST_AUTO_TEST_CASE(test_from_string) BOOST_AUTO_TEST_CASE(test_from_string)
{ {
{ {
const std::string str("123"); const std::string str("123");
BOOST_CHECK_EQUAL(toml::from_string<int>(str, 0), 123); BOOST_TEST(toml::from_string<int>(str, 0) == 123);
} }
{ {
const std::string str("01"); const std::string str("01");
BOOST_CHECK_EQUAL(toml::from_string<int>(str, 0), 1); BOOST_TEST(toml::from_string<int>(str, 0) == 1);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,6 @@
#include "toml/parser.hpp" #include "toml/parser.hpp"
#include "toml/literal.hpp" #include "toml/literal.hpp"
#include "toml/serializer.hpp" #include "toml/serializer.hpp"
#include "toml/from_toml.hpp"
#include "toml/get.hpp" #include "toml/get.hpp"
#endif// TOML_FOR_MODERN_CPP #endif// TOML_FOR_MODERN_CPP

View File

@@ -45,7 +45,7 @@ inline std::string show_char(const char c)
buf.fill('\0'); buf.fill('\0');
const auto r = std::snprintf( const auto r = std::snprintf(
buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF); buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
assert(r == buf.size() - 1); assert(r == static_cast<int>(buf.size()) - 1);
return std::string(buf.data()); return std::string(buf.data());
} }
} }

385
toml/comments.hpp Normal file
View File

@@ -0,0 +1,385 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_COMMENTS_HPP
#define TOML11_COMMENTS_HPP
#include <type_traits>
#include <utility>
#include <iterator>
#include <initializer_list>
#include <vector>
#include <string>
// This file provides mainly two classes, `preserve_comments` and `discard_comments`.
// Those two are a container that have the same interface as `std::vector<std::string>`
// but bahaves in the opposite way. `preserve_comments` is just the same as
// `std::vector<std::string>` and each `std::string` corresponds to a comment line.
// Conversely, `discard_comments` discards all the strings and ignores everything
// assigned in it. `discard_comments` is always empty and you will encounter an
// error whenever you access to the element.
namespace toml
{
struct discard_comments; // forward decl
// use it in the following way
//
// const toml::basic_value<toml::preserve_comments> data =
// toml::parse<toml::preserve_comments>("example.toml");
//
// the interface is almost the same as std::vector<std::string>.
struct preserve_comments
{
// `container_type` is not provided in discard_comments.
// do not use this inner-type in a generic code.
using container_type = std::vector<std::string>;
using size_type = container_type::size_type;
using difference_type = container_type::difference_type;
using value_type = container_type::value_type;
using reference = container_type::reference;
using const_reference = container_type::const_reference;
using pointer = container_type::pointer;
using const_pointer = container_type::const_pointer;
using iterator = container_type::iterator;
using const_iterator = container_type::const_iterator;
using reverse_iterator = container_type::reverse_iterator;
using const_reverse_iterator = container_type::const_reverse_iterator;
preserve_comments() = default;
~preserve_comments() = default;
preserve_comments(preserve_comments const&) = default;
preserve_comments(preserve_comments &&) = default;
preserve_comments& operator=(preserve_comments const&) = default;
preserve_comments& operator=(preserve_comments &&) = default;
explicit preserve_comments(const std::vector<std::string>& c): comments(c){}
explicit preserve_comments(std::vector<std::string>&& c)
: comments(std::move(c))
{}
preserve_comments& operator=(const std::vector<std::string>& c)
{
comments = c;
return *this;
}
preserve_comments& operator=(std::vector<std::string>&& c)
{
comments = std::move(c);
return *this;
}
explicit preserve_comments(const discard_comments&) {}
explicit preserve_comments(size_type n): comments(n) {}
preserve_comments(size_type n, const std::string& x): comments(n, x) {}
preserve_comments(std::initializer_list<std::string> x): comments(x) {}
template<typename InputIterator>
preserve_comments(InputIterator first, InputIterator last)
: comments(first, last)
{}
template<typename InputIterator>
void assign(InputIterator first, InputIterator last) {comments.assign(first, last);}
void assign(std::initializer_list<std::string> ini) {comments.assign(ini);}
void assign(size_type n, const std::string& val) {comments.assign(n, val);}
iterator insert(const_iterator p, const std::string& x)
{
return comments.insert(p, x);
}
iterator insert(const_iterator p, std::string&& x)
{
return comments.insert(p, std::move(x));
}
iterator insert(const_iterator p, size_type n, const std::string& x)
{
return comments.insert(p, n, x);
}
template<typename InputIterator>
iterator insert(const_iterator p, InputIterator first, InputIterator last)
{
return comments.insert(p, first, last);
}
iterator insert(const_iterator p, std::initializer_list<std::string> ini)
{
return comments.insert(p, ini);
}
template<typename ... Ts>
iterator emplace(const_iterator p, Ts&& ... args)
{
return comments.emplace(p, std::forward<Ts>(args)...);
}
iterator erase(const_iterator pos) {return comments.erase(pos);}
iterator erase(const_iterator first, const_iterator last)
{
return comments.erase(first, last);
}
void swap(preserve_comments& other) {comments.swap(other.comments);}
void push_back(const std::string& v) {comments.push_back(v);}
void push_back(std::string&& v) {comments.push_back(std::move(v));}
void pop_back() {comments.pop_back();}
template<typename ... Ts>
void emplace_back(Ts&& ... args) {comments.emplace_back(std::forward<Ts>(args)...);}
void clear() {comments.clear();}
size_type size() const noexcept {return comments.size();}
size_type max_size() const noexcept {return comments.max_size();}
size_type capacity() const noexcept {return comments.capacity();}
bool empty() const noexcept {return comments.empty();}
void reserve(size_type n) {comments.reserve(n);}
void resize(size_type n) {comments.resize(n);}
void resize(size_type n, const std::string& c) {comments.resize(n, c);}
void shrink_to_fit() {comments.shrink_to_fit();}
reference operator[](const size_type n) noexcept {return comments[n];}
const_reference operator[](const size_type n) const noexcept {return comments[n];}
reference at(const size_type n) {return comments.at(n);}
const_reference at(const size_type n) const {return comments.at(n);}
reference front() noexcept {return comments.front();}
const_reference front() const noexcept {return comments.front();}
reference back() noexcept {return comments.back();}
const_reference back() const noexcept {return comments.back();}
pointer data() noexcept {return comments.data();}
const_pointer data() const noexcept {return comments.data();}
iterator begin() noexcept {return comments.begin();}
iterator end() noexcept {return comments.end();}
const_iterator begin() const noexcept {return comments.begin();}
const_iterator end() const noexcept {return comments.end();}
const_iterator cbegin() const noexcept {return comments.cbegin();}
const_iterator cend() const noexcept {return comments.cend();}
reverse_iterator rbegin() noexcept {return comments.rbegin();}
reverse_iterator rend() noexcept {return comments.rend();}
const_reverse_iterator rbegin() const noexcept {return comments.rbegin();}
const_reverse_iterator rend() const noexcept {return comments.rend();}
const_reverse_iterator crbegin() const noexcept {return comments.crbegin();}
const_reverse_iterator crend() const noexcept {return comments.crend();}
friend bool operator==(const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator< (const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator> (const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs);
private:
container_type comments;
};
inline bool operator==(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments == rhs.comments;}
inline bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments != rhs.comments;}
inline bool operator< (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments < rhs.comments;}
inline bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments <= rhs.comments;}
inline bool operator> (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments > rhs.comments;}
inline bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments >= rhs.comments;}
inline void swap(preserve_comments& lhs, preserve_comments& rhs)
{
lhs.swap(rhs);
return;
}
namespace detail
{
// To provide the same interface with `preserve_comments`, `discard_comments`
// should have an iterator. But it does not contain anything, so we need to
// add an iterator that points nothing.
//
// It always points null, so DO NOT unwrap this iterator. It always crashes
// your program.
template<typename T, bool is_const>
struct empty_iterator
{
using value_type = T;
using reference_type = typename std::conditional<is_const, T const&, T&>::type;
using pointer_type = typename std::conditional<is_const, T const*, T*>::type;
using difference_type = std::ptrdiff_t;
using iterator_category = std::random_access_iterator_tag;
empty_iterator() = default;
~empty_iterator() = default;
empty_iterator(empty_iterator const&) = default;
empty_iterator(empty_iterator &&) = default;
empty_iterator& operator=(empty_iterator const&) = default;
empty_iterator& operator=(empty_iterator &&) = default;
// DO NOT call these operators.
reference_type operator*() const noexcept {std::terminate();}
pointer_type operator->() const noexcept {return nullptr;}
reference_type operator[](difference_type) const noexcept {return this->operator*();}
// These operators do nothing.
empty_iterator& operator++() noexcept {return *this;}
empty_iterator operator++(int) noexcept {return *this;}
empty_iterator& operator--() noexcept {return *this;}
empty_iterator operator--(int) noexcept {return *this;}
empty_iterator& operator+=(difference_type) noexcept {return *this;}
empty_iterator& operator-=(difference_type) noexcept {return *this;}
empty_iterator operator+(difference_type) const noexcept {return *this;}
empty_iterator operator-(difference_type) const noexcept {return *this;}
};
template<typename T, bool C>
bool operator==(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
template<typename T, bool C>
bool operator!=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
template<typename T, bool C>
bool operator< (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
template<typename T, bool C>
bool operator<=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
template<typename T, bool C>
bool operator> (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
template<typename T, bool C>
bool operator>=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
template<typename T, bool C>
typename empty_iterator<T, C>::difference_type
operator-(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return 0;}
template<typename T, bool C>
empty_iterator<T, C>
operator+(typename empty_iterator<T, C>::difference_type, const empty_iterator<T, C>& rhs) noexcept {return rhs;}
template<typename T, bool C>
empty_iterator<T, C>
operator+(const empty_iterator<T, C>& lhs, typename empty_iterator<T, C>::difference_type) noexcept {return lhs;}
} // detail
// The default comment type. It discards all the comments. It requires only one
// byte to contain, so the memory footprint is smaller than preserve_comments.
//
// It just ignores `push_back`, `insert`, `erase`, and any other modifications.
// IT always returns size() == 0, the iterator taken by `begin()` is always the
// same as that of `end()`, and accessing through `operator[]` or iterators
// always causes a segmentation fault. DO NOT access to the element of this.
//
// Why this is chose as the default type is because the last version (2.x.y)
// does not contain any comments in a value. To minimize the impact on the
// efficiency, this is choosed as a default.
//
// To reduce the memory footprint, later we can try empty base optimization (EBO).
struct discard_comments
{
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using value_type = std::string;
using reference = std::string&;
using const_reference = std::string const&;
using pointer = std::string*;
using const_pointer = std::string const*;
using iterator = detail::empty_iterator<std::string, false>;
using const_iterator = detail::empty_iterator<std::string, true>;
using reverse_iterator = detail::empty_iterator<std::string, false>;
using const_reverse_iterator = detail::empty_iterator<std::string, true>;
discard_comments() = default;
~discard_comments() = default;
discard_comments(discard_comments const&) = default;
discard_comments(discard_comments &&) = default;
discard_comments& operator=(discard_comments const&) = default;
discard_comments& operator=(discard_comments &&) = default;
explicit discard_comments(const std::vector<std::string>&) noexcept {}
explicit discard_comments(std::vector<std::string>&&) noexcept {}
discard_comments& operator=(const std::vector<std::string>&) noexcept {return *this;}
discard_comments& operator=(std::vector<std::string>&&) noexcept {return *this;}
explicit discard_comments(const preserve_comments&) noexcept {}
explicit discard_comments(size_type) noexcept {}
discard_comments(size_type, const std::string&) noexcept {}
discard_comments(std::initializer_list<std::string>) noexcept {}
template<typename InputIterator>
discard_comments(InputIterator, InputIterator) noexcept {}
template<typename InputIterator>
void assign(InputIterator, InputIterator) noexcept {}
void assign(std::initializer_list<std::string>) noexcept {}
void assign(size_type, const std::string&) noexcept {}
iterator insert(const_iterator, const std::string&) {return iterator{};}
iterator insert(const_iterator, std::string&&) {return iterator{};}
iterator insert(const_iterator, size_type, const std::string&) {return iterator{};}
template<typename InputIterator>
iterator insert(const_iterator, InputIterator, InputIterator) {return iterator{};}
iterator insert(const_iterator, std::initializer_list<std::string>) {return iterator{};}
template<typename ... Ts>
iterator emplace(const_iterator, Ts&& ...) {return iterator{};}
iterator erase(const_iterator) {return iterator{};}
iterator erase(const_iterator, const_iterator) {return iterator{};}
void swap(discard_comments&) {return;}
void push_back(const std::string&) {return;}
void push_back(std::string&& ) {return;}
void pop_back() {return;}
template<typename ... Ts>
void emplace_back(Ts&& ...) {return;}
void clear() {return;}
size_type size() const noexcept {return 0;}
size_type max_size() const noexcept {return 0;}
size_type capacity() const noexcept {return 0;}
bool empty() const noexcept {return true;}
void reserve(size_type) {return;}
void resize(size_type) {return;}
void resize(size_type, const std::string&) {return;}
void shrink_to_fit() {return;}
// DO NOT access to the element of this container. This container is always
// empty, so accessing through operator[], front/back, data causes address
// error.
reference operator[](const size_type) noexcept {return *data();}
const_reference operator[](const size_type) const noexcept {return *data();}
reference at(const size_type) {throw std::out_of_range("toml::discard_comment is always empty.");}
const_reference at(const size_type) const {throw std::out_of_range("toml::discard_comment is always empty.");}
reference front() noexcept {return *data();}
const_reference front() const noexcept {return *data();}
reference back() noexcept {return *data();}
const_reference back() const noexcept {return *data();}
pointer data() noexcept {return nullptr;}
const_pointer data() const noexcept {return nullptr;}
iterator begin() noexcept {return iterator{};}
iterator end() noexcept {return iterator{};}
const_iterator begin() const noexcept {return const_iterator{};}
const_iterator end() const noexcept {return const_iterator{};}
const_iterator cbegin() const noexcept {return const_iterator{};}
const_iterator cend() const noexcept {return const_iterator{};}
reverse_iterator rbegin() noexcept {return iterator{};}
reverse_iterator rend() noexcept {return iterator{};}
const_reverse_iterator rbegin() const noexcept {return const_iterator{};}
const_reverse_iterator rend() const noexcept {return const_iterator{};}
const_reverse_iterator crbegin() const noexcept {return const_iterator{};}
const_reverse_iterator crend() const noexcept {return const_iterator{};}
};
inline bool operator==(const discard_comments&, const discard_comments&) noexcept {return true;}
inline bool operator!=(const discard_comments&, const discard_comments&) noexcept {return false;}
inline bool operator< (const discard_comments&, const discard_comments&) noexcept {return false;}
inline bool operator<=(const discard_comments&, const discard_comments&) noexcept {return true;}
inline bool operator> (const discard_comments&, const discard_comments&) noexcept {return false;}
inline bool operator>=(const discard_comments&, const discard_comments&) noexcept {return true;}
inline void swap(const discard_comments&, const discard_comments&) noexcept {return;}
} // toml11
#endif// TOML11_COMMENTS_HPP

View File

@@ -46,7 +46,7 @@ inline std::tm localtime_s(const std::time_t* src)
#endif #endif
} // detail } // detail
enum class month_t : std::int8_t enum class month_t : std::uint8_t
{ {
Jan = 0, Jan = 0,
Feb = 1, Feb = 1,
@@ -98,9 +98,9 @@ struct local_date
t.tm_sec = 0; t.tm_sec = 0;
t.tm_min = 0; t.tm_min = 0;
t.tm_hour = 0; t.tm_hour = 0;
t.tm_mday = this->day; t.tm_mday = static_cast<int>(this->day);
t.tm_mon = this->month; t.tm_mon = static_cast<int>(this->month);
t.tm_year = this->year - 1900; t.tm_year = static_cast<int>(this->year) - 1900;
t.tm_wday = 0; // the value will be ignored t.tm_wday = 0; // the value will be ignored
t.tm_yday = 0; // the value will be ignored t.tm_yday = 0; // the value will be ignored
t.tm_isdst = -1; t.tm_isdst = -1;
@@ -188,22 +188,22 @@ struct local_time
explicit local_time(const std::chrono::duration<Rep, Period>& t) explicit local_time(const std::chrono::duration<Rep, Period>& t)
{ {
const auto h = std::chrono::duration_cast<std::chrono::hours>(t); const auto h = std::chrono::duration_cast<std::chrono::hours>(t);
this->hour = h.count(); this->hour = static_cast<std::uint8_t>(h.count());
const auto t2 = t - h; const auto t2 = t - h;
const auto m = std::chrono::duration_cast<std::chrono::minutes>(t2); const auto m = std::chrono::duration_cast<std::chrono::minutes>(t2);
this->minute = m.count(); this->minute = static_cast<std::uint8_t>(m.count());
const auto t3 = t2 - m; const auto t3 = t2 - m;
const auto s = std::chrono::duration_cast<std::chrono::seconds>(t3); const auto s = std::chrono::duration_cast<std::chrono::seconds>(t3);
this->second = s.count(); this->second = static_cast<std::uint8_t>(s.count());
const auto t4 = t3 - s; const auto t4 = t3 - s;
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t4); const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t4);
this->millisecond = ms.count(); this->millisecond = static_cast<std::uint16_t>(ms.count());
const auto t5 = t4 - ms; const auto t5 = t4 - ms;
const auto us = std::chrono::duration_cast<std::chrono::microseconds>(t5); const auto us = std::chrono::duration_cast<std::chrono::microseconds>(t5);
this->microsecond = us.count(); this->microsecond = static_cast<std::uint16_t>(us.count());
const auto t6 = t5 - us; const auto t6 = t5 - us;
const auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t6); const auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t6);
this->nanosecond = ns.count(); this->nanosecond = static_cast<std::uint16_t>(ns.count());
} }
operator std::chrono::nanoseconds() const operator std::chrono::nanoseconds() const

View File

@@ -1,71 +0,0 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_FROM_TOML_HPP
#define TOML11_FROM_TOML_HPP
#include "get.hpp"
namespace toml
{
template<typename T>
void from_toml(T& x, const toml::value& v)
{
x = toml::get<typename std::remove_reference<T>::type>(v);
return;
}
namespace detail
{
template<typename T>
constexpr toml::value_t determine_castable_type()
{
return check_type<T>() != toml::value_t::Unknown ? check_type<T>() :
toml::detail::is_map<T>::value ? toml::value_t::Table :
toml::detail::is_container<T>::value ? toml::value_t::Array :
toml::value_t::Unknown;
}
template<std::size_t N, typename ... Ts>
struct from_toml_tie_impl
{
constexpr static std::size_t index = sizeof...(Ts) - N;
constexpr static toml::value_t type_index =
determine_castable_type<
typename std::tuple_element<index, std::tuple<Ts...>>::type>();
static void invoke(std::tuple<Ts& ...> tie, const toml::value& v)
{
// static_cast is needed because with intel c++ compiler, operator==
// is only defined when the two types are strictly equal, and type_index
// is const toml::value_t, while v.type() is toml::value_t.
if(static_cast<toml::value_t>(type_index) == v.type())
{
from_toml(std::get<index>(tie), v);
return;
}
return from_toml_tie_impl<N-1, Ts...>::invoke(tie, v);
}
};
template<typename ... Ts>
struct from_toml_tie_impl<0, Ts...>
{
static void invoke(std::tuple<Ts& ...>, const toml::value&)
{
return;
}
};
} // detail
template<typename ... Ts>
void from_toml(std::tuple<Ts& ...> tie, const toml::value& v)
{
detail::from_toml_tie_impl<sizeof...(Ts), Ts...>::invoke(tie, v);
return;
}
} // toml
#endif // TOML11_FROM_TOML

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@ inline namespace literals
inline namespace toml_literals inline namespace toml_literals
{ {
inline ::toml::value operator""_toml(const char* str, std::size_t len) inline ::toml::value operator"" _toml(const char* str, std::size_t len)
{ {
::toml::detail::location<std::vector<char>> ::toml::detail::location<std::vector<char>>
loc(/* filename = */ std::string("TOML literal encoded in a C++ code"), loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
@@ -53,7 +53,7 @@ inline ::toml::value operator""_toml(const char* str, std::size_t len)
// If it is neither a table-key or a array-of-table-key, it may be a value. // If it is neither a table-key or a array-of-table-key, it may be a value.
if(!is_table_key && !is_aots_key) if(!is_table_key && !is_aots_key)
{ {
if(auto data = ::toml::detail::parse_value(loc)) if(auto data = ::toml::detail::parse_value<::toml::value>(loc))
{ {
return data.unwrap(); return data.unwrap();
} }
@@ -70,14 +70,9 @@ inline ::toml::value operator""_toml(const char* str, std::size_t len)
// It is a valid toml file. // It is a valid toml file.
// It should be parsed as if we parse a file with this content. // It should be parsed as if we parse a file with this content.
if(auto data = ::toml::detail::parse_toml_file(loc)) if(auto data = ::toml::detail::parse_toml_file<::toml::value>(loc))
{ {
loc.reset(loc.begin()); // rollback to the top of the literal return data.unwrap();
// skip needless characters for error message
skip_line::invoke(loc); // skip the first several needless lines
skip_ws::invoke(loc); // skip the first several needless whitespaces
return ::toml::value(std::move(data.unwrap()),
::toml::detail::region<std::vector<char>>(std::move(loc)));
} }
else // none of them. else // none of them.
{ {

View File

@@ -253,6 +253,11 @@ std::string read_utf8_codepoint(const region<Container>& reg,
std::istringstream iss(str); std::istringstream iss(str);
iss >> std::hex >> codepoint; iss >> std::hex >> codepoint;
const auto to_char = [](const int i) noexcept -> char {
const auto uc = static_cast<unsigned char>(i);
return *reinterpret_cast<const char*>(std::addressof(uc));
};
std::string character; std::string character;
if(codepoint < 0x80) // U+0000 ... U+0079 ; just an ASCII. if(codepoint < 0x80) // U+0000 ... U+0079 ; just an ASCII.
{ {
@@ -261,8 +266,8 @@ std::string read_utf8_codepoint(const region<Container>& reg,
else if(codepoint < 0x800) //U+0080 ... U+07FF else if(codepoint < 0x800) //U+0080 ... U+07FF
{ {
// 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111 // 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111
character += static_cast<unsigned char>(0xC0| codepoint >> 6); character += to_char(0xC0| codepoint >> 6);
character += static_cast<unsigned char>(0x80|(codepoint & 0x3F)); character += to_char(0x80|(codepoint & 0x3F));
} }
else if(codepoint < 0x10000) // U+0800...U+FFFF else if(codepoint < 0x10000) // U+0800...U+FFFF
{ {
@@ -276,17 +281,17 @@ std::string read_utf8_codepoint(const region<Container>& reg,
} }
assert(codepoint < 0xD800 || 0xDFFF < codepoint); assert(codepoint < 0xD800 || 0xDFFF < codepoint);
// 1110yyyy 10yxxxxx 10xxxxxx // 1110yyyy 10yxxxxx 10xxxxxx
character += static_cast<unsigned char>(0xE0| codepoint >> 12); character += to_char(0xE0| codepoint >> 12);
character += static_cast<unsigned char>(0x80|(codepoint >> 6 & 0x3F)); character += to_char(0x80|(codepoint >> 6 & 0x3F));
character += static_cast<unsigned char>(0x80|(codepoint & 0x3F)); character += to_char(0x80|(codepoint & 0x3F));
} }
else if(codepoint < 0x110000) // U+010000 ... U+10FFFF else if(codepoint < 0x110000) // U+010000 ... U+10FFFF
{ {
// 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx // 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
character += static_cast<unsigned char>(0xF0| codepoint >> 18); character += to_char(0xF0| codepoint >> 18);
character += static_cast<unsigned char>(0x80|(codepoint >> 12 & 0x3F)); character += to_char(0x80|(codepoint >> 12 & 0x3F));
character += static_cast<unsigned char>(0x80|(codepoint >> 6 & 0x3F)); character += to_char(0x80|(codepoint >> 6 & 0x3F));
character += static_cast<unsigned char>(0x80|(codepoint & 0x3F)); character += to_char(0x80|(codepoint & 0x3F));
} }
else // out of UTF-8 region else // out of UTF-8 region
{ {
@@ -655,9 +660,9 @@ parse_local_time(location<Container>& loc)
{{std::addressof(inner_loc), "here"}})); {{std::addressof(inner_loc), "here"}}));
} }
local_time time( local_time time(
static_cast<std::int8_t>(from_string<int>(h.unwrap().str(), 0)), from_string<int>(h.unwrap().str(), 0),
static_cast<std::int8_t>(from_string<int>(m.unwrap().str(), 0)), from_string<int>(m.unwrap().str(), 0),
static_cast<std::int8_t>(from_string<int>(s.unwrap().str(), 0)), 0, 0); from_string<int>(s.unwrap().str(), 0), 0, 0);
const auto before_secfrac = inner_loc.iter(); const auto before_secfrac = inner_loc.iter();
if(const auto secfrac = lex_time_secfrac::invoke(inner_loc)) if(const auto secfrac = lex_time_secfrac::invoke(inner_loc))
@@ -673,13 +678,13 @@ parse_local_time(location<Container>& loc)
} }
if(sf.size() >= 6) if(sf.size() >= 6)
{ {
time.millisecond = from_string<std::int16_t>(sf.substr(0, 3), 0); time.millisecond = from_string<std::uint16_t>(sf.substr(0, 3), 0u);
time.microsecond = from_string<std::int16_t>(sf.substr(3, 3), 0); time.microsecond = from_string<std::uint16_t>(sf.substr(3, 3), 0u);
} }
else if(sf.size() >= 3) else if(sf.size() >= 3)
{ {
time.millisecond = from_string<std::int16_t>(sf, 0); time.millisecond = from_string<std::uint16_t>(sf, 0u);
time.microsecond = 0; time.microsecond = 0u;
} }
} }
else else
@@ -869,13 +874,16 @@ parse_key(location<Container>& loc)
} }
// forward-decl to implement parse_array and parse_table // forward-decl to implement parse_array and parse_table
template<typename Container> template<typename Value, typename Container>
result<value, std::string> parse_value(location<Container>&); result<Value, std::string> parse_value(location<Container>&);
template<typename Container> template<typename Value, typename Container>
result<std::pair<array, region<Container>>, std::string> result<std::pair<typename Value::array_type, region<Container>>, std::string>
parse_array(location<Container>& loc) parse_array(location<Container>& loc)
{ {
using value_type = Value;
using array_type = typename value_type::array_type;
const auto first = loc.iter(); const auto first = loc.iter();
if(loc.iter() == loc.end()) if(loc.iter() == loc.end())
{ {
@@ -890,7 +898,7 @@ parse_array(location<Container>& loc)
using lex_ws_comment_newline = repeat< using lex_ws_comment_newline = repeat<
either<lex_wschar, lex_newline, lex_comment>, unlimited>; either<lex_wschar, lex_newline, lex_comment>, unlimited>;
array retval; array_type retval;
while(loc.iter() != loc.end()) while(loc.iter() != loc.end())
{ {
lex_ws_comment_newline::invoke(loc); // skip lex_ws_comment_newline::invoke(loc); // skip
@@ -902,7 +910,7 @@ parse_array(location<Container>& loc)
region<Container>(loc, first, loc.iter()))); region<Container>(loc, first, loc.iter())));
} }
if(auto val = parse_value(loc)) if(auto val = parse_value<value_type>(loc))
{ {
if(!retval.empty() && retval.front().type() != val.as_ok().type()) if(!retval.empty() && retval.front().type() != val.as_ok().type())
{ {
@@ -966,10 +974,12 @@ parse_array(location<Container>& loc)
{{std::addressof(loc), "should be closed"}})); {{std::addressof(loc), "should be closed"}}));
} }
template<typename Container> template<typename Value, typename Container>
result<std::pair<std::pair<std::vector<key>, region<Container>>, value>, std::string> result<std::pair<std::pair<std::vector<key>, region<Container>>, Value>, std::string>
parse_key_value_pair(location<Container>& loc) parse_key_value_pair(location<Container>& loc)
{ {
using value_type = Value;
const auto first = loc.iter(); const auto first = loc.iter();
auto key_reg = parse_key(loc); auto key_reg = parse_key(loc);
if(!key_reg) if(!key_reg)
@@ -1013,7 +1023,7 @@ parse_key_value_pair(location<Container>& loc)
} }
const auto after_kvsp = loc.iter(); // err msg const auto after_kvsp = loc.iter(); // err msg
auto val = parse_value(loc); auto val = parse_value<value_type>(loc);
if(!val) if(!val)
{ {
std::string msg; std::string msg;
@@ -1081,8 +1091,8 @@ parse_table_key(location<Container>& loc);
// Here, it parses region of `tab->at(k)` as a table key and check the depth // Here, it parses region of `tab->at(k)` as a table key and check the depth
// of the key. If the key region points deeper node, it would be allowed. // of the key. If the key region points deeper node, it would be allowed.
// Otherwise, the key points the same node. It would be rejected. // Otherwise, the key points the same node. It would be rejected.
template<typename Iterator> template<typename Value, typename Iterator>
bool is_valid_forward_table_definition(const value& fwd, bool is_valid_forward_table_definition(const Value& fwd,
Iterator key_first, Iterator key_curr, Iterator key_last) Iterator key_first, Iterator key_curr, Iterator key_last)
{ {
location<std::string> def("internal", detail::get_region(fwd).str()); location<std::string> def("internal", detail::get_region(fwd).str());
@@ -1123,9 +1133,9 @@ bool is_valid_forward_table_definition(const value& fwd,
return false; return false;
} }
template<typename InputIterator, typename Container> template<typename Value, typename InputIterator, typename Container>
result<bool, std::string> result<bool, std::string>
insert_nested_key(table& root, const toml::value& v, insert_nested_key(typename Value::table_type& root, const Value& v,
InputIterator iter, const InputIterator last, InputIterator iter, const InputIterator last,
region<Container> key_reg, region<Container> key_reg,
const bool is_array_of_table = false) const bool is_array_of_table = false)
@@ -1133,10 +1143,14 @@ insert_nested_key(table& root, const toml::value& v,
static_assert(std::is_same<key, static_assert(std::is_same<key,
typename std::iterator_traits<InputIterator>::value_type>::value,""); typename std::iterator_traits<InputIterator>::value_type>::value,"");
using value_type = Value;
using table_type = typename value_type::table_type;
using array_type = typename value_type::array_type;
const auto first = iter; const auto first = iter;
assert(iter != last); assert(iter != last);
table* tab = std::addressof(root); table_type* tab = std::addressof(root);
for(; iter != last; ++iter) // search recursively for(; iter != last; ++iter) // search recursively
{ {
const key& k = *iter; const key& k = *iter;
@@ -1176,7 +1190,7 @@ insert_nested_key(table& root, const toml::value& v,
})); }));
} }
// the above if-else-if checks tab->at(k) is an array // the above if-else-if checks tab->at(k) is an array
array& a = tab->at(k).as_array(); auto& a = tab->at(k).as_array();
if(!(a.front().is_table())) if(!(a.front().is_table()))
{ {
throw syntax_error(format_underline(concat_to_string( throw syntax_error(format_underline(concat_to_string(
@@ -1223,7 +1237,7 @@ insert_nested_key(table& root, const toml::value& v,
} }
else // if not, we need to create the array of table else // if not, we need to create the array of table
{ {
toml::value aot(toml::array(1, v), key_reg); value_type aot(array_type(1, v), key_reg);
tab->insert(std::make_pair(k, aot)); tab->insert(std::make_pair(k, aot));
return ok(true); return ok(true);
} }
@@ -1298,7 +1312,7 @@ insert_nested_key(table& root, const toml::value& v,
// [x.y.z] // [x.y.z]
if(tab->count(k) == 0) if(tab->count(k) == 0)
{ {
(*tab)[k] = toml::value(toml::table{}, key_reg); (*tab)[k] = value_type(table_type{}, key_reg);
} }
// type checking... // type checking...
@@ -1308,7 +1322,7 @@ insert_nested_key(table& root, const toml::value& v,
} }
else if(tab->at(k).is_array()) // inserting to array-of-tables? else if(tab->at(k).is_array()) // inserting to array-of-tables?
{ {
array& a = (*tab)[k].as_array(); auto& a = (*tab)[k].as_array();
if(!a.back().is_table()) if(!a.back().is_table())
{ {
throw syntax_error(format_underline(concat_to_string( throw syntax_error(format_underline(concat_to_string(
@@ -1338,12 +1352,15 @@ insert_nested_key(table& root, const toml::value& v,
return err(std::string("toml::detail::insert_nested_key: never reach here")); return err(std::string("toml::detail::insert_nested_key: never reach here"));
} }
template<typename Container> template<typename Value, typename Container>
result<std::pair<table, region<Container>>, std::string> result<std::pair<typename Value::table_type, region<Container>>, std::string>
parse_inline_table(location<Container>& loc) parse_inline_table(location<Container>& loc)
{ {
using value_type = Value;
using table_type = typename value_type::table_type;
const auto first = loc.iter(); const auto first = loc.iter();
table retval; table_type retval;
if(!(loc.iter() != loc.end() && *loc.iter() == '{')) if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
{ {
return err(format_underline("[error] toml::parse_inline_table: ", return err(format_underline("[error] toml::parse_inline_table: ",
@@ -1361,14 +1378,14 @@ parse_inline_table(location<Container>& loc)
retval, region<Container>(loc, first, loc.iter()))); retval, region<Container>(loc, first, loc.iter())));
} }
const auto kv_r = parse_key_value_pair(loc); const auto kv_r = parse_key_value_pair<value_type>(loc);
if(!kv_r) if(!kv_r)
{ {
return err(kv_r.unwrap_err()); return err(kv_r.unwrap_err());
} }
const std::vector<key>& keys = kv_r.unwrap().first.first; const std::vector<key>& keys = kv_r.unwrap().first.first;
const region<Container>& key_reg = kv_r.unwrap().first.second; const region<Container>& key_reg = kv_r.unwrap().first.second;
const value& val = kv_r.unwrap().second; const value_type& val = kv_r.unwrap().second;
const auto inserted = const auto inserted =
insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg); insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg);
@@ -1410,48 +1427,165 @@ parse_inline_table(location<Container>& loc)
} }
template<typename Container> template<typename Container>
value_t guess_number_type(const location<Container>& l) result<value_t, std::string> guess_number_type(const location<Container>& l)
{ {
// This function tries to find some (common) mistakes by checking characters
// that follows the last character of a value. But it is often difficult
// because some non-newline characters can appear after a value. E.g.
// spaces, tabs, commas (in an array or inline table), closing brackets
// (of an array or inline table), comment-sign (#). Since this function
// does not parse further, those characters are always allowed to be there.
location<Container> loc = l; location<Container> loc = l;
if(lex_offset_date_time::invoke(loc)) {return value_t::OffsetDatetime;} if(lex_offset_date_time::invoke(loc)) {return ok(value_t::offset_datetime);}
loc.reset(l.iter()); loc.reset(l.iter());
if(lex_local_date_time::invoke(loc)) {return value_t::LocalDatetime;} if(lex_local_date_time::invoke(loc))
{
// bad offset may appear after this.
if(loc.iter() != loc.end() && (*loc.iter() == '+' || *loc.iter() == '-'
|| *loc.iter() == 'Z' || *loc.iter() == 'z'))
{
return err(format_underline("[error] bad offset: should be [+-]HH:MM or Z",
{{std::addressof(loc), "[+-]HH:MM or Z"}},
{"pass: +09:00, -05:30", "fail: +9:00, -5:30"}));
}
return ok(value_t::local_datetime);
}
loc.reset(l.iter()); loc.reset(l.iter());
if(lex_local_date::invoke(loc)) {return value_t::LocalDate;} if(lex_local_date::invoke(loc))
{
// bad time may appear after this.
// A space is allowed as a delimiter between local time. But there are
// both cases in which a space becomes valid or invalid.
// - invalid: 2019-06-16 7:00:00
// - valid : 2019-06-16 07:00:00
if(loc.iter() != loc.end())
{
const auto c = *loc.iter();
if(c == 'T' || c == 't')
{
return err(format_underline("[error] bad time: should be HH:MM:SS.subsec",
{{std::addressof(loc), "HH:MM:SS.subsec"}},
{"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
"fail: 1979-05-27T7:32:00, 1979-05-27 17:32"}));
}
if('0' <= c && c <= '9')
{
return err(format_underline("[error] bad time: missing T",
{{std::addressof(loc), "T or space required here"}},
{"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
"fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
}
if(c == ' ' && std::next(loc.iter()) != loc.end() &&
('0' <= *std::next(loc.iter()) && *std::next(loc.iter())<= '9'))
{
loc.advance();
return err(format_underline("[error] bad time: should be HH:MM:SS.subsec",
{{std::addressof(loc), "HH:MM:SS.subsec"}},
{"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
"fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
}
}
return ok(value_t::local_date);
}
loc.reset(l.iter()); loc.reset(l.iter());
if(lex_local_time::invoke(loc)) {return value_t::LocalTime;} if(lex_local_time::invoke(loc)) {return ok(value_t::local_time);}
loc.reset(l.iter()); loc.reset(l.iter());
if(lex_float::invoke(loc)) {return value_t::Float;} if(lex_float::invoke(loc))
{
if(loc.iter() != loc.end() && *loc.iter() == '_')
{
return err(format_underline("[error] bad float: `_` should be surrounded by digits",
{{std::addressof(loc), "here"}},
{"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
"fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
}
return ok(value_t::floating);
}
loc.reset(l.iter()); loc.reset(l.iter());
return value_t::Integer; if(lex_integer::invoke(loc))
{
if(loc.iter() != loc.end())
{
const auto c = *loc.iter();
if(c == '_')
{
return err(format_underline("[error] bad integer: `_` should be surrounded by digits",
{{std::addressof(loc), "here"}},
{"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
"fail: 1__000, 0123"}));
}
if('0' <= c && c <= '9')
{
// leading zero. point '0'
loc.retrace();
return err(format_underline("[error] bad integer: leading zero",
{{std::addressof(loc), "here"}},
{"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
"fail: 1__000, 0123"}));
}
if(c == ':' || c == '-')
{
return err(format_underline("[error] bad datetime: invalid format",
{{std::addressof(loc), "here"}},
{"pass: 1979-05-27T07:32:00-07:00, 1979-05-27 07:32:00.999999Z",
"fail: 1979-05-27T7:32:00-7:00, 1979-05-27 7:32-00:30"}));
}
if(c == '.' || c == 'e' || c == 'E')
{
return err(format_underline("[error] bad float: invalid format",
{{std::addressof(loc), "here"}},
{"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
"fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
}
}
return ok(value_t::integer);
}
if(loc.iter() != loc.end() && *loc.iter() == '.')
{
return err(format_underline("[error] bad float: invalid format",
{{std::addressof(loc), "integer part required before this"}},
{"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
"fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
}
if(loc.iter() != loc.end() && *loc.iter() == '_')
{
return err(format_underline("[error] bad number: `_` should be surrounded by digits",
{{std::addressof(loc), "`_` is not surrounded by digits"}},
{"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
"fail: 1__000, 0123"}));
}
return err(format_underline("[error] bad format: unknown value appeared",
{{std::addressof(loc), "here"}}));
} }
template<typename Container> template<typename Container>
value_t guess_value_type(const location<Container>& loc) result<value_t, std::string> guess_value_type(const location<Container>& loc)
{ {
switch(*loc.iter()) switch(*loc.iter())
{ {
case '"' : {return value_t::String; } case '"' : {return ok(value_t::string); }
case '\'': {return value_t::String; } case '\'': {return ok(value_t::string); }
case 't' : {return value_t::Boolean;} case 't' : {return ok(value_t::boolean); }
case 'f' : {return value_t::Boolean;} case 'f' : {return ok(value_t::boolean); }
case '[' : {return value_t::Array; } case '[' : {return ok(value_t::array); }
case '{' : {return value_t::Table; } case '{' : {return ok(value_t::table); }
case 'i' : {return value_t::Float; } // inf. case 'i' : {return ok(value_t::floating);} // inf.
case 'n' : {return value_t::Float; } // nan. case 'n' : {return ok(value_t::floating);} // nan.
default : {return guess_number_type(loc);} default : {return guess_number_type(loc);}
} }
} }
template<typename Container> template<typename Value, typename Container>
result<value, std::string> parse_value(location<Container>& loc) result<Value, std::string> parse_value(location<Container>& loc)
{ {
using value_type = Value;
const auto first = loc.iter(); const auto first = loc.iter();
if(first == loc.end()) if(first == loc.end())
{ {
@@ -1459,18 +1593,23 @@ result<value, std::string> parse_value(location<Container>& loc)
{{std::addressof(loc), ""}})); {{std::addressof(loc), ""}}));
} }
switch(guess_value_type(loc)) const auto type = guess_value_type(loc);
if(!type)
{ {
case value_t::Boolean : {return parse_boolean(loc); } return err(type.unwrap_err());
case value_t::Integer : {return parse_integer(loc); } }
case value_t::Float : {return parse_floating(loc); } switch(type.unwrap())
case value_t::String : {return parse_string(loc); } {
case value_t::OffsetDatetime : {return parse_offset_datetime(loc);} case value_t::boolean : {return parse_boolean(loc); }
case value_t::LocalDatetime : {return parse_local_datetime(loc); } case value_t::integer : {return parse_integer(loc); }
case value_t::LocalDate : {return parse_local_date(loc); } case value_t::floating : {return parse_floating(loc); }
case value_t::LocalTime : {return parse_local_time(loc); } case value_t::string : {return parse_string(loc); }
case value_t::Array : {return parse_array(loc); } case value_t::offset_datetime: {return parse_offset_datetime(loc);}
case value_t::Table : {return parse_inline_table(loc); } case value_t::local_datetime : {return parse_local_datetime(loc); }
case value_t::local_date : {return parse_local_date(loc); }
case value_t::local_time : {return parse_local_time(loc); }
case value_t::array : {return parse_array<value_type>(loc); }
case value_t::table : {return parse_inline_table<value_type>(loc);}
default: default:
{ {
const auto msg = format_underline("[error] toml::parse_value: " const auto msg = format_underline("[error] toml::parse_value: "
@@ -1594,13 +1733,17 @@ parse_array_table_key(location<Container>& loc)
} }
// parse table body (key-value pairs until the iter hits the next [tablekey]) // parse table body (key-value pairs until the iter hits the next [tablekey])
template<typename Container> template<typename Value, typename Container>
result<table, std::string> parse_ml_table(location<Container>& loc) result<typename Value::table_type, std::string>
parse_ml_table(location<Container>& loc)
{ {
using value_type = Value;
using table_type = typename value_type::table_type;
const auto first = loc.iter(); const auto first = loc.iter();
if(first == loc.end()) if(first == loc.end())
{ {
return ok(toml::table{}); return ok(table_type{});
} }
// XXX at lest one newline is needed. // XXX at lest one newline is needed.
@@ -1608,7 +1751,7 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>; sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
skip_line::invoke(loc); skip_line::invoke(loc);
table tab; table_type tab;
while(loc.iter() != loc.end()) while(loc.iter() != loc.end())
{ {
lex_ws::invoke(loc); lex_ws::invoke(loc);
@@ -1624,11 +1767,11 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
return ok(tab); return ok(tab);
} }
if(const auto kv = parse_key_value_pair(loc)) if(const auto kv = parse_key_value_pair<value_type>(loc))
{ {
const std::vector<key>& keys = kv.unwrap().first.first; const std::vector<key>& keys = kv.unwrap().first.first;
const region<Container>& key_reg = kv.unwrap().first.second; const region<Container>& key_reg = kv.unwrap().first.second;
const value& val = kv.unwrap().second; const value_type& val = kv.unwrap().second;
const auto inserted = const auto inserted =
insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg); insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg);
if(!inserted) if(!inserted)
@@ -1673,18 +1816,59 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
return ok(tab); return ok(tab);
} }
template<typename Container> template<typename Value, typename Container>
result<table, std::string> parse_toml_file(location<Container>& loc) result<Value, std::string> parse_toml_file(location<Container>& loc)
{ {
using value_type = Value;
using table_type = typename value_type::table_type;
const auto first = loc.iter(); const auto first = loc.iter();
if(first == loc.end()) if(first == loc.end())
{ {
return ok(toml::table{}); return ok(value_type(table_type{}));
} }
table data; // put the first line as a region of a file
const region<Container> file(loc, loc.iter(),
std::find(loc.iter(), loc.end(), '\n'));
// The first successive comments that are separated from the first value
// by an empty line are for a file itself.
// ```toml
// # this is a comment for a file.
//
// key = "the first value"
// ```
// ```toml
// # this is a comment for "the first value".
// key = "the first value"
// ```
std::vector<std::string> comments;
using lex_first_comments = sequence<
repeat<sequence<maybe<lex_ws>, lex_comment, lex_newline>, at_least<1>>,
sequence<maybe<lex_ws>, lex_newline>
>;
if(const auto token = lex_first_comments::invoke(loc))
{
location<std::string> inner_loc(loc.name(), token.unwrap().str());
while(inner_loc.iter() != inner_loc.end())
{
maybe<lex_ws>::invoke(inner_loc); // remove ws if exists
if(lex_newline::invoke(inner_loc))
{
assert(inner_loc.iter() == inner_loc.end());
break; // empty line found.
}
auto com = lex_comment::invoke(inner_loc).unwrap().str();
com.erase(com.begin()); // remove # sign
comments.push_back(std::move(com));
lex_newline::invoke(inner_loc);
}
}
table_type data;
// root object is also a table, but without [tablename] // root object is also a table, but without [tablename]
if(auto tab = parse_ml_table(loc)) if(auto tab = parse_ml_table<value_type>(loc))
{ {
data = std::move(tab.unwrap()); data = std::move(tab.unwrap());
} }
@@ -1700,14 +1884,14 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
// message. // message.
if(const auto tabkey = parse_array_table_key(loc)) if(const auto tabkey = parse_array_table_key(loc))
{ {
const auto tab = parse_ml_table(loc); const auto tab = parse_ml_table<value_type>(loc);
if(!tab){return err(tab.unwrap_err());} if(!tab){return err(tab.unwrap_err());}
const auto& keys = tabkey.unwrap().first; const auto& keys = tabkey.unwrap().first;
const auto& reg = tabkey.unwrap().second; const auto& reg = tabkey.unwrap().second;
const auto inserted = insert_nested_key(data, const auto inserted = insert_nested_key(data,
toml::value(tab.unwrap(), reg), value_type(tab.unwrap(), reg),
keys.begin(), keys.end(), reg, keys.begin(), keys.end(), reg,
/*is_array_of_table=*/ true); /*is_array_of_table=*/ true);
if(!inserted) {return err(inserted.unwrap_err());} if(!inserted) {return err(inserted.unwrap_err());}
@@ -1716,14 +1900,14 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
} }
if(const auto tabkey = parse_table_key(loc)) if(const auto tabkey = parse_table_key(loc))
{ {
const auto tab = parse_ml_table(loc); const auto tab = parse_ml_table<value_type>(loc);
if(!tab){return err(tab.unwrap_err());} if(!tab){return err(tab.unwrap_err());}
const auto& keys = tabkey.unwrap().first; const auto& keys = tabkey.unwrap().first;
const auto& reg = tabkey.unwrap().second; const auto& reg = tabkey.unwrap().second;
const auto inserted = insert_nested_key(data, const auto inserted = insert_nested_key(data,
toml::value(tab.unwrap(), reg), keys.begin(), keys.end(), reg); value_type(tab.unwrap(), reg), keys.begin(), keys.end(), reg);
if(!inserted) {return err(inserted.unwrap_err());} if(!inserted) {return err(inserted.unwrap_err());}
continue; continue;
@@ -1731,13 +1915,23 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
return err(format_underline("[error]: toml::parse_toml_file: " return err(format_underline("[error]: toml::parse_toml_file: "
"unknown line appeared", {{std::addressof(loc), "unknown format"}})); "unknown line appeared", {{std::addressof(loc), "unknown format"}}));
} }
return ok(data);
Value v(std::move(data), file);
v.comments() = comments;
return ok(std::move(v));
} }
} // detail } // detail
inline table parse(std::istream& is, std::string fname = "unknown file") template<typename Comment = ::toml::discard_comments,
template<typename ...> class Table = std::unordered_map,
template<typename ...> class Array = std::vector>
basic_value<Comment, Table, Array>
parse(std::istream& is, const std::string& fname = "unknown file")
{ {
using value_type = basic_value<Comment, Table, Array>;
const auto beg = is.tellg(); const auto beg = is.tellg();
is.seekg(0, std::ios::end); is.seekg(0, std::ios::end);
const auto end = is.tellg(); const auto end = is.tellg();
@@ -1745,7 +1939,8 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
is.seekg(beg); is.seekg(beg);
// read whole file as a sequence of char // read whole file as a sequence of char
std::vector<char> letters(fsize); assert(fsize >= 0);
std::vector<char> letters(static_cast<std::size_t>(fsize));
is.read(letters.data(), fsize); is.read(letters.data(), fsize);
detail::location<std::vector<char>> detail::location<std::vector<char>>
@@ -1767,7 +1962,7 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
} }
} }
const auto data = detail::parse_toml_file(loc); const auto data = detail::parse_toml_file<value_type>(loc);
if(!data) if(!data)
{ {
throw syntax_error(data.unwrap_err()); throw syntax_error(data.unwrap_err());
@@ -1775,14 +1970,17 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
return data.unwrap(); return data.unwrap();
} }
inline table parse(const std::string& fname) template<typename Comment = ::toml::discard_comments,
template<typename ...> class Table = std::unordered_map,
template<typename ...> class Array = std::vector>
inline basic_value<Comment, Table, Array> parse(const std::string& fname)
{ {
std::ifstream ifs(fname.c_str(), std::ios_base::binary); std::ifstream ifs(fname.c_str(), std::ios_base::binary);
if(!ifs.good()) if(!ifs.good())
{ {
throw std::runtime_error("toml::parse: file open error -> " + fname); throw std::runtime_error("toml::parse: file open error -> " + fname);
} }
return parse(ifs, fname); return parse<Comment, Table, Array>(ifs, fname);
} }
} // toml } // toml

View File

@@ -9,6 +9,7 @@
#include <initializer_list> #include <initializer_list>
#include <iterator> #include <iterator>
#include <iomanip> #include <iomanip>
#include <cassert>
namespace toml namespace toml
{ {
@@ -53,9 +54,7 @@ struct region_base
// number of characters in the line after the region // number of characters in the line after the region
virtual std::size_t after() const noexcept {return 0;} virtual std::size_t after() const noexcept {return 0;}
virtual std::string comment_before() const {return "";} // just before virtual std::vector<std::string> comments()const {return {};}
virtual std::string comment_inline() const {return "";} // in the same line
virtual std::string comment() const {return "";} // concatenate
// ```toml // ```toml
// # comment_before // # comment_before
// key = "value" # comment_inline // key = "value" # comment_inline
@@ -71,6 +70,7 @@ template<typename Container>
struct location final : public region_base struct location final : public region_base
{ {
using const_iterator = typename Container::const_iterator; using const_iterator = typename Container::const_iterator;
using difference_type = typename const_iterator::difference_type;
using source_ptr = std::shared_ptr<const Container>; using source_ptr = std::shared_ptr<const Container>;
static_assert(std::is_same<char, typename Container::value_type>::value,""); static_assert(std::is_same<char, typename Container::value_type>::value,"");
@@ -104,15 +104,17 @@ struct location final : public region_base
// to the location changes the point to look. So an overload of `iter()` // to the location changes the point to look. So an overload of `iter()`
// which returns mutable reference is removed and `advance()`, `retrace()` // which returns mutable reference is removed and `advance()`, `retrace()`
// and `reset()` is added. // and `reset()` is added.
void advance(std::size_t n = 1) noexcept void advance(difference_type n = 1) noexcept
{ {
this->line_number_ += std::count(this->iter_, this->iter_ + n, '\n'); this->line_number_ += static_cast<std::size_t>(
std::count(this->iter_, std::next(this->iter_, n), '\n'));
this->iter_ += n; this->iter_ += n;
return; return;
} }
void retrace(std::size_t n = 1) noexcept void retrace(difference_type n = 1) noexcept
{ {
this->line_number_ -= std::count(this->iter_ - n, this->iter_, '\n'); this->line_number_ -= static_cast<std::size_t>(
std::count(std::prev(this->iter_, n), this->iter_, '\n'));
this->iter_ -= n; this->iter_ -= n;
return; return;
} }
@@ -122,11 +124,13 @@ struct location final : public region_base
// iterators and returns a negative value if `first > last`. // iterators and returns a negative value if `first > last`.
if(0 <= std::distance(rollback, this->iter_)) // rollback < iter if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
{ {
this->line_number_ -= std::count(rollback, this->iter_, '\n'); this->line_number_ -= static_cast<std::size_t>(
std::count(rollback, this->iter_, '\n'));
} }
else // iter < rollback [[unlikely]] else // iter < rollback [[unlikely]]
{ {
this->line_number_ += std::count(this->iter_, rollback, '\n'); this->line_number_ += static_cast<std::size_t>(
std::count(this->iter_, rollback, '\n'));
} }
this->iter_ = rollback; this->iter_ = rollback;
return; return;
@@ -163,11 +167,15 @@ struct location final : public region_base
} }
std::size_t before() const noexcept override std::size_t before() const noexcept override
{ {
return std::distance(this->line_begin(), this->iter()); const auto sz = std::distance(this->line_begin(), this->iter());
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
std::size_t after() const noexcept override std::size_t after() const noexcept override
{ {
return std::distance(this->iter(), this->line_end()); const auto sz = std::distance(this->iter(), this->line_end());
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
source_ptr const& source() const& noexcept {return source_;} source_ptr const& source() const& noexcept {return source_;}
@@ -251,15 +259,21 @@ struct region final : public region_base
std::size_t size() const noexcept override std::size_t size() const noexcept override
{ {
return std::distance(first_, last_); const auto sz = std::distance(first_, last_);
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
std::size_t before() const noexcept override std::size_t before() const noexcept override
{ {
return std::distance(this->line_begin(), this->first()); const auto sz = std::distance(this->line_begin(), this->first());
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
std::size_t after() const noexcept override std::size_t after() const noexcept override
{ {
return std::distance(this->last(), this->line_end()); const auto sz = std::distance(this->last(), this->line_end());
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
bool contain_newline() const noexcept bool contain_newline() const noexcept
@@ -288,90 +302,112 @@ struct region final : public region_base
std::string name() const override {return source_name_;} std::string name() const override {return source_name_;}
std::string comment_before() const override std::vector<std::string> comments() const override
{ {
auto iter = this->line_begin(); // points the first element // assuming the current region (`*this`) points a value.
std::vector<std::pair<decltype(iter), decltype(iter)>> comments; // ```toml
// a = "value"
// ^^^^^^^- this region
// ```
using rev_iter = std::reverse_iterator<const_iterator>;
std::vector<std::string> com{};
{
// find comments just before the current region.
// ```toml
// # this should be collected.
// # this also.
// a = value # not this.
// ```
// # this is a comment for `a`, not array elements.
// a = [1, 2, 3, 4, 5]
if(this->first() == std::find_if(this->line_begin(), this->first(),
[](const char c) noexcept -> bool {return c == '[' || c == '{';}))
{
auto iter = this->line_begin(); // points the first character
while(iter != this->begin()) while(iter != this->begin())
{ {
iter = std::prev(iter); iter = std::prev(iter);
using rev_iter = std::reverse_iterator<decltype(iter)>;
auto line_before = std::find(rev_iter(iter), rev_iter(this->begin()),
'\n').base();
// range [line_before, iter) represents the previous line
auto comment_found = std::find(line_before, iter, '#'); // range [line_start, iter) represents the previous line
if(iter != comment_found && std::all_of(line_before, comment_found, const auto line_start = std::find(
rev_iter(iter), rev_iter(this->begin()), '\n').base();
const auto comment_found = std::find(line_start, iter, '#');
if(comment_found == iter)
{
break; // comment not found.
}
// exclude the following case.
// > a = "foo" # comment // <-- this is not a comment for b but a.
// > b = "current value"
if(std::all_of(line_start, comment_found,
[](const char c) noexcept -> bool { [](const char c) noexcept -> bool {
return c == ' ' || c == '\t'; return c == ' ' || c == '\t';
})) }))
{ {
// the line before this range contains only a comment. // unwrap the first '#' by std::next.
comments.push_back(std::make_pair(comment_found, iter)); auto str = make_string(std::next(comment_found), iter);
if(str.back() == '\r') {str.pop_back();}
com.push_back(std::move(str));
} }
else else
{ {
break; break;
} }
iter = line_before; iter = line_start;
}
}
} }
std::string com; if(com.size() > 1)
for(auto i = comments.crbegin(), e = comments.crend(); i!=e; ++i)
{ {
if(i != comments.crbegin()) {com += '\n';} std::reverse(com.begin(), com.end());
com += std::string(i->first, i->second);
}
return com;
} }
std::string comment_inline() const override
{ {
if(this->contain_newline()) // find comments just after the current region.
{ // ```toml
std::string com; // # not this.
// check both the first and the last line. // a = value # this one.
const auto first_line_end = // a = [ # not this (technically difficult)
std::find(this->line_begin(), this->last(), '\n'); //
const auto first_comment_found = // ] # and this.
std::find(this->line_begin(), first_line_end, '#'); // ```
// The reason why it's difficult is that it requires parsing in the
if(first_comment_found != first_line_end) // following case.
{ // ```toml
com += std::string(first_comment_found, first_line_end); // a = [ 10 # this comment is for `10`. not for `a` but `a[0]`.
} // # ...
// ] # this is apparently a comment for a.
const auto last_comment_found = //
std::find(this->last(), this->line_end(), '#'); // b = [
if(last_comment_found != this->line_end()) // 3.14 ] # there is no way to add a comment to `3.14` currently.
{ //
if(!com.empty()){com += '\n';} // c = [
com += std::string(last_comment_found, this->line_end()); // 3.14 # do this if you need a comment here.
} // ]
return com; // ```
}
const auto comment_found = const auto comment_found =
std::find(this->line_begin(), this->line_end(), '#'); std::find(this->last(), this->line_end(), '#');
return std::string(comment_found, this->line_end()); if(comment_found != this->line_end()) // '#' found
}
std::string comment() const override
{ {
std::string com_bef = this->comment_before(); // table = {key = "value"} # what is this for?
std::string com_inl = this->comment_inline(); // the above comment is not for "value", but {key="value"}.
if(!com_bef.empty() && !com_inl.empty()) if(comment_found == std::find_if(this->last(), comment_found,
[](const char c) noexcept -> bool {
return !(c == ' ' || c == '\t' || c == ',');
}))
{ {
com_bef += '\n'; // unwrap the first '#' by std::next.
return com_bef + com_inl; auto str = make_string(std::next(comment_found), this->line_end());
if(str.back() == '\r') {str.pop_back();}
com.push_back(std::move(str));
} }
else if(com_bef.empty())
{
return com_inl;
} }
else
{
return com_bef;
} }
return com;
} }
private: private:
@@ -383,47 +419,42 @@ struct region final : public region_base
// to show a better error message. // to show a better error message.
inline std::string format_underline(const std::string& message, inline std::string format_underline(const std::string& message,
std::vector<std::pair<region_base const*, std::string>> reg_com, const std::vector<std::pair<region_base const*, std::string>>& reg_com,
std::vector<std::string> helps = {}) const std::vector<std::string>& helps = {})
{ {
assert(!reg_com.empty()); assert(!reg_com.empty());
#ifdef _WIN32 const auto line_num_width = static_cast<int>(std::max_element(
const auto newline = "\r\n"; reg_com.begin(), reg_com.end(),
#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& lhs,
std::pair<region_base const*, std::string> const& rhs) std::pair<region_base const*, std::string> const& rhs)
{ {
return lhs.first->line_num().size() < rhs.first->line_num().size(); return lhs.first->line_num().size() < rhs.first->line_num().size();
} }
)->first->line_num().size(); )->first->line_num().size());
std::ostringstream retval; std::ostringstream retval;
retval << message << newline; retval << message << '\n';
for(std::size_t i=0; i<reg_com.size(); ++i) for(auto iter = reg_com.begin(); iter != reg_com.end(); ++iter)
{ {
if(i!=0 && reg_com.at(i-1).first->name() == reg_com.at(i).first->name()) // if the filenames are the same, print "..."
if(iter != reg_com.begin() &&
std::prev(iter)->first->name() == iter->first->name())
{ {
retval << newline << " ..." << newline; retval << "\n ...\n";
} }
else else // if filename differs, print " --> filename.toml"
{ {
if(i != 0) {retval << newline;} if(iter != reg_com.begin()) {retval << '\n';}
retval << " --> " << reg_com.at(i).first->name() << newline; retval << " --> " << iter->first->name() << '\n';
} }
const region_base* const reg = iter->first;
const region_base* const reg = reg_com.at(i).first; const std::string& comment = iter->second;
const std::string& comment = reg_com.at(i).second;
retval << ' ' << std::setw(line_num_width) << reg->line_num(); retval << ' ' << std::setw(line_num_width) << reg->line_num();
retval << " | " << reg->line() << newline; retval << " | " << reg->line() << '\n';
retval << make_string(line_num_width + 1, ' '); retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
retval << " | " << make_string(reg->before(), ' '); retval << " | " << make_string(reg->before(), ' ');
if(reg->size() == 1) if(reg->size() == 1)
@@ -440,20 +471,18 @@ inline std::string format_underline(const std::string& message,
const auto underline_len = std::min(reg->size(), reg->line().size()); const auto underline_len = std::min(reg->size(), reg->line().size());
retval << make_string(underline_len, '~'); retval << make_string(underline_len, '~');
} }
retval << ' '; retval << ' ';
retval << comment; retval << comment;
} }
if(helps.size() != 0) if(!helps.empty())
{ {
retval << newline; retval << '\n';
retval << make_string(line_num_width + 1, ' '); retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
retval << " | "; retval << " | ";
for(const auto help : helps) for(const auto help : helps)
{ {
retval << newline; retval << "\nHint: ";
retval << "Hint: ";
retval << help; retval << help;
} }
} }

View File

@@ -10,9 +10,26 @@
namespace toml namespace toml
{ {
template<typename Comment,
template<typename ...> class Table,
template<typename ...> class Array>
struct serializer struct serializer
{ {
serializer(const std::size_t w = 80, using value_type = basic_value<Comment, Table, Array>;
using key_type = typename value_type::key_type ;
using comment_type = typename value_type::comment_type ;
using boolean_type = typename value_type::boolean_type ;
using integer_type = typename value_type::integer_type ;
using floating_type = typename value_type::floating_type ;
using string_type = typename value_type::string_type ;
using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
serializer(const std::size_t w = 80u,
const int float_prec = std::numeric_limits<toml::floating>::max_digits10, const int float_prec = std::numeric_limits<toml::floating>::max_digits10,
const bool can_be_inlined = false, const bool can_be_inlined = false,
std::vector<toml::key> ks = {}) std::vector<toml::key> ks = {})
@@ -21,19 +38,20 @@ struct serializer
{} {}
~serializer() = default; ~serializer() = default;
std::string operator()(const toml::boolean& b) const std::string operator()(const boolean_type& b) const
{ {
return b ? "true" : "false"; return b ? "true" : "false";
} }
std::string operator()(const integer i) const std::string operator()(const integer_type i) const
{ {
return std::to_string(i); return std::to_string(i);
} }
std::string operator()(const toml::floating f) const std::string operator()(const floating_type f) const
{ {
const auto fmt = "%.*g"; const auto fmt = "%.*g";
const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f); const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f);
std::vector<char> buf(bsz + 1, '\0'); // +1 for null character(\0) // +1 for null character(\0)
std::vector<char> buf(static_cast<std::size_t>(bsz + 1), '\0');
std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f); std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f);
std::string token(buf.begin(), std::prev(buf.end())); std::string token(buf.begin(), std::prev(buf.end()));
@@ -41,16 +59,27 @@ struct serializer
{ {
token += '0'; token += '0';
} }
const auto e = std::find_if(token.cbegin(), token.cend(),
[](const char c) -> bool { const auto e = std::find_if(
return c == 'E' || c == 'e'; token.cbegin(), token.cend(), [](const char c) noexcept -> bool {
return c == 'e' || c == 'E';
}); });
if(e == token.cend()) const auto has_exponent = (token.cend() != e);
const auto has_fraction = (token.cend() != std::find(
token.cbegin(), token.cend(), '.'));
if(!has_exponent && !has_fraction)
{
// the resulting value does not have any float specific part!
token += ".0";
return token;
}
if(!has_exponent)
{ {
return token; // there is no exponent part. just return it. return token; // there is no exponent part. just return it.
} }
// zero-prefix in an exponent is not allowed in TOML. // zero-prefix in an exponent is NOT allowed in TOML.
// remove it if it exists. // remove it if it exists.
bool sign_exists = false; bool sign_exists = false;
std::size_t zero_prefix = 0; std::size_t zero_prefix = 0;
@@ -64,11 +93,12 @@ struct serializer
{ {
const auto offset = std::distance(token.cbegin(), e) + const auto offset = std::distance(token.cbegin(), e) +
(sign_exists ? 2 : 1); (sign_exists ? 2 : 1);
token.erase(offset, zero_prefix); token.erase(static_cast<typename std::string::size_type>(offset),
zero_prefix);
} }
return token; return token;
} }
std::string operator()(const string& s) const std::string operator()(const string_type& s) const
{ {
if(s.kind == string_t::basic) if(s.kind == string_t::basic)
{ {
@@ -130,37 +160,44 @@ struct serializer
} }
} }
std::string operator()(const local_date& d) const std::string operator()(const local_date_type& d) const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << d; oss << d;
return oss.str(); return oss.str();
} }
std::string operator()(const local_time& t) const std::string operator()(const local_time_type& t) const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << t; oss << t;
return oss.str(); return oss.str();
} }
std::string operator()(const local_datetime& dt) const std::string operator()(const local_datetime_type& dt) const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << dt; oss << dt;
return oss.str(); return oss.str();
} }
std::string operator()(const offset_datetime& odt) const std::string operator()(const offset_datetime_type& odt) const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << odt; oss << odt;
return oss.str(); return oss.str();
} }
std::string operator()(const array& v) const std::string operator()(const array_type& v) const
{ {
if(!v.empty() && v.front().is_table())// v is an array of tables if(!v.empty() && v.front().is_table())// v is an array of tables
{ {
// if it's not inlined, we need to add `[[table.key]]`. // if it's not inlined, we need to add `[[table.key]]`.
// but if it can be inlined, we need `table.key = [...]`. // but if it can be inlined,
// ```
// table.key = [
// {...},
// # comment
// {...},
// ]
// ```
if(this->can_be_inlined_) if(this->can_be_inlined_)
{ {
std::string token; std::string token;
@@ -169,37 +206,56 @@ struct serializer
token += this->serialize_key(keys_.back()); token += this->serialize_key(keys_.back());
token += " = "; token += " = ";
} }
bool width_exceeds = false; bool failed = false;
token += "[\n"; token += "[\n";
for(const auto& item : v) for(const auto& item : v)
{ {
const auto t = // if an element of the table has a comment, the table
this->make_inline_table(item.cast<value_t::Table>()); // cannot be inlined.
if(this->has_comment_inside(item.as_table()))
{
failed = true;
break;
}
for(const auto& c : item.comments())
{
token += '#';
token += c;
token += '\n';
}
const auto t = this->make_inline_table(item.as_table());
if(t.size() + 1 > width_ || // +1 for the last comma {...}, if(t.size() + 1 > width_ || // +1 for the last comma {...},
std::find(t.cbegin(), t.cend(), '\n') != t.cend()) std::find(t.cbegin(), t.cend(), '\n') != t.cend())
{ {
width_exceeds = true; failed = true;
break; break;
} }
token += t; token += t;
token += ",\n"; token += ",\n";
} }
if(!width_exceeds) if(!failed)
{ {
token += "]\n"; token += "]\n";
return token; return token;
} }
// if width_exceeds, serialize it as [[array.of.tables]]. // if failed, serialize them as [[array.of.tables]].
} }
std::string token; std::string token;
for(const auto& item : v) for(const auto& item : v)
{ {
for(const auto& c : item.comments())
{
token += '#';
token += c;
token += '\n';
}
token += "[["; token += "[[";
token += this->serialize_dotted_key(keys_); token += this->serialize_dotted_key(keys_);
token += "]]\n"; token += "]]\n";
token += this->make_multiline_table(item.cast<value_t::Table>()); token += this->make_multiline_table(item.as_table());
} }
return token; return token;
} }
@@ -208,7 +264,9 @@ struct serializer
return std::string("[]"); return std::string("[]");
} }
// not an array of tables. normal array. first, try to make it inline. // not an array of tables. normal array.
// first, try to make it inline if none of the elements have a comment.
if(!this->has_comment_inside(v))
{ {
const auto inl = this->make_inline_array(v); const auto inl = this->make_inline_array(v);
if(inl.size() < this->width_ && if(inl.size() < this->width_ &&
@@ -218,16 +276,54 @@ struct serializer
} }
} }
// if the length exceeds this->width_, print multiline array // if the length exceeds this->width_, print multiline array.
// key = [
// # ...
// 42,
// ...
// ]
std::string token; std::string token;
std::string current_line; std::string current_line;
token += "[\n"; token += "[\n";
for(const auto& item : v) for(const auto& item : v)
{ {
auto next_elem = toml::visit(*this, item); if(!item.comments().empty())
// newline between array-value and comma is not allowed {
if(next_elem.back() == '\n'){next_elem.pop_back();} // if comment exists, the element must be the only element in the line.
// e.g. the following is not allowed.
// ```toml
// array = [
// # comment for what?
// 1, 2, 3, 4, 5
// ]
// ```
if(!current_line.empty())
{
if(current_line.back() != '\n')
{
current_line += '\n';
}
token += current_line;
current_line.clear();
}
for(const auto& c : item.comments())
{
token += '#';
token += c;
token += '\n';
}
token += toml::visit(*this, item);
if(token.back() == '\n') {token.pop_back();}
token += ",\n";
continue;
}
std::string next_elem;
next_elem += toml::visit(*this, item);
// comma before newline.
if(next_elem.back() == '\n') {next_elem.pop_back();}
// if current line does not exceeds the width limit, continue.
if(current_line.size() + next_elem.size() + 1 < this->width_) if(current_line.size() + next_elem.size() + 1 < this->width_)
{ {
current_line += next_elem; current_line += next_elem;
@@ -235,12 +331,13 @@ struct serializer
} }
else if(current_line.empty()) else if(current_line.empty())
{ {
// the next elem cannot be within the width. // if current line was empty, force put the next_elem because
// next_elem is not splittable
token += next_elem; token += next_elem;
token += ",\n"; token += ",\n";
// keep current line empty // current_line is kept empty
} }
else // current_line has some tokens and it exceeds width else // reset current_line
{ {
assert(current_line.back() == ','); assert(current_line.back() == ',');
token += current_line; token += current_line;
@@ -258,9 +355,12 @@ struct serializer
return token; return token;
} }
std::string operator()(const table& v) const // templatize for any table-like container
std::string operator()(const table_type& v) const
{ {
if(this->can_be_inlined_) // if an element has a comment, then it can't be inlined.
// table = {# how can we write a comment for this? key = "value"}
if(this->can_be_inlined_ && !(this->has_comment_inside(v)))
{ {
std::string token; std::string token;
if(!this->keys_.empty()) if(!this->keys_.empty())
@@ -369,8 +469,27 @@ struct serializer
return retval; return retval;
} }
std::string make_inline_array(const array& v) const // if an element of a table or an array has a comment, it cannot be inlined.
bool has_comment_inside(const array_type& a) const noexcept
{ {
for(const auto& v : a)
{
if(!v.comments().empty()) {return true;}
}
return false;
}
bool has_comment_inside(const table_type& t) const noexcept
{
for(const auto& kv : t)
{
if(!kv.second.comments().empty()) {return true;}
}
return false;
}
std::string make_inline_array(const array_type& v) const
{
assert(!has_comment_inside(v));
std::string token; std::string token;
token += '['; token += '[';
bool is_first = true; bool is_first = true;
@@ -384,8 +503,9 @@ struct serializer
return token; return token;
} }
std::string make_inline_table(const table& v) const std::string make_inline_table(const table_type& v) const
{ {
assert(!has_comment_inside(v));
assert(this->can_be_inlined_); assert(this->can_be_inlined_);
std::string token; std::string token;
token += '{'; token += '{';
@@ -403,7 +523,7 @@ struct serializer
return token; return token;
} }
std::string make_multiline_table(const table& v) const std::string make_multiline_table(const table_type& v) const
{ {
std::string token; std::string token;
@@ -416,6 +536,15 @@ struct serializer
continue; continue;
} }
if(!kv.second.comments().empty())
{
for(const auto& c : kv.second.comments())
{
token += '#';
token += c;
token += '\n';
}
}
const auto key_and_sep = this->serialize_key(kv.first) + " = "; const auto key_and_sep = this->serialize_key(kv.first) + " = ";
const auto residual_width = (this->width_ > key_and_sep.size()) ? const auto residual_width = (this->width_ > key_and_sep.size()) ?
this->width_ - key_and_sep.size() : 0; this->width_ - key_and_sep.size() : 0;
@@ -460,12 +589,22 @@ struct serializer
// still inline tables only. // still inline tables only.
tmp += '\n'; tmp += '\n';
} }
if(!kv.second.comments().empty())
{
for(const auto& c : kv.second.comments())
{
token += '#';
token += c;
token += '\n';
}
}
token += tmp; token += tmp;
} }
return token; return token;
} }
bool is_array_of_tables(const value& v) const bool is_array_of_tables(const value_type& v) const
{ {
if(!v.is_array()) {return false;} if(!v.is_array()) {return false;}
const auto& a = v.as_array(); const auto& a = v.as_array();
@@ -480,45 +619,52 @@ struct serializer
std::vector<toml::key> keys_; std::vector<toml::key> keys_;
}; };
inline std::string template<typename C,
format(const value& v, std::size_t w = 80, template<typename ...> class M, template<typename ...> class V>
std::string
format(const basic_value<C, M, V>& v, std::size_t w = 80u,
int fprec = std::numeric_limits<toml::floating>::max_digits10, int fprec = std::numeric_limits<toml::floating>::max_digits10,
bool force_inline = false) bool force_inline = false)
{ {
// if value is a table, it is considered to be a root object. // if value is a table, it is considered to be a root object.
// the root object can't be an inline table. so pass false. otherwise, true. // the root object can't be an inline table.
return visit(serializer(w, fprec, (!v.is_table()) || force_inline), v); if(v.is_table())
} {
inline std::string std::ostringstream oss;
format(const table& t, std::size_t w = 80, if(!v.comments().empty())
int fprec = std::numeric_limits<toml::floating>::max_digits10, {
bool force_inline = false) for(const auto& c : v.comments())
{ {
return serializer(w, fprec, force_inline)(t); oss << '#' << c << '\n';
}
oss << '\n';
}
oss << visit(serializer<C, M, V>(w, fprec, false), v);
return oss.str();
}
return visit(serializer<C, M, V>(w, fprec, force_inline), v);
} }
template<typename charT, typename traits> template<typename charT, typename traits, typename C,
template<typename ...> class M, template<typename ...> class V>
std::basic_ostream<charT, traits>& std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const value& v) operator<<(std::basic_ostream<charT, traits>& os, const basic_value<C, M, V>& v)
{ {
// get status of std::setw(). // get status of std::setw().
const std::size_t w = os.width(); const auto w = static_cast<std::size_t>(os.width());
const int fprec = os.precision(); const int fprec = static_cast<int>(os.precision());
os.width(0); os.width(0);
if(!v.comments().empty())
{
for(const auto& c : v.comments())
{
os << '#' << c << '\n';
}
os << '\n';
}
// the root object can't be an inline table. so pass `false`. // the root object can't be an inline table. so pass `false`.
os << visit(serializer(w, fprec, false), v); os << visit(serializer<C, M, V>(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; return os;
} }

82
toml/source_location.hpp Normal file
View File

@@ -0,0 +1,82 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_SOURCE_LOCATION_HPP
#define TOML11_SOURCE_LOCATION_HPP
#include "region.hpp"
#include <cstdint>
namespace toml
{
// A struct to contain location in a toml file.
// The interface imitates std::experimental::source_location,
// but not completely the same.
//
// It would be constructed by toml::value. It can be used to generate
// user-defined error messages.
//
// - std::uint_least32_t line() const noexcept
// - returns the line number where the region is on.
// - std::uint_least32_t column() const noexcept
// - returns the column number where the region starts.
// - std::uint_least32_t region() const noexcept
// - returns the size of the region.
//
// +-- line() +-- region of interest (region() == 9)
// v .---+---.
// 12 | value = "foo bar"
// ^
// +-- column()
//
// - std::string const& file_name() const noexcept;
// - name of the file.
// - std::string const& line_str() const noexcept;
// - the whole line that contains the region of interest.
//
struct source_location
{
public:
source_location()
: line_num_(0), column_num_(0), region_size_(0),
file_name_("unknown file"), line_str_("")
{}
explicit source_location(const detail::region_base* reg)
: line_num_(0), column_num_(0), region_size_(0),
file_name_("unknown file"), line_str_("")
{
if(reg)
{
line_num_ = static_cast<std::uint_least32_t>(std::stoul(reg->line_num()));
column_num_ = static_cast<std::uint_least32_t>(reg->before() + 1);
region_size_ = static_cast<std::uint_least32_t>(reg->size());
file_name_ = reg->name();
line_str_ = reg->line();
}
}
~source_location() = default;
source_location(source_location const&) = default;
source_location(source_location &&) = default;
source_location& operator=(source_location const&) = default;
source_location& operator=(source_location &&) = default;
std::uint_least32_t line() const noexcept {return line_num_;}
std::uint_least32_t column() const noexcept {return column_num_;}
std::uint_least32_t region() const noexcept {return region_size_;}
std::string const& file_name() const noexcept {return file_name_;}
std::string const& line_str() const noexcept {return line_str_;}
private:
std::uint_least32_t line_num_;
std::uint_least32_t column_num_;
std::uint_least32_t region_size_;
std::string file_name_;
std::string line_str_;
};
} // toml
#endif// TOML11_SOURCE_LOCATION_HPP

View File

@@ -6,18 +6,20 @@
#include <utility> #include <utility>
#include <chrono> #include <chrono>
#include <tuple> #include <tuple>
#include <string>
#if __cplusplus >= 201703L
#if __has_include(<string_view>)
#include <string_view>
#endif // has_include(<string_view>)
#endif // cplusplus >= C++17
namespace toml namespace toml
{ {
template<typename C, template<typename ...> class T, template<typename ...> class A>
class value; // forward decl class basic_value;
namespace detail namespace detail
{ {
template<typename T>
using unwrap_t = typename std::decay<T>::type;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// check whether type T is a kind of container/map class // check whether type T is a kind of container/map class
@@ -48,12 +50,22 @@ struct has_resize_method_impl
template<typename T> static std::false_type check(...); template<typename T> static std::false_type check(...);
}; };
struct is_comparable_impl
{
template<typename T> static std::true_type check(decltype(std::declval<T>() < std::declval<T>())*);
template<typename T> static std::false_type check(...);
};
struct has_from_toml_method_impl struct has_from_toml_method_impl
{ {
template<typename T> template<typename T, typename C,
template<typename ...> class Tb, template<typename ...> class A>
static std::true_type check( static std::true_type check(
decltype(std::declval<T>().from_toml(std::declval<::toml::value>()))*); decltype(std::declval<T>().from_toml(
template<typename T> std::declval<::toml::basic_value<C, Tb, A>>()))*);
template<typename T, typename C,
template<typename ...> class Tb, template<typename ...> class A>
static std::false_type check(...); static std::false_type check(...);
}; };
struct has_into_toml_method_impl struct has_into_toml_method_impl
@@ -80,11 +92,14 @@ template<typename T>
struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){}; 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> template<typename T>
struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){};
template<typename T, typename C,
template<typename ...> class Tb, template<typename ...> class A>
struct has_from_toml_method struct has_from_toml_method
: decltype(has_from_toml_method_impl::check<T>(nullptr)){}; : decltype(has_from_toml_method_impl::check<T, C, Tb, A>(nullptr)){};
template<typename T> template<typename T>
struct has_into_toml_method struct has_into_toml_method
: decltype(has_into_toml_method_impl::check<T>(nullptr)){}; : decltype(has_into_toml_method_impl::check<T>(nullptr)){};
@@ -114,7 +129,7 @@ template<typename T>
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{}; struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// normal type checker // type checkers
template<typename T> struct is_std_pair : std::false_type{}; template<typename T> struct is_std_pair : std::false_type{};
template<typename T1, typename T2> template<typename T1, typename T2>
@@ -128,6 +143,42 @@ template<typename T> struct is_chrono_duration: std::false_type{};
template<typename Rep, typename Period> template<typename Rep, typename Period>
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{}; struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
template<typename T>
struct is_map : conjunction< // map satisfies all the following conditions
has_iterator<T>, // has T::iterator
has_value_type<T>, // has T::value_type
has_key_type<T>, // has T::key_type
has_mapped_type<T> // has T::mapped_type
>{};
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>>, // not a map
negation<std::is_same<T, std::string>>, // not a std::string
#if __cplusplus >= 201703L
negation<std::is_same<T, std::string_view>>, // not a std::string_view
#endif
has_iterator<T>, // has T::iterator
has_value_type<T> // has T::value_type
>{};
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>{};
template<typename T>
struct is_basic_value: std::false_type{};
template<typename T> struct is_basic_value<T&> : is_basic_value<T>{};
template<typename T> struct is_basic_value<T const&> : is_basic_value<T>{};
template<typename T> struct is_basic_value<T volatile&> : is_basic_value<T>{};
template<typename T> struct is_basic_value<T const volatile&> : is_basic_value<T>{};
template<typename C, template<typename ...> class M, template<typename ...> class V>
struct is_basic_value<::toml::basic_value<C, M, V>>: std::true_type{};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// C++14 index_sequence // C++14 index_sequence
@@ -154,6 +205,11 @@ struct index_sequence_maker<0>
template<std::size_t N> template<std::size_t N>
using make_index_sequence = typename index_sequence_maker<N-1>::type; using make_index_sequence = typename index_sequence_maker<N-1>::type;
// ---------------------------------------------------------------------------
// C++14 enable_if_t
template<bool B, typename T>
using enable_if_t = typename std::enable_if<B, T>::type;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// return_type_of_t // return_type_of_t

View File

@@ -5,55 +5,51 @@
#include "datetime.hpp" #include "datetime.hpp"
#include "string.hpp" #include "string.hpp"
#include "traits.hpp" #include "traits.hpp"
#include "comments.hpp"
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#if __cplusplus >= 201703L
#if __has_include(<string_view>)
#include <string_view>
#endif
#endif
namespace toml namespace toml
{ {
using character = char; template<typename Comment, // discard/preserve_comment
template<typename ...> class Table, // map-like class
template<typename ...> class Array> // vector-like class
class basic_value;
class value; using character = char;
using key = std::string; using key = std::string;
using Boolean = bool; using boolean = bool;
using Integer = std::int64_t; using integer = std::int64_t;
using Float = double; using floating = double; // "float" is a keyward, cannot use it here.
using String = ::toml::string; // the following stuffs are structs defined here, so aliases are not needed.
using Datetime = offset_datetime; // - string
using OffsetDatetime = offset_datetime; // - offset_datetime
using LocalDatetime = local_datetime; // - offset_datetime
using LocalDate = local_date; // - local_datetime
using LocalTime = local_time; // - local_date
using Array = std::vector<value>; // - local_time
using Table = std::unordered_map<key, value>;
// alias for snake_case, consistency with STL/Boost, toml::key, toml::value // default toml::value and default array/table. these are defined after defining
using boolean = Boolean; // basic_value itself.
using integer = Integer; // using value = basic_value<discard_comments, std::unordered_map, std::vector>;
using floating = Float; // XXX `float` is keyword. we can't use it here // using array = typename value::array_type;
using array = Array; // using table = typename value::table_type;
using table = Table;
enum class value_t : std::uint8_t enum class value_t : std::uint8_t
{ {
Empty = 0, empty = 0,
Boolean = 1, boolean = 1,
Integer = 2, integer = 2,
Float = 3, floating = 3,
String = 4, string = 4,
OffsetDatetime = 5, offset_datetime = 5,
LocalDatetime = 6, local_datetime = 6,
LocalDate = 7, local_date = 7,
LocalTime = 8, local_time = 8,
Array = 9, array = 9,
Table = 10, table = 10,
Unknown = 255,
}; };
template<typename charT, typename traits> template<typename charT, typename traits>
@@ -62,27 +58,27 @@ operator<<(std::basic_ostream<charT, traits>& os, value_t t)
{ {
switch(t) switch(t)
{ {
case toml::value_t::Boolean : os << "boolean"; return os; case value_t::boolean : os << "boolean"; return os;
case toml::value_t::Integer : os << "integer"; return os; case value_t::integer : os << "integer"; return os;
case toml::value_t::Float : os << "float"; return os; case value_t::floating : os << "floating"; return os;
case toml::value_t::String : os << "string"; return os; case value_t::string : os << "string"; return os;
case toml::value_t::OffsetDatetime: os << "offset_datetime"; return os; case value_t::offset_datetime : os << "offset_datetime"; return os;
case toml::value_t::LocalDatetime : os << "local_datetime"; return os; case value_t::local_datetime : os << "local_datetime"; return os;
case toml::value_t::LocalDate : os << "local_date"; return os; case value_t::local_date : os << "local_date"; return os;
case toml::value_t::LocalTime : os << "local_time"; return os; case value_t::local_time : os << "local_time"; return os;
case toml::value_t::Array : os << "array"; return os; case value_t::array : os << "array"; return os;
case toml::value_t::Table : os << "table"; return os; case value_t::table : os << "table"; return os;
case toml::value_t::Empty : os << "empty"; return os; case value_t::empty : os << "empty"; return os;
case toml::value_t::Unknown : os << "unknown"; return os; default : os << "unknown"; return os;
default : os << "nothing"; return os;
} }
} }
template<typename charT = character, typename traits = std::char_traits<charT>, template<typename charT = char,
typename traits = std::char_traits<charT>,
typename alloc = std::allocator<charT>> typename alloc = std::allocator<charT>>
inline std::basic_string<charT, traits, alloc> stringize(value_t t) inline std::basic_string<charT, traits, alloc> stringize(value_t t)
{ {
std::ostringstream oss; std::basic_ostringstream<charT, traits, alloc> oss;
oss << t; oss << t;
return oss.str(); return oss.str();
} }
@@ -90,60 +86,47 @@ inline std::basic_string<charT, traits, alloc> stringize(value_t t)
namespace detail namespace detail
{ {
template<typename T> // helper to define a type that represents a value_t value.
constexpr inline value_t check_type() template<value_t V>
{ using value_t_constant = std::integral_constant<value_t, V>;
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) // meta-function that convertes from value_t to the exact toml type that corresponds to.
{ // It takes toml::basic_value type because array and table types depend on it.
return vt != value_t::Unknown; template<value_t t, typename Value> struct enum_to_type {using type = void ;};
} template<typename Value> struct enum_to_type<value_t::empty , Value>{using type = void ;};
template<typename Value> struct enum_to_type<value_t::boolean , Value>{using type = boolean ;};
template<typename Value> struct enum_to_type<value_t::integer , Value>{using type = integer ;};
template<typename Value> struct enum_to_type<value_t::floating , Value>{using type = floating ;};
template<typename Value> struct enum_to_type<value_t::string , Value>{using type = string ;};
template<typename Value> struct enum_to_type<value_t::offset_datetime, Value>{using type = offset_datetime ;};
template<typename Value> struct enum_to_type<value_t::local_datetime , Value>{using type = local_datetime ;};
template<typename Value> struct enum_to_type<value_t::local_date , Value>{using type = local_date ;};
template<typename Value> struct enum_to_type<value_t::local_time , Value>{using type = local_time ;};
template<typename Value> struct enum_to_type<value_t::array , Value>{using type = typename Value::array_type;};
template<typename Value> struct enum_to_type<value_t::table , Value>{using type = typename Value::table_type;};
template<value_t t> struct toml_default_type; // meta-function that converts from an exact toml type to the enum that corresponds to.
template<> struct toml_default_type<value_t::Boolean > {typedef boolean type;}; template<typename T, typename Value>
template<> struct toml_default_type<value_t::Integer > {typedef integer type;}; struct type_to_enum : std::conditional<
template<> struct toml_default_type<value_t::Float > {typedef floating type;}; std::is_same<T, typename Value::array_type>::value, // if T == array_type,
template<> struct toml_default_type<value_t::String > {typedef string type;}; value_t_constant<value_t::array>, // then value_t::array
template<> struct toml_default_type<value_t::OffsetDatetime>{typedef offset_datetime type;}; typename std::conditional< // else...
template<> struct toml_default_type<value_t::LocalDatetime> {typedef local_datetime type;}; std::is_same<T, typename Value::table_type>::value, // if T == table_type
template<> struct toml_default_type<value_t::LocalDate> {typedef local_date type;}; value_t_constant<value_t::table>, // then value_t::table
template<> struct toml_default_type<value_t::LocalTime> {typedef local_time type;}; value_t_constant<value_t::empty> // else value_t::empty
template<> struct toml_default_type<value_t::Array > {typedef array type;}; >::type
template<> struct toml_default_type<value_t::Table > {typedef table type;}; >::type {};
template<> struct toml_default_type<value_t::Empty > {typedef void type;}; template<typename Value> struct type_to_enum<boolean , Value>: value_t_constant<value_t::boolean > {};
template<> struct toml_default_type<value_t::Unknown > {typedef void type;}; template<typename Value> struct type_to_enum<integer , Value>: value_t_constant<value_t::integer > {};
template<typename Value> struct type_to_enum<floating , Value>: value_t_constant<value_t::floating > {};
template<typename Value> struct type_to_enum<string , Value>: value_t_constant<value_t::string > {};
template<typename Value> struct type_to_enum<offset_datetime, Value>: value_t_constant<value_t::offset_datetime> {};
template<typename Value> struct type_to_enum<local_datetime , Value>: value_t_constant<value_t::local_datetime > {};
template<typename Value> struct type_to_enum<local_date , Value>: value_t_constant<value_t::local_date > {};
template<typename Value> struct type_to_enum<local_time , Value>: value_t_constant<value_t::local_time > {};
template<typename T> struct toml_value_t {static constexpr value_t value = value_t::Unknown ;}; // meta-function that checks the type T is the same as one of the toml::* types.
template<> struct toml_value_t<boolean >{static constexpr value_t value = value_t::Boolean ;}; template<typename T, typename Value>
template<> struct toml_value_t<integer >{static constexpr value_t value = value_t::Integer ;};
template<> struct toml_value_t<floating >{static constexpr value_t value = value_t::Float ;};
template<> struct toml_value_t<string >{static constexpr value_t value = value_t::String ;};
template<> struct toml_value_t<offset_datetime>{static constexpr value_t value = value_t::OffsetDatetime;};
template<> struct toml_value_t<local_datetime >{static constexpr value_t value = value_t::LocalDatetime ;};
template<> struct toml_value_t<local_date >{static constexpr value_t value = value_t::LocalDate ;};
template<> struct toml_value_t<local_time >{static constexpr value_t value = value_t::LocalTime ;};
template<> struct toml_value_t<array >{static constexpr value_t value = value_t::Array ;};
template<> struct toml_value_t<table >{static constexpr value_t value = value_t::Table ;};
template<typename T>
struct is_exact_toml_type : disjunction< struct is_exact_toml_type : disjunction<
std::is_same<T, boolean >, std::is_same<T, boolean >,
std::is_same<T, integer >, std::is_same<T, integer >,
@@ -153,41 +136,13 @@ struct is_exact_toml_type : disjunction<
std::is_same<T, local_datetime >, std::is_same<T, local_datetime >,
std::is_same<T, local_date >, std::is_same<T, local_date >,
std::is_same<T, local_time >, std::is_same<T, local_time >,
std::is_same<T, array >, std::is_same<T, typename Value::array_type>,
std::is_same<T, table > std::is_same<T, typename Value::table_type>
>{}; >{};
template<typename T> struct is_exact_toml_type<T&> : is_exact_toml_type<T>{}; template<typename T, typename V> struct is_exact_toml_type<T&, V> : is_exact_toml_type<T, V>{};
template<typename T> struct is_exact_toml_type<T const&> : is_exact_toml_type<T>{}; template<typename T, typename V> struct is_exact_toml_type<T const&, V> : is_exact_toml_type<T, V>{};
template<typename T> struct is_exact_toml_type<T volatile&> : is_exact_toml_type<T>{}; template<typename T, typename V> struct is_exact_toml_type<T volatile&, V> : is_exact_toml_type<T, V>{};
template<typename T> struct is_exact_toml_type<T const volatile&>: is_exact_toml_type<T>{}; template<typename T, typename V> struct is_exact_toml_type<T const volatile&, V>: is_exact_toml_type<T, V>{};
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>>,
#if __cplusplus >= 201703L
negation<std::is_same<T, std::string_view>>,
#endif
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 } // detail
} // toml } // toml

File diff suppressed because it is too large Load Diff