Compare commits

...

356 Commits

Author SHA1 Message Date
ToruNiina
2eb2e0a753 doc: update README 2019-07-13 15:11:01 +09:00
ToruNiina
87e0ba201e feat: enable to swap comment and strings 2019-07-13 14:33:14 +09:00
ToruNiina
24a05c7c93 doc: update serialization section #73 2019-07-10 09:12:38 +09:00
ToruNiina
c3653b85f1 doc: fix include directory #72 2019-07-10 08:45:09 +09:00
ToruNiina
00b05c63b9 doc: add explanation about os << toml::string 2019-07-07 21:24:33 +09:00
ToruNiina
35b7c79ebd doc: update README 2019-07-03 17:33:24 +09:00
ToruNiina
9ef146d022 🔀 Merge branch 'v3' 2019-07-03 17:31:45 +09:00
ToruNiina
2c192af35d test: add test for toml::string format 2019-06-29 20:20:31 +09:00
ToruNiina
c2435b0d56 feat:boom:: format toml::string as TOML format 2019-06-29 20:19:47 +09:00
ToruNiina
9b12b17d5e ci: fix ci job script 2019-06-29 17:36:16 +09:00
ToruNiina
e61b38fac2 ci: add test_serialization to the jobs 2019-06-29 16:45:59 +09:00
ToruNiina
716f7bacba ci: run serialization test to circleci 2019-06-29 16:43:11 +09:00
ToruNiina
299d1098e4 test: add serialization test for arbitrary file 2019-06-29 16:40:42 +09:00
ToruNiina
c272188060 fix: check inline table does not include LF 2019-06-29 16:39:54 +09:00
ToruNiina
0fc0967f6f fix: remove CR before comparing to the reference 2019-06-29 15:38:28 +09:00
ToruNiina
df0d870c97 test: add test for serialization with nocomment 2019-06-29 15:00:00 +09:00
ToruNiina
d5299fef04 feat: add no_comment option to serializer 2019-06-29 14:59:18 +09:00
ToruNiina
937a3b4a2e test: add test for nocomment/showcomment 2019-06-28 19:09:05 +09:00
ToruNiina
0502924d25 feat: add nocomment and showcomment 2019-06-28 19:08:48 +09:00
ToruNiina
6182f3ee9d test: add test for operator<<(os, non-table-value) 2019-06-28 17:56:41 +09:00
ToruNiina
3624e4b690 fix: put comment just after non-table values
When non-table value is passed to the `operator<<`, it assumes that the
original C++ code looks like the following.

```cpp
std::cout << "key = " << v << std::endl;
```

In this case, the comment associated to `v` should be put just after
`v`, not before.
```toml
key = # comment <= bad
"value"

key = "value" # comment <= good
```

So, if `v` is not a table it would put comments just after the value.
2019-06-28 17:53:19 +09:00
ToruNiina
37e96ed8dc test: add test for format_key() 2019-06-28 17:47:42 +09:00
ToruNiina
79e7511871 feat: add format_key to help serialization 2019-06-28 17:47:19 +09:00
ToruNiina
284f122433 refactor: replace for-loop by comment output 2019-06-28 14:58:47 +09:00
ToruNiina
134475e292 test: check ostream op for comment containers 2019-06-28 14:58:16 +09:00
ToruNiina
28b3f7d6fb feat: add ostream operator to comment containers 2019-06-28 14:57:45 +09:00
ToruNiina
6b5fd349aa fix: initialize source_location correctly 2019-06-26 21:35:01 +09:00
ToruNiina
76e44a0c48 refactor: remove needless inline specifier 2019-06-26 21:34:36 +09:00
ToruNiina
b4bbd0a005 chore: update version string in CMakeLists 2019-06-26 21:31:35 +09:00
ToruNiina
f9ee645dc2 doc: add link to v3 branch 2019-06-23 21:00:59 +09:00
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
ToruNiina
717f5929c2 feat: use detail::none_t instead of char
Although the error value from combinators currently does not have any
information, it can have an information because it is a char value. It
is better to use no-information-type explicitly to make it clear that
it does not have any information. So I added none_t in toml::detai and
use it in combinators and parsers as an error value from combinators.
2019-05-31 17:07:52 +09:00
ToruNiina
81abb6c9d7 perf: remove err-msg from combinator
Generate error message in `parse_something()`, not in `lex_something`.
Since the error message generated by `lex_something` is too difficult to
read for humans, I've disabled the error message generation for the sake
of efficiency (it takes time to generate error message that will never
be read). I think now the error message generation itself safely can be
removed from combinators. At this stage, `lex_something` does not need
to return `result<T, E>` because all the error type would be discarded.
Now it is turned out that returing `optional<T>` from lex_* is enough.
Maybe later I would change the return type itself, but currently I
changed the error type from std::string to char because implementing
optional takes time and effort. It makes the parsing process a bit
faster.
2019-05-30 20:08:37 +09:00
ToruNiina
8bba3c8a14 refactor: use literal instead of empty string
so far, the error value of the lexer is just ignored because they are
not readable (results from all the nested combinator are concatenated,
so they are too redundant). those ones are replaced by a simple literal.
2019-05-30 19:33:25 +09:00
ToruNiina
b13e727b90 refactor: remove unused func, combinator::pattern
because it is not human-readable (too long and redundant)
2019-05-30 18:05:47 +09:00
ToruNiina
d352c9e66f perf: suppress unused error message generation 2019-05-30 17:47:06 +09:00
ToruNiina
c0aaba06d0 Merge branch 'refactoring' 2019-05-30 16:25:10 +09:00
ToruNiina
1633268d57 refactor: use snake_case typename only 2019-05-30 14:39:15 +09:00
ToruNiina
3bf1c2b820 Merge branch 'refactoring' to master 2019-05-30 00:18:07 +09:00
ToruNiina
4dbd2cb9fe refactor: use as_* to avoid needless checking 2019-05-29 21:22:32 +09:00
ToruNiina
65124a8d2e refactor: use is_something instead of is(...)
to reduce the code size a bit
2019-05-29 21:20:22 +09:00
ToruNiina
1b78f161f5 refactor: use is_something/as_something in parser
this reduces the size of the code. And also it skips needless
double-checking, so we can expect it makes parsing a bit faster.
2019-05-29 21:18:17 +09:00
ToruNiina
0ce259ada0 refactor: split throw_bad_cast from value::cast 2019-05-29 21:06:25 +09:00
ToruNiina
74da49f87f refactor: move switch_cast from inside of value
use as_something() instead of it. To realize this, the implementation of
as_something() is also changed. Now as_something does not depends on
`cast`. This reduces complexity around casting toml::value to other types.
2019-05-29 20:18:15 +09:00
ToruNiina
d5d697639c docs: add contributor to README 2019-05-10 23:02:23 +09:00
Toru Niina
0b365ca7d3 Merge pull request #63 from chronoxor/master
Fix Visual Studio 2019 warnings in pedantic compilation mode (/W4 /WX)
2019-05-10 22:58:17 +09:00
Ivan Shynkarenka
db6f3d5d11 Fix Visual Studio 2019 warnings in pedantic compilation mode (/W4 /WX) 2019-05-10 14:58:22 +03:00
ToruNiina
87be890e07 feat: remove deprecated functions 2019-04-28 15:59:09 +09:00
Toru Niina
d72dc706d0 Merge pull request #61 from ToruNiina/as-something
feat: add as_something functions for convenience
2019-04-28 15:02:19 +09:00
ToruNiina
4cbbcd8f62 Merge branch 'master' into as-something 2019-04-27 19:04:44 +09:00
Toru Niina
a2631ecacb Merge pull request #60 from ToruNiina/string-view
support std::string_view
2019-04-27 18:33:59 +09:00
ToruNiina
4bcc5e8375 Merge branch 'master' into as-something 2019-04-27 17:42:12 +09:00
Toru Niina
90f84000ba Merge pull request #59 from ToruNiina/preserve-comments
Preserve comments; related to #48
2019-04-27 17:40:26 +09:00
ToruNiina
20a13754a7 chore: update README for as_* functions 2019-04-27 16:50:44 +09:00
ToruNiina
aa7b9a3965 refactor: rename as_floating -> as_float
Actually, since `floating` is used for toml::types, `as_floating`
seems to be clearer. But currently `is_*` functions uses `float`,
not `floating`, so `as_float` is chosen for the consistency.
In a future release, possibly v3, those names may need to be
re-considered for clarity.
2019-04-27 16:45:25 +09:00
ToruNiina
84ac1d10f3 test: add test for toml::value::as_something 2019-04-27 16:22:50 +09:00
ToruNiina
0d623856a7 feat: add value::as_something() for convenience 2019-04-27 16:22:23 +09:00
ToruNiina
ec0d4e4e8c chore: update README for comments 2019-04-27 15:50:54 +09:00
ToruNiina
80ea736b3f ci: try to update standard library on travis 2019-04-27 14:46:40 +09:00
ToruNiina
ebaa5dfb51 chore: fix build settings for OS X on Travis 2019-04-26 21:10:29 +09:00
ToruNiina
f3bdf083fe fix: fix typo in test code for string_view 2019-04-26 16:51:23 +09:00
ToruNiina
1ce54a9cf9 chore: add auto test with c++17 + latest compilers 2019-04-26 16:35:03 +09:00
ToruNiina
6383a93ce7 chore: check CXX_STANDARD exists or not 2019-04-26 16:33:48 +09:00
ToruNiina
01aa2ef5b2 feat: add ctor to value to init with string_view 2019-04-26 16:33:09 +09:00
ToruNiina
819351f5a4 test: add test for init toml::value by string_view 2019-04-26 16:32:23 +09:00
ToruNiina
2967cebfb3 test: add test to get a toml::value as string_view 2019-04-26 16:31:59 +09:00
ToruNiina
32e9a2c1c7 test: add test for comments in an array 2019-04-26 15:35:41 +09:00
ToruNiina
8e0a40a1aa test: add test for getting comments 2019-04-25 22:34:12 +09:00
ToruNiina
e460826084 feat: enable to get a comment related to a value
- comment_before(): get comments just before a value.
- comment_inline(): get a comment in the same line as a value.
- comment(): get comment_before() + comment_inline().
2019-04-25 22:32:39 +09:00
ToruNiina
aa3445f38c feat: add functions to get comments around region 2019-04-25 22:32:18 +09:00
ToruNiina
408b7bf35e Merge branch 'master' into string-view 2019-04-23 23:32:08 +09:00
ToruNiina
6185dfee14 chore: fix typo in README 2019-04-23 23:31:37 +09:00
ToruNiina
37aa2739a5 chore: add description about string_view to README 2019-04-23 23:27:53 +09:00
ToruNiina
d061c33a16 feat: enable toml::get with std::string_view 2019-04-23 23:24:23 +09:00
ToruNiina
0c7d2d07d4 feat: do not consider string_view as a container
it is a kind of string.
2019-04-23 23:23:57 +09:00
ToruNiina
62cf4373bd feat: conversion toml::string <-> string_view 2019-04-22 23:18:05 +09:00
Toru Niina
a74ad23514 Merge pull request #58 from ToruNiina/improve-err-msg-literal
Improve error message from toml literal
2019-04-22 20:50:11 +09:00
ToruNiina
2d9b4992ec fix: restrict length of underline by size of line
in some cases, `region` contains several lines and `region::size`
returns the whole size that is a sum of lengthes of all the lines.
To avoid too long underlines, restrict the length of underline by
the length of the line that is shown in the message.
2019-04-21 16:38:08 +09:00
ToruNiina
82e8c1e68b fix: skip first ws/newlines in toml literal
when ""_toml literal is used with C++11 raw-string literal,
it normally starts with newline like the following.
```cpp
const auto v = u8R"(
    [table]
    key = "value"
    )"_toml;
```
With this, the error message shows the first empty line that starts just
after `u8R"(` and thus the error message shows nothing. To avoid this,
skip the first empty lines and whitespaces in literal.
2019-04-21 16:31:24 +09:00
ToruNiina
46be054ce9 fix: improve err msg for multiline inline table
show "missing curly brace" instead of "missing table key-value separator"
2019-04-19 13:22:13 +09:00
ToruNiina
789d784769 chore: update README; about literals 2019-04-19 13:18:35 +09:00
ToruNiina
81deb8efde chore: update README 2019-04-19 12:41:24 +09:00
Toru Niina
072dccd05d Merge pull request #56 from ToruNiina/optimization
Optimization
2019-04-19 01:30:29 +09:00
ToruNiina
637c99d637 refactor: generate error message in parser 2019-04-18 15:09:58 +09:00
ToruNiina
0f48852730 perf: check value type before parsing
to avoid needless error message generation
2019-04-18 14:26:27 +09:00
ToruNiina
0499b2907d Merge branch 'master' into optimization 2019-04-18 14:10:08 +09:00
ToruNiina
61e69c9251 fix: count line number from 1, not 0 2019-04-18 13:56:19 +09:00
ToruNiina
4a560ea1e5 fix: show correct error message 2019-04-18 00:04:33 +09:00
ToruNiina
c5b6ee6f81 feat: add yet another constructor to value
to make implementation of parse_value easier
2019-04-17 23:43:42 +09:00
ToruNiina
1a7bf63622 Merge branch 'master' into optimization 2019-04-17 14:58:28 +09:00
Toru Niina
8847cdc0a9 Merge pull request #55 from wbenny/master
fix /W4 warnings on MSVC
2019-04-17 13:16:19 +09:00
ToruNiina
c82e76a111 perf: check string type before parsing it
to avoid unncessary error message generation, check the first some
characters before parsing it. It makes parsing process faster and
is also helpful to generate more accurate error messages.
2019-04-16 21:47:24 +09:00
ToruNiina
4db486d76d perf: check integer prefix before trying to parse
all the parsers generate error messages and error message generation is
not a lightweight task. It concatenates a lot of strings, it formats
many values, etc. To avoid useless error-message generation, first check
which prefix is used and then parse special integers. Additionally, by
checking that, the quality of the error message can be improved (later).
2019-04-16 21:37:12 +09:00
ToruNiina
91966a6917 perf: do not use concat_string if it is not needed
At the earlier stage of the development, I thought that it is useful if
lexer-combinators generate error messages, because by doing this,
parser would not need to generate an error message. But now it turned
out that to show an appropriate error message, parser need to generate
according to the context. And almost all the messages from lexer are
discarded. So I added another parameter to lexer-combinator to suppress
error message generation. In the future, we may want to remove messages
completely from lexers, but currently I will keep it. Removing those
unused message generation makes the parsing process faster.
2019-04-16 21:09:59 +09:00
ToruNiina
b3917aaadf refactor: use snprintf to show char in hex
instead of std::ostringstream.
2019-04-16 20:54:29 +09:00
Petr Benes
ba307003c4 fix /W4 warnings on MSVC 2019-04-16 13:25:45 +02:00
Toru Niina
21fd1271d9 Merge pull request #54 from ToruNiina/hotfix
fix: resolve ambiguity in the `""_toml` literal
2019-04-15 13:34:35 +09:00
ToruNiina
f9ab7d6f56 chore: add note about literals to README.md 2019-04-14 20:08:23 +09:00
ToruNiina
0a3a41a708 test: add test for literals for difficult case 2019-04-14 20:06:11 +09:00
ToruNiina
6c2a536fa5 fix: check literal has a table or an array first
The literal like this `"[[table]]"_toml` caused a syntax error. It is
because the literal parser first check that it might be a bare value
without a key, and parse_array directory throws syntax_error. This
change makes the parser first check a literal is a name of table, and
then parse the content.
2019-04-14 19:48:43 +09:00
Toru Niina
26eced3640 Merge pull request #52 from ToruNiina/speedup-for-large-files
Speedup parsing large files
2019-04-13 16:11:21 +09:00
ToruNiina
6f950c9ec8 perf: cache current line number in location
`location::line_num()` function used to be implemented by using
`std::count`, so each time the parser encounters a type mismatch,
`std::count` was called with almost whole file. It decelerates the
parsing process too much, so I decided to add `line_number_` member
variable to `location` and add `advance/retrace/reset` to `location`
in order to modify the position that is pointed.
2019-04-12 18:32:46 +09:00
ToruNiina
ea13e40889 feat: add static_assert for location/range
to check the container is randomly-accessible
2019-04-12 18:00:53 +09:00
ToruNiina
595fb1aef3 refactor: remove unused function parameter names 2019-04-06 19:39:13 +09:00
ToruNiina
18986978fb chore: add short example code to README 2019-03-24 21:30:27 +09:00
ToruNiina
c3cb22a789 chore: fix example of err msg by re-running sample 2019-03-21 18:12:35 +09:00
ToruNiina
5aebd6b562 fix: restore the back compat of format_error
the following code was okay in the last release
```
toml::format_error("[test]", v, "test", {"hint1", "hint2"})
```
but was not okay in the current master. This commit fixes this.

cons: By this, the number of values to show is limited upto 3.
2019-03-20 20:46:22 +09:00
ToruNiina
4c13085b35 fix: add stream operator for toml::table 2019-03-20 19:30:08 +09:00
ToruNiina
8709e8a14e chore: fix incorrect syntax highlight in README 2019-03-20 19:29:03 +09:00
ToruNiina
9eea46ec01 chore: fix typoes and broken links in README 2019-03-20 12:06:55 +09:00
ToruNiina
2e9f937c43 chore: update README 2019-03-20 11:53:03 +09:00
Toru Niina
65b10b6537 Merge pull request #46 from ToruNiina/toml-literal
feat: add ""_toml literal
2019-03-20 10:12:56 +09:00
ToruNiina
b51a8d5966 fix: add missing include file in test code 2019-03-20 00:58:58 +09:00
Toru Niina
55e3d70869 Merge pull request #47 from ToruNiina/format-table
`toml::format` and top-level table
2019-03-20 00:49:59 +09:00
ToruNiina
20ba57e389 fix: add missing const specifier to some of get()s 2019-03-20 00:37:13 +09:00
ToruNiina
39bc3c64fe test: add test for ""_toml literals 2019-03-20 00:36:46 +09:00
ToruNiina
40ccf1d912 feat: add argument to control top-level inlinization 2019-03-19 23:25:26 +09:00
ToruNiina
982ae36428 feat: add ""_toml literal 2019-03-19 21:34:57 +09:00
ToruNiina
d6714ec450 feat: detect value type and format as a file
in toml::format
2019-03-19 21:24:51 +09:00
ToruNiina
773c3816be ci: remove needless confirmation on CI 2019-03-19 19:39:45 +09:00
Toru Niina
1b417ddc7a Merge pull request #45 from ToruNiina/get_or
fix `get_or` and add `find_or`
2019-03-19 01:41:21 +09:00
ToruNiina
7a0ecf977d feat: add find_or(table, key, fallback)
get_or(value, fallback) is still ok, but get_or(table, key, fallback)
is now deprecated.
2019-03-18 17:44:03 +09:00
ToruNiina
aade704411 refactor: remove needless overload of get_or 2019-03-18 17:10:18 +09:00
ToruNiina
ca3f6102ef fix: correctly resolve overloads of get_or 2019-03-18 16:44:36 +09:00
ToruNiina
4a58b629ce feat: add a way to check arg is "string literal" 2019-03-18 16:31:12 +09:00
ToruNiina
3adba237b8 feat: enable to show message for deprecated() 2019-03-18 16:28:27 +09:00
Toru Niina
ccf03d9291 Merge pull request #44 from ToruNiina/test-link
test: add test for multiple translation unit
2019-03-18 15:20:04 +09:00
Toru Niina
30ae90ebd5 Merge pull request #43 from ToruNiina/hotfix
fix: incorrect move in constructor and return type deducing in toml::visit
2019-03-18 14:08:23 +09:00
ToruNiina
d5369c3429 test: add test for multiple translation unit 2019-03-18 12:39:58 +09:00
Toru Niina
48f2f0555d Merge pull request #42 from ToruNiina/test-suite
run toml-test suite
2019-03-18 12:33:48 +09:00
ToruNiina
f40fd12e25 refactor: add and rewrite comments 2019-03-18 11:09:12 +09:00
ToruNiina
65c2c3c238 fix: correctly deduce return value of visitor 2019-03-18 10:53:04 +09:00
ToruNiina
891a61a5e3 fix: do not move array element without checking 2019-03-18 02:05:55 +09:00
ToruNiina
1e6f30f6fa chore: update README.md 2019-03-18 01:50:23 +09:00
ToruNiina
02346a3126 Merge branch 'master' into test-suite 2019-03-18 01:40:17 +09:00
Toru Niina
1908f18e95 Merge pull request #41 from ToruNiina/hotfix
fix: simplify and correct the format of timezone
2019-03-18 01:39:11 +09:00
ToruNiina
3bfa7f09ba test: use the test suite in the effective way
add tests/check_toml_test.cpp to compare json object
2019-03-18 01:36:43 +09:00
ToruNiina
243f43fafd Merge branch 'master' into hotfix 2019-03-17 21:16:37 +09:00
ToruNiina
66e27a94b6 fix: simplify and correct the format of timezone 2019-03-17 21:14:17 +09:00
ToruNiina
227688ec63 ci: make result clearer a bit 2019-03-17 19:36:23 +09:00
ToruNiina
e761a503c0 ci: fix silly mistake in circleci script 2019-03-17 19:27:58 +09:00
ToruNiina
209ad79a8f ci: fix config file of circleci 2019-03-17 19:26:22 +09:00
ToruNiina
cdf209d7f6 ci: show the status on CI 2019-03-17 19:23:52 +09:00
ToruNiina
77ab391885 ci: fix name of directory and add test script 2019-03-17 19:20:24 +09:00
ToruNiina
6628fe5ace test: add language agnostic toml-test 2019-03-17 19:12:13 +09:00
Toru Niina
f3e3000d45 Merge pull request #40 from ToruNiina/remove-to-toml
refactor: remove to_toml and related tests
2019-03-17 13:12:30 +09:00
Toru Niina
f7380c6e32 Merge pull request #39 from ToruNiina/throw-incorrect-unicode
Throw syntax_error when parser encounter an incorrect utf-8 codepoint
2019-03-17 13:12:16 +09:00
Toru Niina
d86870e038 Merge pull request #38 from ToruNiina/get-any-type
extended conversions
2019-03-17 13:11:59 +09:00
Toru Niina
0908806915 Merge pull request #33 from ToruNiina/is-something
add `is_boolean` and other stuffs like that
2019-03-16 23:55:01 +09:00
ToruNiina
d17c192681 refactor: remove to_toml and related tests 2019-03-16 17:05:58 +09:00
ToruNiina
cad8f51256 doc: add explanation of conversions to README 2019-03-16 16:56:37 +09:00
ToruNiina
43014c6619 fix: remove redefined default template argument 2019-03-16 16:24:10 +09:00
ToruNiina
30a41aa710 fix: use older style in BOOST_TEST 2019-03-16 16:15:01 +09:00
ToruNiina
04bfeba3f2 merge branch master into get-any-type 2019-03-16 15:58:18 +09:00
ToruNiina
190636b791 fix: support getting a container of external types 2019-03-16 15:52:22 +09:00
ToruNiina
31e450f9af test: add test for from/into based conversions 2019-03-16 15:46:21 +09:00
ToruNiina
b1b72a94a8 feat: support conversion with external types 2019-03-16 14:44:04 +09:00
ToruNiina
6929bcdf78 feat: add from<T> and into<T> 2019-03-16 14:27:05 +09:00
ToruNiina
fd063af7ce refactor: make include guard style uniform 2019-03-16 14:19:47 +09:00
ToruNiina
df6dcbc4ed feat: check a class has from/into_toml member fn
to support better serialization
2019-03-16 14:16:31 +09:00
ToruNiina
76863cb27f refactor: simplify branches about utf8 codepoint 2019-03-15 17:48:47 +09:00
ToruNiina
514df99e40 feat: consider invalid UTF-8 as syntax_error
the following codepoints are considered to be a syntax_error
- [0xD800, 0xDFFF]
- larger than 0x10FFFF
2019-03-15 17:39:31 +09:00
ToruNiina
055353a460 chore: merge branch 'master' into is-something 2019-03-15 17:25:17 +09:00
ToruNiina
c4c416e8b2 doc: add is_* function to README 2019-03-12 22:18:25 +09:00
ToruNiina
6693ec78f4 test: add test for toml::value::is_something() 2019-03-12 20:44:27 +09:00
ToruNiina
dc112bd6c1 feat: add is_[boolean|integer|...]() member func
it is an alias to is<toml::value_t::[Boolean|Integer|...]>
2019-03-12 20:43:07 +09:00
65 changed files with 9896 additions and 3330 deletions

83
.circleci/config.yml Normal file
View File

@@ -0,0 +1,83 @@
version: 2.1
jobs:
test_suite:
environment:
- GOPATH: /home/circleci/go
docker:
- image: circleci/golang:1.9
steps:
- checkout
- run:
command: |
g++ --version
cd tests/
g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check_toml_test.cpp -o check_toml_test
go get github.com/BurntSushi/toml-test
$GOPATH/bin/toml-test ./check_toml_test
test_serialization:
docker:
- image: circleci/buildpack-deps:bionic
steps:
- checkout
- run:
command: |
g++ --version
cd tests/
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check_serialization.cpp -o check_serialization
git clone https://github.com/BurntSushi/toml-test.git
cp check_serialization toml-test/tests/valid
cd toml-test/tests/valid
for f in $(ls ./*.toml);
do echo "==> ${f}";
cat ${f};
echo "---------------------------------------";
./check_serialization ${f};
if [ $? -ne 0 ] ; then
exit 1
fi
echo "=======================================";
done
output_result:
docker:
- image: circleci/buildpack-deps:bionic
steps:
- checkout
- run:
command: |
g++ --version
cd tests/
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check.cpp -o check
git clone https://github.com/BurntSushi/toml-test.git
cp check toml-test/tests/invalid
cp check toml-test/tests/valid
cd toml-test/tests/invalid
for f in $(ls ./*.toml);
do echo "==> ${f}";
cat ${f};
echo "---------------------------------------";
./check ${f} invalid;
if [ $? -ne 0 ] ; then
exit 1
fi
echo "=======================================";
done
cd ../valid
for f in $(ls ./*.toml);
do echo "==> ${f}";
cat ${f};
echo "---------------------------------------";
./check ${f} valid;
if [ $? -ne 0 ] ; then
exit 1
fi
echo "=======================================";
done
workflows:
version: 2.1
test:
jobs:
- test_suite
- test_serialization
- output_result

View File

@@ -5,127 +5,180 @@ matrix:
- os: linux
language: cpp
compiler: gcc
env: COMPILER="g++-5"
env: COMPILER="g++-5" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-5
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: gcc
env: COMPILER="g++-6"
env: COMPILER="g++-6" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-6
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: gcc
env: COMPILER="g++-7"
env: COMPILER="g++-7" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-7
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: gcc
env: COMPILER="g++-8"
env: COMPILER="g++-8" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-8
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: gcc
env: COMPILER="g++-8" CXX_STANDARD=17
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-8
- boost1.70
- os: linux
language: cpp
compiler: clang
env: COMPILER="clang++-3.7"
env: COMPILER="clang++-3.7" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-8
- clang-3.7
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: clang
env: COMPILER="clang++-4.0"
env: COMPILER="clang++-4.0" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-8
- clang-4.0
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: clang
env: COMPILER="clang++-5.0"
env: COMPILER="clang++-5.0" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-8
- clang-5.0
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: clang
env: COMPILER="clang++-6.0"
env: COMPILER="clang++-6.0" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-6.0
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-8
- clang-6.0
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: clang
env: COMPILER="clang++-7"
env: COMPILER="clang++-7" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-8
- clang-7
- libboost-all-dev
- boost1.70
- os: linux
language: cpp
compiler: clang
env: COMPILER="clang++-8"
env: COMPILER="clang++-8" CXX_STANDARD=11
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-8
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- g++-8
- clang-8
- boost1.70
- os: linux
language: cpp
compiler: clang
env: COMPILER="clang++-8" CXX_STANDARD=17
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-8
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- clang-8
- libboost-all-dev
- g++-8
- boost1.70
- os: osx
language: cpp
compiler: clang
env: CXX_STANDARD=11
script:
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
mkdir -p cmake
travis_retry wget "https://github.com/Kitware/CMake/releases/download/v3.14.5/cmake-3.14.5-Linux-x86_64.tar.gz"
tar xf cmake-3.14.5-Linux-x86_64.tar.gz -C cmake --strip-components=1
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
else
brew upgrade cmake boost
fi
- cmake --version
- mkdir build
- cd build
- git clone https://github.com/toml-lang/toml.git
- cmake -DCMAKE_CXX_COMPILER=$COMPILER ..
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD ..
- make
- ctest --output-on-failure

View File

@@ -1,10 +1,23 @@
cmake_minimum_required(VERSION 2.8)
enable_testing()
project(toml11)
set(toml11_VERSION_MAYOR 3)
set(toml11_VERSION_MINOR 0)
set(toml11_VERSION_PATCH 0)
set(toml11_VERSION
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}-beta"
)
option(toml11_BUILD_TEST "Build toml tests" ON)
include(CheckCXXCompilerFlag)
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
set(CXX_STANDARD_REQUIRED ON)
else()
# Manually check for C++11 compiler flag.
@@ -31,5 +44,62 @@ else()
endif()
endif()
include_directories(${PROJECT_SOURCE_DIR})
add_subdirectory(tests)
# Set some common directories
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 ()

1398
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ build_script:
- cd build
- git clone https://github.com/toml-lang/toml.git
- 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%"
test_script:

View File

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

View File

@@ -1,5 +1,6 @@
set(TEST_NAMES
test_datetime
test_string
test_utility
test_result
test_traits
@@ -20,24 +21,31 @@ set(TEST_NAMES
test_parse_inline_table
test_parse_key
test_parse_table_key
test_literals
test_comments
test_get
test_get_related_func
test_to_toml
test_from_toml
test_get_or
test_find
test_find_or
test_expect
test_parse_file
test_serialize_file
test_parse_unicode
test_error_detection
test_format_error
test_extended_conversions
)
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA)
CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
if(COMPILER_SUPPORTS_WALL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif()
if(COMPILER_SUPPORTS_WEXTRA)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
endif()
if(COMPILER_SUPPORTS_WPEDANTIC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
endif()
@@ -86,7 +94,7 @@ add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST)
foreach(TEST_NAME ${TEST_NAMES})
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})
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
@@ -98,3 +106,9 @@ foreach(TEST_NAME ${TEST_NAMES})
)
endif()
endforeach(TEST_NAME)
# this test is to check it compiles. it will not run
add_executable(test_multiple_translation_unit
test_multiple_translation_unit_1.cpp
test_multiple_translation_unit_2.cpp)
target_link_libraries(test_multiple_translation_unit toml11::toml11)

41
tests/check.cpp Normal file
View File

@@ -0,0 +1,41 @@
#include "toml.hpp"
#include <iostream>
#include <iomanip>
int main(int argc, char **argv)
{
if(argc != 3)
{
std::cerr << "usage: ./check [filename] [valid|invalid]" << std::endl;
return 1;
}
const std::string file_kind(argv[2]);
try
{
const auto data = toml::parse(argv[1]);
std::cout << std::setprecision(16) << std::setw(80) << data;
if(file_kind == "valid")
{
return 0;
}
else
{
return 1;
}
}
catch(const toml::syntax_error& err)
{
std::cout << "what(): " << err.what() << std::endl;
if(file_kind == "invalid")
{
return 0;
}
else
{
return 1;
}
}
return 127;
}

View File

@@ -0,0 +1,57 @@
#include "toml.hpp"
#include <iostream>
#include <iomanip>
int main(int argc, char **argv)
{
if(argc != 2)
{
std::cerr << "usage: ./check [filename]" << std::endl;
return 1;
}
const std::string filename(argv[1]);
{
const auto data = toml::parse(filename);
{
std::ofstream ofs("tmp.toml");
ofs << std::setprecision(16) << std::setw(80) << data;
}
const auto serialized = toml::parse("tmp.toml");
if(data != serialized)
{
std::cerr << "============================================================\n";
std::cerr << "result (w/o comment) different: " << filename << std::endl;
std::cerr << "------------------------------------------------------------\n";
std::cerr << "# serialized\n";
std::cerr << serialized;
std::cerr << "------------------------------------------------------------\n";
std::cerr << "# data\n";
std::cerr << data;
return 1;
}
}
{
const auto data = toml::parse<toml::preserve_comments>(filename);
{
std::ofstream ofs("tmp.toml");
ofs << std::setprecision(16) << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("tmp.toml");
if(data != serialized)
{
std::cerr << "============================================================\n";
std::cerr << "result (w/ comment) different: " << filename << std::endl;
std::cerr << "------------------------------------------------------------\n";
std::cerr << "# serialized\n";
std::cerr << serialized;
std::cerr << "------------------------------------------------------------\n";
std::cerr << "# data\n";
std::cerr << data;
return 1;
}
}
return 0;
}

142
tests/check_toml_test.cpp Normal file
View File

@@ -0,0 +1,142 @@
#include "toml.hpp"
#include <iostream>
#include <iomanip>
struct json_serializer
{
void operator()(toml::boolean v)
{
std::cout << "{\"type\":\"bool\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(toml::integer v)
{
std::cout << "{\"type\":\"integer\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(toml::floating v)
{
std::cout << "{\"type\":\"float\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::string& v)
{
// since toml11 automatically convert string to multiline string that is
// valid only in TOML, we need to format the string to make it valid in
// JSON.
std::cout << "{\"type\":\"string\",\"value\":\""
<< this->escape_string(v.str) << "\"}";
return ;
}
void operator()(const toml::local_time& v)
{
std::cout << "{\"type\":\"local_time\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::local_date& v)
{
std::cout << "{\"type\":\"local_date\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::local_datetime& v)
{
std::cout << "{\"type\":\"local_datetime\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::offset_datetime& v)
{
std::cout << "{\"type\":\"datetime\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::array& v)
{
if(!v.empty() && v.front().is_table())
{
std::cout << '[';
bool is_first = true;
for(const auto& elem : v)
{
if(!is_first) {std::cout << ", ";}
is_first = false;
toml::visit(*this, elem);
}
std::cout << ']';
}
else
{
std::cout << "{\"type\":\"array\",\"value\":[";
bool is_first = true;
for(const auto& elem : v)
{
if(!is_first) {std::cout << ", ";}
is_first = false;
toml::visit(*this, elem);
}
std::cout << "]}";
}
return ;
}
void operator()(const toml::table& v)
{
std::cout << '{';
bool is_first = true;
for(const auto& elem : v)
{
if(!is_first) {std::cout << ", ";}
is_first = false;
std::cout << toml::format(toml::value(elem.first),
std::numeric_limits<std::size_t>::max());
std::cout << ':';
toml::visit(*this, elem.second);
}
std::cout << '}';
return ;
}
std::string escape_string(const std::string& s) const
{
std::string retval;
for(const char c : s)
{
switch(c)
{
case '\\': {retval += "\\\\"; break;}
case '\"': {retval += "\\\""; break;}
case '\b': {retval += "\\b"; break;}
case '\t': {retval += "\\t"; break;}
case '\f': {retval += "\\f"; break;}
case '\n': {retval += "\\n"; break;}
case '\r': {retval += "\\r"; break;}
default : {retval += c; break;}
}
}
return retval;
}
};
int main()
{
try
{
std::vector<char> buf;
std::cin.peek();
while(!std::cin.eof())
{
buf.push_back(std::cin.get());
std::cin.peek();
}
std::string bufstr(buf.begin(), buf.end());
std::istringstream ss(bufstr);
const auto data = toml::parse(ss);
std::cout << std::setprecision(std::numeric_limits<double>::max_digits10);
toml::visit(json_serializer(), data);
return 0;
}
catch(const toml::syntax_error& err)
{
std::cout << "what(): " << err.what() << std::endl;
return 1;
}
}

514
tests/test_comments.cpp Normal file
View File

@@ -0,0 +1,514 @@
#define BOOST_TEST_MODULE "test_comments"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
BOOST_AUTO_TEST_CASE(test_comment_before)
{
{
const std::string file = u8R"(
# comment for a.
a = 42
# comment for b.
b = "baz"
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto& a = toml::find(v, "a");
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 std::string file = u8R"(
# comment for a.
# another comment for a.
a = 42
# comment for b.
# also comment for b.
b = "baz"
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto& a = toml::find(v, "a");
const auto& b = toml::find(v, "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)
{
{
const std::string file = u8R"(
a = 42 # comment for a.
b = "baz" # comment for b.
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto& a = toml::find(v, "a");
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 std::string file = u8R"(
a = [
42,
] # comment for a.
b = [
"bar", # this is not a comment for b, but "bar"
] # this is a comment for b.
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto& a = toml::find(v, "a");
const auto& b = toml::find(v, "b");
const auto& b0 = b.as_array().at(0);
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" this is a comment for b.");
BOOST_TEST(b0.comments().size() == 1u);
BOOST_TEST(b0.comments().front() == u8" this is not a comment for b, but \"bar\"");
}
}
BOOST_AUTO_TEST_CASE(test_comment_both)
{
{
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<toml::preserve_comments>(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().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);
}
}
BOOST_AUTO_TEST_CASE(test_output_comments)
{
using value_type = toml::basic_value<toml::preserve_comments>;
{
const value_type v(42, {"comment1", "comment2"});
std::ostringstream oss;
oss << v.comments();
std::ostringstream ref;
ref << "#comment1\n";
ref << "#comment2\n";
BOOST_TEST(oss.str() == ref.str());
}
{
const value_type v(42, {"comment1", "comment2"});
std::ostringstream oss;
// If v is not a table, toml11 assumes that user is writing something
// like the following.
oss << "answer = " << v;
BOOST_TEST(oss.str() == "answer = 42 #comment1comment2");
}
{
const value_type v(42, {"comment1", "comment2"});
std::ostringstream oss;
// If v is not a table, toml11 assumes that user is writing something
// like the following.
oss << toml::nocomment << "answer = " << v;
BOOST_TEST(oss.str() == "answer = 42");
}
{
const value_type v(42, {"comment1", "comment2"});
std::ostringstream oss;
// If v is not a table, toml11 assumes that user is writing something
// like the following.
oss << toml::nocomment << toml::showcomment << "answer = " << v;
BOOST_TEST(oss.str() == "answer = 42 #comment1comment2");
}
}

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 date1(date);
BOOST_CHECK_EQUAL(date, date1);
BOOST_TEST(date == date1);
const std::chrono::system_clock::time_point tp(date);
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);
BOOST_CHECK(date > date3);
BOOST_TEST(date > date3);
std::ostringstream oss;
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)
{
const toml::local_time time(12, 30, 45);
const toml::local_time time1(time);
BOOST_CHECK_EQUAL(time, time1);
BOOST_TEST(time == time1);
const std::chrono::nanoseconds dur(time);
std::chrono::nanoseconds ns(0);
ns += std::chrono::hours (12);
ns += std::chrono::minutes(30);
ns += std::chrono::seconds(45);
BOOST_CHECK_EQUAL(dur.count(), ns.count());
BOOST_TEST(dur.count() == ns.count());
const toml::local_time time3(12, 15, 45);
BOOST_CHECK(time > time3);
BOOST_TEST(time > time3);
{
std::ostringstream oss;
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);
std::ostringstream oss;
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 time1(time);
BOOST_CHECK_EQUAL(time, time1);
BOOST_TEST(time == time1);
const std::chrono::minutes dur(time);
std::chrono::minutes m(0);
m += std::chrono::hours (9);
m += std::chrono::minutes(30);
BOOST_CHECK_EQUAL(dur.count(), m.count());
BOOST_TEST(dur.count() == m.count());
const toml::time_offset time2(9, 0);
BOOST_CHECK(time2 < time);
BOOST_TEST(time2 < time);
std::ostringstream oss;
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)
@@ -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),
toml::local_time(12, 30, 45));
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 toml::local_datetime dt2(tp);
BOOST_CHECK_EQUAL(dt, dt2);
BOOST_TEST(dt == dt2);
std::ostringstream oss;
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)
@@ -97,17 +97,18 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
toml::local_time(12, 30, 45),
toml::time_offset(9, 30));
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 toml::offset_datetime dt2(tp1);
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;
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(
@@ -116,6 +117,6 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
toml::time_offset(0, 0));
std::ostringstream oss;
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)
{
std::istringstream stream(std::string("= \"value\""));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_empty_key");
}
catch(const toml::syntax_error& syn)
{
// to see the error message
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_missing_value)
{
std::istringstream stream(std::string("a ="));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_missing_value");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_too_many_value)
{
std::istringstream stream(std::string("a = 1 = \"value\""));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_too_many_value");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
@@ -66,17 +35,7 @@ BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
"[table]\n"
"b = 42\n"
));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_duplicate_table");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
@@ -87,17 +46,7 @@ BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
"[table]\n"
"b = 42\n"
));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_conflict_array_table");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
@@ -108,17 +57,7 @@ BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
"[[table]]\n"
"b = 42\n"
));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_conflict_table_array");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
@@ -127,17 +66,7 @@ BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
"a = 1\n"
"a = 2\n"
));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_duplicate_value");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
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.c = 2\n"
));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_conflicting_value");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
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(
"a = [1, 1.0]\n"
));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_inhomogeneous_array");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
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"
"b = 2\n"
));
bool exception_thrown = false;
try
{
toml::parse(stream, "test_detect_appending_array_of_table");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}

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

@@ -0,0 +1,292 @@
#define BOOST_TEST_MODULE "test_extended_conversions"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <deque>
#include <map>
namespace extlib
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
void from_toml(const toml::value& v)
{
this->a = toml::find<int>(v, "a");
this->b = toml::find<std::string>(v, "b");
return ;
}
toml::table into_toml() const
{
return toml::table{{"a", this->a}, {"b", this->b}};
}
};
} // extlib
namespace toml
{
template<>
struct from<extlib::foo>
{
static extlib::foo from_toml(const toml::value& v)
{
return extlib::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib::foo>
{
static toml::table into_toml(const extlib::foo& f)
{
return toml::table{{"a", f.a}, {"b", f.b}};
}
};
} // toml
// ---------------------------------------------------------------------------
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)
{
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::value v2(foo);
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)
{
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "baz");
const toml::value v2(bar);
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)
{
{
const toml::value v{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}},
};
const auto foos = toml::get<std::vector<extlib::foo>>(v);
BOOST_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<extlib::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::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
#include <boost/test/unit_test.hpp>
#else
@@ -22,7 +22,7 @@ BOOST_AUTO_TEST_CASE(test_1_value)
{
const std::string pretty_error =
toml::format_error("[error] test error", val, "this is a value",
std::vector<std::string>{"this is a hint"});
{"this is a hint"});
std::cout << pretty_error << std::endl;
}
}
@@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(test_2_values)
toml::format_error("[error] test error with two values",
v1, "this is the answer",
v2, "this is the pi",
std::vector<std::string>{"hint"});
{"hint"});
std::cout << pretty_error << std::endl;
}
}
@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(test_3_values)
v1, "this is the answer",
v2, "this is the pi",
v3, "this is a meta-syntactic variable",
std::vector<std::string>{"hint 1", "hint 2"});
{"hint 1", "hint 2"});
std::cout << pretty_error << std::endl;
}
}

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,280 +5,284 @@
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml/value.hpp>
#include <toml/get.hpp>
#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>
>;
BOOST_AUTO_TEST_CASE(test_get_exact)
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
{
{
toml::value v(true);
BOOST_CHECK_EQUAL(true, toml::get<toml::boolean>(v));
value_type v(true);
BOOST_TEST(true == toml::get<toml::boolean>(v));
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);
BOOST_CHECK_EQUAL(toml::integer(42), toml::get<toml::integer>(v));
value_type v(42);
BOOST_TEST(toml::integer(42) == toml::get<toml::integer>(v));
toml::get<toml::integer>(v) = 54;
BOOST_CHECK_EQUAL(toml::integer(54), toml::get<toml::integer>(v));
BOOST_TEST(toml::integer(54) == toml::get<toml::integer>(v));
}
{
toml::value v(3.14);
BOOST_CHECK_EQUAL(toml::floating(3.14), toml::get<toml::floating>(v));
value_type v(3.14);
BOOST_TEST(toml::floating(3.14) == toml::get<toml::floating>(v));
toml::get<toml::floating>(v) = 2.71;
BOOST_CHECK_EQUAL(toml::floating(2.71), toml::get<toml::floating>(v));
BOOST_TEST(toml::floating(2.71) == toml::get<toml::floating>(v));
}
{
toml::value v("foo");
BOOST_CHECK_EQUAL(toml::string("foo", toml::string_t::basic),
value_type v("foo");
BOOST_TEST(toml::string("foo", toml::string_t::basic) ==
toml::get<toml::string>(v));
toml::get<toml::string>(v).str += "bar";
BOOST_CHECK_EQUAL(toml::string("foobar", toml::string_t::basic),
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
toml::get<toml::string>(v));
}
{
toml::value v("foo", toml::string_t::literal);
BOOST_CHECK_EQUAL(toml::string("foo", toml::string_t::literal),
value_type v("foo", toml::string_t::literal);
BOOST_TEST(toml::string("foo", toml::string_t::literal) ==
toml::get<toml::string>(v));
toml::get<toml::string>(v).str += "bar";
BOOST_CHECK_EQUAL(toml::string("foobar", toml::string_t::literal),
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
toml::get<toml::string>(v));
}
{
toml::local_date d(2018, toml::month_t::Apr, 22);
toml::value v(d);
BOOST_CHECK(d == toml::get<toml::local_date>(v));
value_type v(d);
BOOST_TEST(d == toml::get<toml::local_date>(v));
toml::get<toml::local_date>(v).year = 2017;
d.year = 2017;
BOOST_CHECK(d == toml::get<toml::local_date>(v));
BOOST_TEST(d == toml::get<toml::local_date>(v));
}
{
toml::local_time t(12, 30, 45);
toml::value v(t);
BOOST_CHECK(t == toml::get<toml::local_time>(v));
value_type v(t);
BOOST_TEST(t == toml::get<toml::local_time>(v));
toml::get<toml::local_time>(v).hour = 9;
t.hour = 9;
BOOST_CHECK(t == toml::get<toml::local_time>(v));
BOOST_TEST(t == toml::get<toml::local_time>(v));
}
{
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45));
toml::value v(dt);
BOOST_CHECK(dt == toml::get<toml::local_datetime>(v));
value_type v(dt);
BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
toml::get<toml::local_datetime>(v).date.year = 2017;
dt.date.year = 2017;
BOOST_CHECK(dt == toml::get<toml::local_datetime>(v));
BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
}
{
toml::offset_datetime dt(toml::local_datetime(
toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
toml::value v(dt);
BOOST_CHECK(dt == toml::get<toml::offset_datetime>(v));
value_type v(dt);
BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
toml::get<toml::offset_datetime>(v).date.year = 2017;
dt.date.year = 2017;
BOOST_CHECK(dt == toml::get<toml::offset_datetime>(v));
BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
}
{
toml::array vec;
vec.push_back(toml::value(42));
vec.push_back(toml::value(54));
toml::value v(vec);
BOOST_CHECK(vec == toml::get<toml::array>(v));
using array_type = typename value_type::array_type;
array_type vec;
vec.push_back(value_type(42));
vec.push_back(value_type(54));
value_type v(vec);
BOOST_TEST(vec == toml::get<array_type>(v));
toml::get<toml::array>(v).push_back(toml::value(123));
vec.push_back(toml::value(123));
BOOST_CHECK(vec == toml::get<toml::array>(v));
toml::get<array_type>(v).push_back(value_type(123));
vec.push_back(value_type(123));
BOOST_TEST(vec == toml::get<array_type>(v));
}
{
toml::table tab;
tab["key1"] = toml::value(42);
tab["key2"] = toml::value(3.14);
toml::value v(tab);
BOOST_CHECK(tab == toml::get<toml::table>(v));
using table_type = typename value_type::table_type;
table_type tab;
tab["key1"] = value_type(42);
tab["key2"] = value_type(3.14);
value_type v(tab);
BOOST_TEST(tab == toml::get<table_type>(v));
toml::get<toml::table>(v)["key3"] = toml::value(123);
tab["key3"] = toml::value(123);
BOOST_CHECK(tab == toml::get<toml::table>(v));
toml::get<table_type>(v)["key3"] = value_type(123);
tab["key3"] = value_type(123);
BOOST_TEST(tab == toml::get<table_type>(v));
}
{
toml::value v1(42);
BOOST_CHECK(v1 == toml::get<toml::value>(v1));
value_type v1(42);
BOOST_TEST(v1 == toml::get<value_type>(v1));
toml::value v2(54);
toml::get<toml::value>(v1) = v2;
BOOST_CHECK(v2 == toml::get<toml::value>(v1));
value_type v2(54);
toml::get<value_type>(v1) = v2;
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);
BOOST_CHECK_EQUAL(int(42), toml::get<int >(v));
BOOST_CHECK_EQUAL(short(42), toml::get<short >(v));
BOOST_CHECK_EQUAL(char(42), toml::get<char >(v));
BOOST_CHECK_EQUAL(unsigned(42), toml::get<unsigned >(v));
BOOST_CHECK_EQUAL(long(42), toml::get<long >(v));
BOOST_CHECK_EQUAL(std::int64_t(42), toml::get<std::int64_t >(v));
BOOST_CHECK_EQUAL(std::uint64_t(42), toml::get<std::uint64_t>(v));
BOOST_CHECK_EQUAL(std::int16_t(42), toml::get<std::int16_t >(v));
BOOST_CHECK_EQUAL(std::uint16_t(42), toml::get<std::uint16_t>(v));
value_type v(42);
BOOST_TEST(int(42) == toml::get<int >(v));
BOOST_TEST(short(42) == toml::get<short >(v));
BOOST_TEST(char(42) == toml::get<char >(v));
BOOST_TEST(unsigned(42) == toml::get<unsigned >(v));
BOOST_TEST(long(42) == toml::get<long >(v));
BOOST_TEST(std::int64_t(42) == toml::get<std::int64_t >(v));
BOOST_TEST(std::uint64_t(42) == toml::get<std::uint64_t>(v));
BOOST_TEST(std::int16_t(42) == toml::get<std::int16_t >(v));
BOOST_TEST(std::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);
BOOST_CHECK_EQUAL(static_cast<float >(3.14), toml::get<float >(v));
BOOST_CHECK_EQUAL(static_cast<double >(3.14), toml::get<double >(v));
BOOST_CHECK_EQUAL(static_cast<long double>(3.14), toml::get<long double>(v));
value_type v(3.14);
BOOST_TEST(static_cast<float >(3.14) == toml::get<float >(v));
BOOST_TEST(static_cast<double >(3.14) == toml::get<double >(v));
BOOST_TEST(static_cast<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);
BOOST_CHECK_EQUAL("foo", toml::get<std::string>(v));
value_type v("foo", toml::string_t::basic);
BOOST_TEST("foo" == toml::get<std::string>(v));
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);
BOOST_CHECK_EQUAL("foo", toml::get<std::string>(v));
value_type v("foo", toml::string_t::literal);
BOOST_TEST("foo" == toml::get<std::string>(v));
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
{
value_type v("foo", toml::string_t::basic);
BOOST_TEST("foo" == toml::get<std::string_view>(v));
}
{
value_type v("foo", toml::string_t::literal);
BOOST_TEST("foo" == toml::get<std::string_view>(v));
}
#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));
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 value_type v{42, 54, 69, 72};
const std::vector<int> vec = toml::get<std::vector<int>>(v);
const std::list<short> lst = toml::get<std::list<short>>(v);
const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v);
BOOST_CHECK_EQUAL(42, vec.at(0));
BOOST_CHECK_EQUAL(54, vec.at(1));
BOOST_CHECK_EQUAL(69, vec.at(2));
BOOST_CHECK_EQUAL(72, vec.at(3));
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_CHECK_EQUAL(static_cast<short>(42), *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(54), *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(69), *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(72), *(iter++));
BOOST_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_CHECK_EQUAL(static_cast<std::int64_t>(42), deq.at(0));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(54), deq.at(1));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(69), deq.at(2));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(72), deq.at(3));
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::get<std::array<int, 4>>(v);
BOOST_CHECK_EQUAL(static_cast<int>(42), ary.at(0));
BOOST_CHECK_EQUAL(static_cast<int>(54), ary.at(1));
BOOST_CHECK_EQUAL(static_cast<int>(69), ary.at(2));
BOOST_CHECK_EQUAL(static_cast<int>(72), ary.at(3));
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::get<std::tuple<int, short, unsigned, long>>(v);
BOOST_CHECK_EQUAL(static_cast<int >(42), std::get<0>(tpl));
BOOST_CHECK_EQUAL(static_cast<short >(54), std::get<1>(tpl));
BOOST_CHECK_EQUAL(static_cast<unsigned>(69), std::get<2>(tpl));
BOOST_CHECK_EQUAL(static_cast<long >(72), std::get<3>(tpl));
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));
toml::value p(toml::array{});
toml::get<toml::array>(p).push_back(toml::value(3.14));
toml::get<toml::array>(p).push_back(toml::value(2.71));
const value_type p{3.14, 2.71};
std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
BOOST_CHECK_EQUAL(3.14, pr.first);
BOOST_CHECK_EQUAL(2.71, pr.second);
BOOST_TEST(3.14 == pr.first);
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{});
toml::get<toml::array>(v1).push_back(toml::value(42));
toml::get<toml::array>(v1).push_back(toml::value(54));
toml::get<toml::array>(v1).push_back(toml::value(69));
toml::get<toml::array>(v1).push_back(toml::value(72));
toml::value v2(toml::array{});
toml::get<toml::array>(v2).push_back(toml::value("foo"));
toml::get<toml::array>(v2).push_back(toml::value("bar"));
toml::get<toml::array>(v2).push_back(toml::value("baz"));
toml::value v(toml::array(2));
toml::get<toml::array>(v).at(0) = v1;
toml::get<toml::array>(v).at(1) = v2;
const value_type v1{42, 54, 69, 72};
const value_type v2{"foo", "bar", "baz"};
const value_type v{v1, v2};
std::pair<std::vector<int>, std::vector<std::string>> p =
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
BOOST_CHECK_EQUAL(p.first.at(0), 42);
BOOST_CHECK_EQUAL(p.first.at(1), 54);
BOOST_CHECK_EQUAL(p.first.at(2), 69);
BOOST_CHECK_EQUAL(p.first.at(3), 72);
BOOST_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_CHECK_EQUAL(p.second.at(0), "foo");
BOOST_CHECK_EQUAL(p.second.at(1), "bar");
BOOST_CHECK_EQUAL(p.second.at(2), "baz");
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::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v);
BOOST_CHECK_EQUAL(std::get<0>(t).at(0), 42);
BOOST_CHECK_EQUAL(std::get<0>(t).at(1), 54);
BOOST_CHECK_EQUAL(std::get<0>(t).at(2), 69);
BOOST_CHECK_EQUAL(std::get<0>(t).at(3), 72);
BOOST_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_CHECK_EQUAL(std::get<1>(t).at(0), "foo");
BOOST_CHECK_EQUAL(std::get<1>(t).at(1), "bar");
BOOST_CHECK_EQUAL(std::get<1>(t).at(2), "baz");
BOOST_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(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},
{"key2", 2},
{"key3", 3},
{"key4", 4}
});
};
const auto v = toml::get<std::map<std::string, int>>(v1);
BOOST_CHECK_EQUAL(v.at("key1"), 1);
BOOST_CHECK_EQUAL(v.at("key2"), 2);
BOOST_CHECK_EQUAL(v.at("key3"), 3);
BOOST_CHECK_EQUAL(v.at("key4"), 4);
BOOST_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(test_get_toml_local_date)
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types)
{
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(
toml::get<std::chrono::system_clock::time_point>(v1));
@@ -291,20 +295,22 @@ BOOST_AUTO_TEST_CASE(test_get_toml_local_date)
t.tm_sec = 0;
t.tm_isdst = -1;
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);
BOOST_CHECK(time == std::chrono::hours(12) +
std::chrono::minutes(30) + std::chrono::seconds(45));
const bool result = time == std::chrono::hours(12) +
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_time{12, 30, 45}));
@@ -319,13 +325,13 @@ BOOST_AUTO_TEST_CASE(test_get_toml_local_datetime)
t.tm_sec = 45;
t.tm_isdst = -1;
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_time{12, 30, 0},
toml::time_offset{9, 0}));
@@ -337,18 +343,18 @@ BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime)
// get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_CHECK(tmp);
BOOST_TEST(tmp);
const auto tm = *tmp;
BOOST_CHECK_EQUAL(tm.tm_year + 1900, 2018);
BOOST_CHECK_EQUAL(tm.tm_mon + 1, 4);
BOOST_CHECK_EQUAL(tm.tm_mday, 1);
BOOST_CHECK_EQUAL(tm.tm_hour, 3);
BOOST_CHECK_EQUAL(tm.tm_min, 30);
BOOST_CHECK_EQUAL(tm.tm_sec, 0);
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);
}
{
toml::value v1(toml::offset_datetime(
value_type v1(toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0},
toml::time_offset{-8, 0}));
@@ -360,14 +366,14 @@ BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime)
// get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_CHECK(tmp);
BOOST_TEST(tmp);
const auto tm = *tmp;
BOOST_CHECK_EQUAL(tm.tm_year + 1900, 2018);
BOOST_CHECK_EQUAL(tm.tm_mon + 1, 4);
BOOST_CHECK_EQUAL(tm.tm_mday, 1);
BOOST_CHECK_EQUAL(tm.tm_hour, 20);
BOOST_CHECK_EQUAL(tm.tm_min, 30);
BOOST_CHECK_EQUAL(tm.tm_sec, 0);
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_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,81 +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)
{
{
toml::table v{{"num", 42}};
BOOST_CHECK_EQUAL(42, toml::get_or<int>(v, "num", 0));
BOOST_CHECK_EQUAL(0, toml::get_or<int>(v, "foo", 0));
}
{
toml::value v = toml::table{{"num", 42}};
BOOST_CHECK_EQUAL(42, toml::get_or<int>(v, "num", 0));
BOOST_CHECK_EQUAL(0, toml::get_or<int>(v, "foo", 0));
}
{
toml::value v1(42);
toml::value v2(3.14);
BOOST_CHECK_EQUAL(42, toml::get_or<int>(v1, 0));
BOOST_CHECK_EQUAL(0, toml::get_or<int>(v2, 0));
}
}
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,17 +10,17 @@ do { \
const std::string expected(expct); \
toml::detail::location<std::string> loc("test", token); \
const auto result = lxr::invoke(loc); \
BOOST_CHECK(result.is_ok()); \
BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \
const auto region = result.unwrap(); \
BOOST_CHECK_EQUAL(region.str(), expected); \
BOOST_CHECK_EQUAL(region.str().size(), expected.size()); \
BOOST_CHECK_EQUAL(static_cast<std::size_t>(std::distance( \
loc.begin(), loc.iter())), region.size()); \
const auto region = result.unwrap(); \
BOOST_TEST(region.str() == expected); \
BOOST_TEST(region.str().size() == expected.size()); \
BOOST_TEST(static_cast<std::size_t>(std::distance( \
loc.begin(), loc.iter())) == region.size()); \
} else { \
std::cerr << "lexer " << lxr::pattern() << " failed with input `"; \
std::cerr << token << "`. expected `" << expected << "`\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
std::cerr << "lexer failed with input `"; \
std::cerr << token << "`. expected `" << expected << "`\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \
} while(false); \
/**/
@@ -30,6 +30,7 @@ do { \
const std::string token (tkn); \
toml::detail::location<std::string> loc("test", token); \
const auto result = lxr::invoke(loc); \
BOOST_CHECK(result.is_err()); \
BOOST_CHECK(loc.begin() == loc.iter()); \
BOOST_TEST(result.is_err()); \
const bool loc_same = (loc.begin() == loc.iter()); \
BOOST_TEST(loc_same); \
} while(false); /**/

163
tests/test_literals.cpp Normal file
View File

@@ -0,0 +1,163 @@
#define BOOST_TEST_MODULE "test_literals"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <map>
BOOST_AUTO_TEST_CASE(test_file_as_literal)
{
using namespace toml::literals::toml_literals;
{
const toml::value r{{"a", 42}, {"b", "baz"}};
const toml::value v = u8R"(
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
{
const toml::value r{
{"c", 3.14},
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
};
const toml::value v = u8R"(
c = 3.14
[table]
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
{
const toml::value r{
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
};
const toml::value v = u8R"(
[table]
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
}
BOOST_AUTO_TEST_CASE(test_value_as_literal)
{
using namespace toml::literals::toml_literals;
{
const toml::value v1 = u8"true"_toml;
const toml::value v2 = u8"false"_toml;
BOOST_TEST(v1.is_boolean());
BOOST_TEST(v2.is_boolean());
BOOST_TEST(toml::get<bool>(v1));
BOOST_TEST(!toml::get<bool>(v2));
}
{
const toml::value v1 = u8"123_456"_toml;
const toml::value v2 = u8"0b0010"_toml;
const toml::value v3 = u8"0xDEADBEEF"_toml;
BOOST_TEST(v1.is_integer());
BOOST_TEST(v2.is_integer());
BOOST_TEST(v3.is_integer());
BOOST_TEST(toml::get<toml::integer>(v1) == 123456);
BOOST_TEST(toml::get<toml::integer>(v2) == 2);
BOOST_TEST(toml::get<toml::integer>(v3) == 0xDEADBEEF);
}
{
const toml::value v1 = u8"3.1415"_toml;
const toml::value v2 = u8"6.02e+23"_toml;
BOOST_TEST(v1.is_floating());
BOOST_TEST(v2.is_floating());
BOOST_TEST(toml::get<double>(v1) == 3.1415, boost::test_tools::tolerance(0.00001));
BOOST_TEST(toml::get<double>(v2) == 6.02e23, boost::test_tools::tolerance(0.0001));
}
{
const toml::value v1 = u8R"("foo")"_toml;
const toml::value v2 = u8R"('foo')"_toml;
const toml::value v3 = u8R"("""foo""")"_toml;
const toml::value v4 = u8R"('''foo''')"_toml;
BOOST_TEST(v1.is_string());
BOOST_TEST(v2.is_string());
BOOST_TEST(v3.is_string());
BOOST_TEST(v4.is_string());
BOOST_TEST(toml::get<std::string>(v1) == "foo");
BOOST_TEST(toml::get<std::string>(v2) == "foo");
BOOST_TEST(toml::get<std::string>(v3) == "foo");
BOOST_TEST(toml::get<std::string>(v4) == "foo");
}
{
{
const toml::value v1 = u8R"([1,2,3])"_toml;
BOOST_TEST(v1.is_array());
const bool result = (toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3});
BOOST_TEST(result);
}
{
const toml::value v2 = u8R"([1,])"_toml;
BOOST_TEST(v2.is_array());
const bool result = (toml::get<std::vector<int>>(v2) == std::vector<int>{1});
BOOST_TEST(result);
}
{
const toml::value v3 = u8R"([[1,]])"_toml;
BOOST_TEST(v3.is_array());
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;
BOOST_TEST(v4.is_array());
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;
BOOST_TEST(v1.is_table());
const bool result = toml::get<std::map<std::string,int>>(v1) ==
std::map<std::string,int>{{"a", 42}};
BOOST_TEST(result);
}
{
const toml::value v1 = u8"1979-05-27"_toml;
BOOST_TEST(v1.is_local_date());
BOOST_TEST(toml::get<toml::local_date>(v1) ==
toml::local_date(1979, toml::month_t::May, 27));
}
{
const toml::value v1 = u8"12:00:00"_toml;
BOOST_TEST(v1.is_local_time());
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;
BOOST_TEST(v1.is_local_datetime());
BOOST_TEST(toml::get<toml::local_datetime>(v1) ==
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)));
}
{
const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
BOOST_TEST(v1.is_offset_datetime());
BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
}
}

View File

@@ -0,0 +1,11 @@
#include <toml.hpp>
int read_a(const toml::table&);
int main()
{
const std::string content("a = 0");
std::istringstream iss(content);
const auto data = toml::parse(iss, "test_multiple_translation_unit.toml");
return read_a(toml::get<toml::table>(data));
}

View File

@@ -0,0 +1,6 @@
#include <toml.hpp>
int read_a(const toml::table& t)
{
return toml::get<int>(t.at("a"));
}

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
#include <boost/test/unit_test.hpp>
#else
@@ -13,118 +13,118 @@ using namespace detail;
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);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5]", a);
TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,1,4,1,5]", a);
}
{
array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\"]", a);
TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\", \"bar\", \"baz\"]", a);
}
{
array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5,]", a);
TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,1,4,1,5,]", a);
}
{
array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\",]", a);
TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\", \"bar\", \"baz\",]", a);
}
}
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);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,1,4,1,5]", toml::value(a));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5]", toml::value(a));
}
{
array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\"]", toml::value(a));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\", \"baz\"]", toml::value(a));
}
{
array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,1,4,1,5,]", toml::value(a));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5,]", toml::value(a));
}
{
array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\",]", toml::value(a));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\", \"baz\",]", toml::value(a));
}
}
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);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,\n1,\n4,\n1,\n5]", a);
TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,\n1,\n4,\n1,\n5]", a);
}
{
array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
}
{
array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", a);
TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", a);
}
{
array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("b#r");
a[2] = toml::value("b#z");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a);
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)
{
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);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,\n1,\n4,\n1,\n5]", toml::value(a));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,\n1,\n4,\n1,\n5]", toml::value(a));
}
{
array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",\n\"bar\",\n\"baz\"]", toml::value(a));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n\"bar\",\n\"baz\"]", toml::value(a));
}
{
array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", toml::value(a));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", toml::value(a));
}
{
array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("b#r");
a[2] = toml::value("b#z");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", toml::value(a));
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 <iomanip>
#include <algorithm>
#include <toml/region.hpp>
#include <toml/result.hpp>
#include <toml.hpp>
// some of the parsers returns not only a value but also a region.
#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \
@@ -10,13 +9,13 @@ do { \
const std::string token(tkn); \
toml::detail::location<std::string> loc("test", token); \
const auto result = psr(loc); \
BOOST_CHECK(result.is_ok()); \
BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \
BOOST_CHECK(result.unwrap().first == expct); \
BOOST_TEST(result.unwrap().first == expct); \
} else { \
std::cerr << "parser " << #psr << " failed with input `"; \
std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
std::cerr << "parser " << #psr << " failed with input `"; \
std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \
} while(false); \
/**/
@@ -26,13 +25,13 @@ do { \
const std::string token(tkn); \
toml::detail::location<std::string> loc("test", token); \
const auto result = psr(loc); \
BOOST_CHECK(result.is_ok()); \
BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \
BOOST_CHECK(result.unwrap() == expct); \
BOOST_TEST(result.unwrap() == expct); \
} else { \
std::cerr << "parse_value failed with input `"; \
std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
std::cerr << "parse_value failed with input `"; \
std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \
} while(false); \
/**/

View File

@@ -19,6 +19,6 @@ BOOST_AUTO_TEST_CASE(test_boolean)
BOOST_AUTO_TEST_CASE(test_boolean_value)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "true", toml::value( true));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "false", toml::value(false));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "true", toml::value( true));
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)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00", toml::value(toml::local_time(7, 32, 0)));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.99", toml::value(toml::local_time(7, 32, 0, 990, 0)));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.999", toml::value(toml::local_time(7, 32, 0, 999, 0)));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.999999", toml::value(toml::local_time(7, 32, 0, 999, 999)));
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<toml::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.999", toml::value(toml::local_time(7, 32, 0, 999, 0)));
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)
@@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(test_date)
}
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)));
}
@@ -64,25 +64,25 @@ BOOST_AUTO_TEST_CASE(test_datetime)
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))));
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))));
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))));
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))));
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))));
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))));
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))));
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))));
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))));
}
@@ -111,23 +111,23 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
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::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::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::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::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::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::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0))));
}

View File

@@ -8,73 +8,69 @@
#include <toml.hpp>
#include <iostream>
#include <fstream>
#include <map>
#include <deque>
BOOST_AUTO_TEST_CASE(test_example)
{
const auto data = toml::parse("toml/tests/example.toml");
BOOST_CHECK_EQUAL(toml::get<std::string>(data.at("title")), "TOML Example");
toml::Table owner = toml::get<toml::Table>(data.at("owner"));
BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
const auto& owner = toml::find(data, "owner");
{
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("name")), "Tom Preston-Werner");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("organization")), "GitHub");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")),
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_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::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};
BOOST_CHECK(toml::get<std::vector<int>>(database.at("ports")) == expected_ports);
BOOST_CHECK_EQUAL(toml::get<int>(database.at("connection_max")), 5000);
BOOST_CHECK_EQUAL(toml::get<bool>(database.at("enabled")), true);
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);
}
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"));
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("ip")), "10.0.0.1");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("dc")), "eqdc10");
toml::table alpha = toml::find<toml::table>(servers, "alpha");
BOOST_TEST(toml::get<std::string>(alpha.at("ip")) == "10.0.0.1");
BOOST_TEST(toml::get<std::string>(alpha.at("dc")) == "eqdc10");
toml::Table beta = toml::get<toml::Table>(servers.at("beta"));
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("ip")), "10.0.0.2");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("dc")), "eqdc10");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("country")), "\xE4\xB8\xAD\xE5\x9B\xBD");
toml::table beta = toml::find<toml::table>(servers, "beta");
BOOST_TEST(toml::get<std::string>(beta.at("ip")) == "10.0.0.2");
BOOST_TEST(toml::get<std::string>(beta.at("dc")) == "eqdc10");
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);
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);
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients.at("hosts")) ==
expected_hosts);
BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") == expected_hosts);
}
std::vector<toml::Table> products =
toml::get<std::vector<toml::Table>>(data.at("products"));
std::vector<toml::table> products =
toml::find<std::vector<toml::table>>(data, "products");
{
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(0).at("name")),
"Hammer");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(0).at("sku")),
738594937);
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_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("name")),
"Nail");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(1).at("sku")),
284758393);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("color")),
"gray");
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");
}
}
@@ -83,42 +79,194 @@ BOOST_AUTO_TEST_CASE(test_example_stream)
std::ifstream ifs("toml/tests/example.toml");
const auto data = toml::parse(ifs);
BOOST_CHECK_EQUAL(toml::get<std::string>(data.at("title")), "TOML Example");
toml::Table owner = toml::get<toml::Table>(data.at("owner"));
BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
const auto& owner = toml::find(data, "owner");
{
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("name")), "Tom Preston-Werner");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("organization")), "GitHub");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")),
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_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::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};
BOOST_CHECK(toml::get<std::vector<int>>(database.at("ports")) == expected_ports);
BOOST_CHECK_EQUAL(toml::get<int>(database.at("connection_max")), 5000);
BOOST_CHECK_EQUAL(toml::get<bool>(database.at("enabled")), true);
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);
}
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"));
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("ip")), "10.0.0.1");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("dc")), "eqdc10");
toml::table alpha = toml::find<toml::table>(servers, "alpha");
BOOST_TEST(toml::get<std::string>(alpha.at("ip")) == "10.0.0.1");
BOOST_TEST(toml::get<std::string>(alpha.at("dc")) == "eqdc10");
toml::Table beta = toml::get<toml::Table>(servers.at("beta"));
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("ip")), "10.0.0.2");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("dc")), "eqdc10");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("country")), "\xE4\xB8\xAD\xE5\x9B\xBD");
toml::table beta = toml::find<toml::table>(servers, "beta");
BOOST_TEST(toml::get<std::string>(beta.at("ip")) == "10.0.0.2");
BOOST_TEST(toml::get<std::string>(beta.at("dc")) == "eqdc10");
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"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) ==
expected_name);
@@ -126,73 +274,118 @@ BOOST_AUTO_TEST_CASE(test_example_stream)
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) ==
expected_number);
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);
BOOST_TEST(toml::find(clients, "hosts").comments().at(0) ==
" Line breaks are OK when inside arrays");
}
std::vector<toml::Table> products =
toml::get<std::vector<toml::Table>>(data.at("products"));
std::vector<toml::table> 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");
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);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("name")),
BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) ==
"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);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("color")),
BOOST_TEST(toml::get<std::string>(products.at(1).at("color")) ==
"gray");
}
}
BOOST_AUTO_TEST_CASE(test_fruit)
BOOST_AUTO_TEST_CASE(test_example_preserve_stdmap_stddeque)
{
const auto data = toml::parse("toml/tests/fruit.toml");
const auto blah = toml::get<std::vector<toml::Table>>(
toml::get<toml::Table>(data.at("fruit")).at("blah"));
BOOST_CHECK_EQUAL(toml::get<std::string>(blah.at(0).at("name")), "apple");
BOOST_CHECK_EQUAL(toml::get<std::string>(blah.at(1).at("name")), "banana");
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque
>("toml/tests/example.toml");
static_assert(std::is_same<typename decltype(data)::table_type,
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_CHECK_EQUAL(toml::get<std::string>(physical.at("color")), "red");
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("shape")), "round");
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");
{
const auto physical = toml::get<toml::Table>(blah.at(1).at("physical"));
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("color")), "yellow");
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("shape")), "bent");
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);
}
}
BOOST_AUTO_TEST_CASE(test_hard_example)
{
const auto data = toml::parse("toml/tests/hard_example.toml");
const auto the = toml::get<toml::Table>(data.at("the"));
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")),
"You'll hate me after this - #");
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 hard = toml::get<toml::Table>(the.at("hard"));
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("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::get<std::vector<std::string>>(hard.at("test_array2")) ==
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& 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 bit = toml::get<toml::Table>(hard.at("bit#"));
BOOST_CHECK_EQUAL(toml::get<std::string>(bit.at("what?")),
"You don't think some user won't do that?");
const std::vector<std::string> expected_multi_line_array{"]"};
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
expected_multi_line_array);
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"};
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);
const auto data = toml::parse(iss, "test_file_with_BOM.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -226,8 +419,8 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
}
const auto data = toml::parse("tmp.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -239,8 +432,8 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
std::istringstream iss(table);
const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
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
// mode.
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");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "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,
"test_file_without_newline_at_the_end_of_file.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
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,
"test_file_without_newline_at_the_end_of_file_CRLF.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "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,
"test_file_without_newline_at_the_end_of_file_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
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,
"test_file_without_newline_at_the_end_of_file_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "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,
"test_file_without_newline_at_the_end_of_file_ws.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
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,
"test_file_without_newline_at_the_end_of_file_ws.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "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,
"test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -377,8 +570,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss,
"test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
// comment w/ newline
@@ -394,8 +587,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss,
"test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -409,8 +602,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss,
"test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
// CRLF version
@@ -426,8 +619,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss,
"test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -441,8 +634,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss,
"test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -455,8 +648,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss,
"test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -470,8 +663,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss,
"test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "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,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -504,8 +697,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
// with whitespaces
@@ -521,8 +714,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -536,8 +729,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -551,8 +744,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -566,8 +759,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
// 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,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "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,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -615,8 +808,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
// with whitespaces
@@ -632,8 +825,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -647,8 +840,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -662,8 +855,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -677,8 +870,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
}
{
const std::string table(
@@ -691,7 +884,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss,
"test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value");
BOOST_TEST(toml::find<std::string>(data, "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)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1.0", value( 1.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.1", value( 0.1));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.001", value( 0.001));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.100", value( 0.1));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+3.14", value( 3.14));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-3.14", value(-3.14));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "3.1415_9265_3589", value( 3.141592653589));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+3.1415_9265_3589", value( 3.141592653589));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-3.1415_9265_3589", value(-3.141592653589));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123_456.789", value( 123456.789));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+123_456.789", value( 123456.789));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-123_456.789", value(-123456.789));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+0.0", value( 0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0.0", value(-0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.0", value( 1.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.1", value( 0.1));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.001", value( 0.001));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.100", value( 0.1));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::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<toml::value>, "-3.1415_9265_3589", value(-3.141592653589));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::value>, "-123_456.789", value(-123456.789));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)
@@ -72,24 +72,24 @@ BOOST_AUTO_TEST_CASE(test_exponential)
BOOST_AUTO_TEST_CASE(test_exponential_value)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e+10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e-10", value(-1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123e-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123E-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3E-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3E-1_0", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+0e0", value( 0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0e0", value(-0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e+10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e-10", value(-1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123e-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123E-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<toml::value>, "1_2_3E-1_0", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+0e0", value( 0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0e0", value(-0.0));
}
BOOST_AUTO_TEST_CASE(test_fe)
{
@@ -99,9 +99,9 @@ BOOST_AUTO_TEST_CASE(test_fe)
}
BOOST_AUTO_TEST_CASE(test_fe_vaule)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "6.02e23", value(6.02e23));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "6.02e+23", value(6.02e23));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1.112_650_06e-17", value(1.11265006e-17));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e23", value(6.02e23));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e+23", value(6.02e23));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.112_650_06e-17", value(1.11265006e-17));
}
BOOST_AUTO_TEST_CASE(test_inf)

View File

@@ -13,36 +13,36 @@ using namespace detail;
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;
t["foo"] = toml::value(42);
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_sub;
t_sub["name"] = toml::value("pug");
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)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{}", value(table()));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{}", value(table()));
{
table t;
t["foo"] = toml::value(42);
t["bar"] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{foo = 42, bar = \"baz\"}", value(t));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{foo = 42, bar = \"baz\"}", value(t));
}
{
table t;
table t_sub;
t_sub["name"] = toml::value("pug");
t["type"] = toml::value(t_sub);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{type.name = \"pug\"}", value(t));
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)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1234", toml::value( 1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1234", toml::value( 1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1234", toml::value( -1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0", toml::value( 0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3_4", toml::value( 1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1_2_3_4", toml::value( +1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1_2_3_4", toml::value( -1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123_456_789", toml::value(123456789));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::value>, "-1234", toml::value( -1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0", toml::value( 0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::value>, "-1_2_3_4", toml::value( -1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123_456_789", toml::value(123456789));
}
BOOST_AUTO_TEST_CASE(test_hex)
@@ -50,15 +50,15 @@ BOOST_AUTO_TEST_CASE(test_hex)
BOOST_AUTO_TEST_CASE(test_hex_value)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADBEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdeadbeef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADbeef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEAD_BEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_beef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_BEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xFF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x00FF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x0000FF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADBEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdeadbeef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADbeef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::value>, "0xdead_BEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xFF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x00FF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x0000FF", value(0xFF));
}
BOOST_AUTO_TEST_CASE(test_oct)
@@ -70,9 +70,9 @@ BOOST_AUTO_TEST_CASE(test_oct)
BOOST_AUTO_TEST_CASE(test_oct_value)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o777", value(64*7+8*7+7));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o7_7_7", value(64*7+8*7+7));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o007", value(7));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o777", 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<toml::value>, "0o007", value(7));
}
BOOST_AUTO_TEST_CASE(test_bin)
@@ -85,8 +85,8 @@ BOOST_AUTO_TEST_CASE(test_bin)
BOOST_AUTO_TEST_CASE(test_bin_value)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b10000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b010000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b01_00_00", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b111111", value(63));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b10000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b010000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b01_00_00", value(16));
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)
{
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\"",
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\'",
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\"\"\"",
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'''",
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)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"192.168.1.1\"",
value("192.168.1.1", string_t::basic));
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic));
#else
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"中国\"",
value("中国", string_t::basic));
#endif
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"You'll hate me after this - #\"",
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 # \\\"\"",
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)
{
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.\"\"\"",
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 \"\"\"",
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)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'C:\\Users\\nodejs\\templates'",
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\\'",
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'",
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*>'",
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)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'''I [dw]on't need \\d{2} apples'''",
value("I [dw]on't need \\d{2} apples", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value,
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'''",
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);
const auto result = toml::detail::parse_ml_table(loc);
BOOST_CHECK(result.is_ok());
const auto result = toml::detail::parse_ml_table<toml::value>(loc);
BOOST_TEST(result.is_ok());
const auto data = result.unwrap();
BOOST_CHECK_EQUAL(toml::get<std::string >(data.at("key1")), "value");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(data.at("key2")), 42);
BOOST_CHECK_EQUAL(toml::get<double >(data.at("key3")), 3.14);
BOOST_TEST(toml::get<std::string >(data.at("key1")) == "value");
BOOST_TEST(toml::get<std::int64_t>(data.at("key2")) == 42);
BOOST_TEST(toml::get<double >(data.at("key3")) == 3.14);
}
BOOST_AUTO_TEST_CASE(test_nested_table)
@@ -38,13 +38,13 @@ BOOST_AUTO_TEST_CASE(test_nested_table)
);
location<std::string> loc("test", table);
const auto result = toml::detail::parse_ml_table(loc);
BOOST_CHECK(result.is_ok());
const auto result = toml::detail::parse_ml_table<toml::value>(loc);
BOOST_TEST(result.is_ok());
const auto data = result.unwrap();
const auto a = toml::get<toml::table>(data.at("a"));
const auto c = toml::get<toml::table>(a.at("c"));
BOOST_CHECK_EQUAL(toml::get<std::string >(a.at("b")), "value");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(c.at("d")), 42);
BOOST_TEST(toml::get<std::string >(a.at("b")) == "value");
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 the = toml::get<toml::Table>(data.at("the"));
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")),
const auto the = toml::find<toml::table>(data, "the");
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"));
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{"] ", " # "};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("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")) ==
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"));
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"));
//
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"))),
const auto bit = toml::get<toml::table>(hard.at(std::string("\xCE\xB2\xC3\xAF\xC6\xAD\x23")));
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"));
const std::vector<std::string> expected_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 the = toml::get<toml::Table>(data.at("the"));
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")),
const auto the = toml::find<toml::table>(data, "the");
BOOST_TEST(toml::get<std::string>(the.at("test_string")) ==
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{"] ", " # "};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) ==
expected_the_hard_test_array);
@@ -58,13 +58,13 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
std::string(u8"Éжƥèřï₥èñƭ #9 ωáƨ á ƨúççèƨƨ")};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("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"§á₥è ƭλïñϱ, βúƭ ωïƭλ á ƨƭřïñϱ #"));
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" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \""));
const auto bit = toml::get<toml::Table>(hard.at(std::string(u8"βïƭ#")));
BOOST_CHECK_EQUAL(toml::get<std::string>(bit.at(std::string(u8"ωλáƭ?"))),
const auto bit = toml::get<toml::table>(hard.at(std::string(u8"βïƭ#")));
BOOST_TEST(toml::get<std::string>(bit.at(std::string(u8"ωλáƭ?"))) ==
std::string(u8"Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?"));
const std::vector<std::string> expected_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);
toml::result<int, std::string> result(s);
BOOST_CHECK(!!result);
BOOST_CHECK(result.is_ok());
BOOST_CHECK(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42);
BOOST_TEST(!!result);
BOOST_TEST(result.is_ok());
BOOST_TEST(!result.is_err());
BOOST_TEST(result.unwrap() == 42);
}
{
const auto s = toml::ok(42);
toml::result<int, std::string> result(s);
BOOST_CHECK(!!result);
BOOST_CHECK(result.is_ok());
BOOST_CHECK(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42);
BOOST_TEST(!!result);
BOOST_TEST(result.is_ok());
BOOST_TEST(!result.is_err());
BOOST_TEST(result.unwrap() == 42);
}
{
toml::result<int, std::string> result(toml::ok(42));
BOOST_CHECK(!!result);
BOOST_CHECK(result.is_ok());
BOOST_CHECK(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42);
BOOST_TEST(!!result);
BOOST_TEST(result.is_ok());
BOOST_TEST(!result.is_err());
BOOST_TEST(result.unwrap() == 42);
}
{
auto f = toml::err<std::string>("foobar");
toml::result<int, std::string> result(f);
BOOST_CHECK(!result);
BOOST_CHECK(!result.is_ok());
BOOST_CHECK(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar");
BOOST_TEST(!result);
BOOST_TEST(!result.is_ok());
BOOST_TEST(result.is_err());
BOOST_TEST(result.unwrap_err() == "foobar");
}
{
const auto f = toml::err<std::string>("foobar");
toml::result<int, std::string> result(f);
BOOST_CHECK(!result);
BOOST_CHECK(!result.is_ok());
BOOST_CHECK(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar");
BOOST_TEST(!result);
BOOST_TEST(!result.is_ok());
BOOST_TEST(result.is_err());
BOOST_TEST(result.unwrap_err() == "foobar");
}
{
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
BOOST_CHECK(!result);
BOOST_CHECK(!result.is_ok());
BOOST_CHECK(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar");
BOOST_TEST(!result);
BOOST_TEST(!result.is_ok());
BOOST_TEST(result.is_err());
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"));
result = toml::ok(42);
BOOST_CHECK(!!result);
BOOST_CHECK(result.is_ok());
BOOST_CHECK(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42);
BOOST_TEST(!!result);
BOOST_TEST(result.is_ok());
BOOST_TEST(!result.is_err());
BOOST_TEST(result.unwrap() == 42);
}
{
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
auto s = toml::ok(42);
result = s;
BOOST_CHECK(!!result);
BOOST_CHECK(result.is_ok());
BOOST_CHECK(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42);
BOOST_TEST(!!result);
BOOST_TEST(result.is_ok());
BOOST_TEST(!result.is_err());
BOOST_TEST(result.unwrap() == 42);
}
{
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
const auto s = toml::ok(42);
result = s;
BOOST_CHECK(!!result);
BOOST_CHECK(result.is_ok());
BOOST_CHECK(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42);
BOOST_TEST(!!result);
BOOST_TEST(result.is_ok());
BOOST_TEST(!result.is_err());
BOOST_TEST(result.unwrap() == 42);
}
{
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
result = toml::err<std::string>("hoge");
BOOST_CHECK(!result);
BOOST_CHECK(!result.is_ok());
BOOST_CHECK(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge");
BOOST_TEST(!result);
BOOST_TEST(!result.is_ok());
BOOST_TEST(result.is_err());
BOOST_TEST(result.unwrap_err() == "hoge");
}
{
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
auto f = toml::err<std::string>("hoge");
result = f;
BOOST_CHECK(!result);
BOOST_CHECK(!result.is_ok());
BOOST_CHECK(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge");
BOOST_TEST(!result);
BOOST_TEST(!result.is_ok());
BOOST_TEST(result.is_err());
BOOST_TEST(result.unwrap_err() == "hoge");
}
{
toml::result<int, std::string> result(toml::err<std::string>("foobar"));
const auto f = toml::err<std::string>("hoge");
result = f;
BOOST_CHECK(!result);
BOOST_CHECK(!result.is_ok());
BOOST_CHECK(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge");
BOOST_TEST(!result);
BOOST_TEST(!result.is_ok());
BOOST_TEST(result.is_err());
BOOST_TEST(result.unwrap_err() == "hoge");
}
}
@@ -119,10 +119,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return i * 2;
});
BOOST_CHECK(!!mapped);
BOOST_CHECK(mapped.is_ok());
BOOST_CHECK(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2);
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42 * 2);
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -132,10 +132,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return *i;
});
BOOST_CHECK(!!mapped);
BOOST_CHECK(mapped.is_ok());
BOOST_CHECK(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42);
}
{
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;
});
BOOST_CHECK(!mapped);
BOOST_CHECK(!mapped.is_ok());
BOOST_CHECK(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge");
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -157,10 +157,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return *i;
});
BOOST_CHECK(!mapped);
BOOST_CHECK(!mapped.is_ok());
BOOST_CHECK(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge");
}
}
@@ -173,10 +173,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return s + s;
});
BOOST_CHECK(!!mapped);
BOOST_CHECK(mapped.is_ok());
BOOST_CHECK(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42);
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -186,10 +186,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return s + s;
});
BOOST_CHECK(!!mapped);
BOOST_CHECK(mapped.is_ok());
BOOST_CHECK(!mapped.is_err());
BOOST_CHECK_EQUAL(*(mapped.unwrap()), 42);
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(*(mapped.unwrap()) == 42);
}
{
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 {
return s + s;
});
BOOST_CHECK(!mapped);
BOOST_CHECK(!mapped.is_ok());
BOOST_CHECK(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hogehoge");
}
{
toml::result<int, std::unique_ptr<std::string>>
@@ -210,10 +210,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return *p;
});
BOOST_CHECK(!mapped);
BOOST_CHECK(!mapped.is_ok());
BOOST_CHECK(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge");
}
}
@@ -226,7 +226,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return i * 2;
}, 54);
BOOST_CHECK_EQUAL(mapped, 42 * 2);
BOOST_TEST(mapped == 42 * 2);
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return *i;
}, 54);
BOOST_CHECK_EQUAL(mapped, 42);
BOOST_TEST(mapped == 42);
}
{
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;
}, 54);
BOOST_CHECK_EQUAL(mapped, 54);
BOOST_TEST(mapped == 54);
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -255,7 +255,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return *i;
}, 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;
}, "foobar");
BOOST_CHECK_EQUAL(mapped, "foobar");
BOOST_TEST(mapped == "foobar");
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i;
}, "foobar");
BOOST_CHECK_EQUAL(mapped, "foobar");
BOOST_TEST(mapped == "foobar");
}
{
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;
}, "foobar");
BOOST_CHECK_EQUAL(mapped, "hogehoge");
BOOST_TEST(mapped == "hogehoge");
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -297,7 +297,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i;
}, "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);
});
BOOST_CHECK(!!mapped);
BOOST_CHECK(mapped.is_ok());
BOOST_CHECK(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2);
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42 * 2);
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -324,10 +324,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(*i);
});
BOOST_CHECK(!!mapped);
BOOST_CHECK(mapped.is_ok());
BOOST_CHECK(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42);
}
{
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);
});
BOOST_CHECK(!mapped);
BOOST_CHECK(!mapped.is_ok());
BOOST_CHECK(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge");
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -349,10 +349,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(*i);
});
BOOST_CHECK(!mapped);
BOOST_CHECK(!mapped.is_ok());
BOOST_CHECK(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge");
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge");
}
}
@@ -365,10 +365,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s);
});
BOOST_CHECK(!!mapped);
BOOST_CHECK(mapped.is_ok());
BOOST_CHECK(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42);
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42);
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -378,10 +378,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s);
});
BOOST_CHECK(!!mapped);
BOOST_CHECK(mapped.is_ok());
BOOST_CHECK(!mapped.is_err());
BOOST_CHECK_EQUAL(*mapped.unwrap(), 42);
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(*mapped.unwrap() == 42);
}
{
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);
});
BOOST_CHECK(!mapped);
BOOST_CHECK(!mapped.is_ok());
BOOST_CHECK(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hogehoge");
}
{
toml::result<std::unique_ptr<int>, std::string>
@@ -403,10 +403,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s);
});
BOOST_CHECK(!mapped);
BOOST_CHECK(!mapped.is_ok());
BOOST_CHECK(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge");
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
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> r2(toml::err<std::string>("foo"));
BOOST_CHECK_EQUAL(r1, r1.or_other(r2));
BOOST_CHECK_EQUAL(r2, r1.and_other(r2));
BOOST_CHECK_EQUAL(42, r1.or_other(r2).unwrap());
BOOST_CHECK_EQUAL("foo", r1.and_other(r2).unwrap_err());
BOOST_TEST(r1 == r1.or_other(r2));
BOOST_TEST(r2 == r1.and_other(r2));
BOOST_TEST(42 == r1.or_other(r2).unwrap());
BOOST_TEST("foo" == r1.and_other(r2).unwrap_err());
}
{
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 r4 = r2_gen();
BOOST_CHECK_EQUAL(r3, r1_gen().or_other (r2_gen()));
BOOST_CHECK_EQUAL(r4, r1_gen().and_other(r2_gen()));
BOOST_CHECK_EQUAL(42, r1_gen().or_other (r2_gen()).unwrap());
BOOST_CHECK_EQUAL("foo", r1_gen().and_other(r2_gen()).unwrap_err());
BOOST_TEST(r3 == r1_gen().or_other (r2_gen()));
BOOST_TEST(r4 == r1_gen().and_other(r2_gen()));
BOOST_TEST(42 == r1_gen().or_other (r2_gen()).unwrap());
BOOST_TEST("foo" == r1_gen().and_other(r2_gen()).unwrap_err());
}
}

View File

@@ -6,9 +6,43 @@
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <deque>
#include <map>
#include <iostream>
#include <fstream>
template<typename Comment,
template<typename ...> class Table,
template<typename ...> class Array>
bool has_comment_inside(const toml::basic_value<Comment, Table, Array>& v)
{
if(!v.comments().empty())
{
return false;
}
// v itself does not have a comment.
if(v.is_array())
{
for(const auto& x : v.as_array())
{
if(has_comment_inside(x))
{
return false;
}
}
}
if(v.is_table())
{
for(const auto& x : v.as_table())
{
if(has_comment_inside(x.second))
{
return false;
}
}
}
return true;
}
BOOST_AUTO_TEST_CASE(test_example)
{
@@ -20,15 +54,146 @@ BOOST_AUTO_TEST_CASE(test_example)
auto serialized = toml::parse("tmp1.toml");
{
auto& owner = toml::get<toml::table>(serialized.at("owner"));
auto& bio = toml::get<std::string>(owner.at("bio"));
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_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_map_dq.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp1_map_dq.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_nocomment)
{
{
const auto data = toml::parse<toml::preserve_comments>("toml/tests/example.toml");
{
std::ofstream ofs("tmp1_com_nocomment.toml");
ofs << std::setw(80) << toml::nocomment << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("tmp1_com_nocomment.toml");
// check no comment exist
BOOST_TEST(!has_comment_inside(serialized));
}
{
const auto data_nocomment = toml::parse("toml/tests/example.toml");
auto serialized = toml::parse("tmp1_com_nocomment.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
// check collectly serialized
BOOST_TEST(data_nocomment == serialized);
}
}
BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
"toml/tests/example.toml");
{
std::ofstream ofs("tmp1_com_map_dq.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
"tmp1_com_map_dq.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_map_dq.toml");
ofs << std::setw(80) << serialized;
}
}
BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq_nocomment)
{
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>("toml/tests/example.toml");
{
std::ofstream ofs("tmp1_com_map_dq_nocomment.toml");
ofs << std::setw(80) << toml::nocomment << data;
}
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>("tmp1_com_map_dq_nocomment.toml");
BOOST_TEST(!has_comment_inside(serialized));
}
{
const auto data_nocomment = toml::parse("toml/tests/example.toml");
auto serialized = toml::parse("tmp1_com_map_dq_nocomment.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data_nocomment == serialized);
}
}
BOOST_AUTO_TEST_CASE(test_fruit)
@@ -39,7 +204,43 @@ BOOST_AUTO_TEST_CASE(test_fruit)
ofs << std::setw(80) << data;
}
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)
@@ -50,5 +251,55 @@ BOOST_AUTO_TEST_CASE(test_hard_example)
ofs << std::setw(80) << data;
}
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);
}
BOOST_AUTO_TEST_CASE(test_format_key)
{
{
const toml::key key("normal_bare-key");
BOOST_TEST("normal_bare-key" == toml::format_key(key));
}
{
const toml::key key("key.include.dots");
BOOST_TEST("\"key.include.dots\"" == toml::format_key(key));
}
{
const toml::key key("key-include-unicode-\xE3\x81\x82");
BOOST_TEST("\"key-include-unicode-\xE3\x81\x82\"" == toml::format_key(key));
}
{
const toml::key key("special-chars-\\-\"-\b-\f-\r-\n-\t");
BOOST_TEST("\"special-chars-\\\\-\\\"-\\b-\\f-\\r-\\n-\\t\"" == toml::format_key(key));
}
}

113
tests/test_string.cpp Normal file
View File

@@ -0,0 +1,113 @@
#define BOOST_TEST_MODULE "test_string"
#include <boost/test/unit_test.hpp>
#include <toml.hpp>
BOOST_AUTO_TEST_CASE(test_basic_string)
{
{
const toml::string str("basic string");
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "\"basic string\"");
}
{
const std::string s1 ("basic string");
const toml::string str(s1);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "\"basic string\"");
}
{
const toml::string str("basic string", toml::string_t::basic);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "\"basic string\"");
}
{
const std::string s1 ("basic string");
const toml::string str(s1, toml::string_t::basic);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "\"basic string\"");
}
}
BOOST_AUTO_TEST_CASE(test_basic_ml_string)
{
{
const toml::string str("basic\nstring");
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
BOOST_TEST(oss1.str() == oss2.str());
}
{
const std::string s1 ("basic\nstring");
const toml::string str(s1);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
BOOST_TEST(oss1.str() == oss2.str());
}
{
const toml::string str("basic\nstring", toml::string_t::basic);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
BOOST_TEST(oss1.str() == oss2.str());
}
{
const std::string s1 ("basic\nstring");
const toml::string str(s1, toml::string_t::basic);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
BOOST_TEST(oss1.str() == oss2.str());
}
}
BOOST_AUTO_TEST_CASE(test_literal_string)
{
{
const toml::string str("literal string", toml::string_t::literal);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "'literal string'");
}
{
const std::string s1 ("literal string");
const toml::string str(s1, toml::string_t::literal);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "'literal string'");
}
}
BOOST_AUTO_TEST_CASE(test_literal_ml_string)
{
{
const toml::string str("literal\nstring", toml::string_t::literal);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "'''\nliteral\nstring'''";
BOOST_TEST(oss1.str() == oss2.str());
}
{
const std::string s1 ("literal\nstring");
const toml::string str(s1, toml::string_t::literal);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "'''\nliteral\nstring'''";
BOOST_TEST(oss1.str() == oss2.str());
}
}

View File

@@ -1,189 +0,0 @@
#define BOOST_TEST_MODULE "test_to_toml"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <map>
#include <list>
BOOST_AUTO_TEST_CASE(test_value_boolean)
{
toml::value v1 = toml::to_toml(true);
toml::value v2 = toml::to_toml(false);
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Boolean);
BOOST_CHECK(v1.is(toml::value_t::Boolean));
BOOST_CHECK(v2.is(toml::value_t::Boolean));
BOOST_CHECK(v1.is<toml::Boolean>());
BOOST_CHECK(v2.is<toml::Boolean>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
}
BOOST_AUTO_TEST_CASE(test_value_integer)
{
toml::value v1 = toml::to_toml(-42);
toml::value v2 = toml::to_toml(42u);
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Integer);
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Integer);
BOOST_CHECK(v1.is(toml::value_t::Integer));
BOOST_CHECK(v2.is(toml::value_t::Integer));
BOOST_CHECK(v1.is<toml::Integer>());
BOOST_CHECK(v2.is<toml::Integer>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), -42);
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), 42u);
}
BOOST_AUTO_TEST_CASE(test_value_float)
{
toml::value v1 = toml::to_toml(3.14);
toml::value v2 = toml::to_toml(3.14f);
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Float);
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Float);
BOOST_CHECK(v1.is(toml::value_t::Float));
BOOST_CHECK(v2.is(toml::value_t::Float));
BOOST_CHECK(v1.is<toml::Float>());
BOOST_CHECK(v2.is<toml::Float>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Float>(), 3.14);
BOOST_CHECK_CLOSE_FRACTION(v2.cast<toml::value_t::Float>(), 3.14, 1e-2);
}
BOOST_AUTO_TEST_CASE(test_value_string)
{
toml::value v1 = toml::to_toml(std::string("foo"));
toml::value v2 = toml::to_toml(std::string("foo"), toml::string_t::literal);
toml::value v3 = toml::to_toml("foo");
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::String);
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::String);
BOOST_CHECK_EQUAL(v3.type(), toml::value_t::String);
BOOST_CHECK(v1.is(toml::value_t::String));
BOOST_CHECK(v2.is(toml::value_t::String));
BOOST_CHECK(v3.is(toml::value_t::String));
BOOST_CHECK(v1.is<toml::String>());
BOOST_CHECK(v2.is<toml::String>());
BOOST_CHECK(v3.is<toml::String>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "foo");
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "foo");
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "foo");
}
BOOST_AUTO_TEST_CASE(test_value_local_date)
{
toml::value v1 = toml::to_toml(toml::local_date(2018, toml::month_t::Jan, 31));
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDate);
BOOST_CHECK(v1.is(toml::value_t::LocalDate));
BOOST_CHECK(v1.is<toml::LocalDate>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
toml::local_date(2018, toml::month_t::Jan, 31));
}
BOOST_AUTO_TEST_CASE(test_value_local_time)
{
toml::value v1 = toml::to_toml(toml::local_time(12, 30, 45));
toml::value v2 = toml::to_toml(std::chrono::hours(12) + std::chrono::minutes(30) +
std::chrono::seconds(45));
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalTime);
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::LocalTime);
BOOST_CHECK(v1.is(toml::value_t::LocalTime));
BOOST_CHECK(v2.is(toml::value_t::LocalTime));
BOOST_CHECK(v1.is<toml::LocalTime>());
BOOST_CHECK(v2.is<toml::LocalTime>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
toml::local_time(12, 30, 45));
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalTime>(),
toml::local_time(12, 30, 45));
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
v2.cast<toml::value_t::LocalTime>());
}
BOOST_AUTO_TEST_CASE(test_value_local_datetime)
{
toml::value v1 = toml::to_toml(toml::local_datetime(
toml::local_date(2018, toml::month_t::Jan, 31),
toml::local_time(12, 30, 45)
));
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::LocalDatetime);
BOOST_CHECK(v1.is(toml::value_t::LocalDatetime));
BOOST_CHECK(v1.is<toml::LocalDatetime>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDatetime>(),
toml::local_datetime(
toml::local_date(2018, toml::month_t::Jan, 31),
toml::local_time(12, 30, 45)));
}
BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
{
toml::value v1 = toml::to_toml(toml::offset_datetime(
toml::local_date(2018, toml::month_t::Jan, 31),
toml::local_time(12, 30, 45),
toml::time_offset(9, 0)
));
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::OffsetDatetime);
BOOST_CHECK(v1.is(toml::value_t::OffsetDatetime));
BOOST_CHECK(v1.is<toml::OffsetDatetime>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::OffsetDatetime>(),
toml::offset_datetime(
toml::local_date(2018, toml::month_t::Jan, 31),
toml::local_time(12, 30, 45),
toml::time_offset(9, 0)
));
}
BOOST_AUTO_TEST_CASE(test_value_array)
{
std::vector<int> v{1,2,3,4,5};
toml::value v1 = toml::to_toml(v);
toml::value v2 = toml::to_toml(6,7,8,9,0);
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Array);
BOOST_CHECK(v1.is(toml::value_t::Array));
BOOST_CHECK(v1.is<toml::Array>());
BOOST_CHECK_EQUAL(v2.type(), toml::value_t::Array);
BOOST_CHECK(v2.is(toml::value_t::Array));
BOOST_CHECK(v2.is<toml::Array>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 1);
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 2);
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
}
BOOST_AUTO_TEST_CASE(test_value_table)
{
toml::value v1 = toml::to_toml({{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}});
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Table);
BOOST_CHECK(v1.is(toml::value_t::Table));
BOOST_CHECK(v1.is<toml::Table>());
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Integer>(), 42);
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Float>(), 3.14);
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "qux");
}

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_CHECK(toml::detail::has_iterator<std::list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::has_iterator<std_array_type>::value);
BOOST_CHECK(toml::detail::has_iterator<std_map_type>::value);
BOOST_CHECK(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<std::list<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::forward_list<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::deque<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::vector<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::set<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::unordered_set<std::string>>::value);
BOOST_TEST(toml::detail::has_iterator<std_array_type>::value);
BOOST_TEST(toml::detail::has_iterator<std_map_type>::value);
BOOST_TEST(toml::detail::has_iterator<std_unordered_map_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_CHECK(toml::detail::has_value_type<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std_array_type>::value);
BOOST_CHECK(toml::detail::has_value_type<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::has_value_type<std_map_type>::value);
BOOST_CHECK(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<std::list<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::forward_list<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::deque<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::vector<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std_array_type>::value);
BOOST_TEST(toml::detail::has_value_type<std::set<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::unordered_set<std::string>>::value);
BOOST_TEST(toml::detail::has_value_type<std_map_type>::value);
BOOST_TEST(toml::detail::has_value_type<std_unordered_map_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_CHECK(toml::detail::has_key_type<std_unordered_map_type>::value);
BOOST_CHECK(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_key_type<std_map_type>::value);
BOOST_TEST(toml::detail::has_key_type<std_unordered_map_type>::value);
BOOST_TEST(toml::detail::has_mapped_type<std_map_type>::value);
BOOST_TEST(toml::detail::has_mapped_type<std_unordered_map_type>::value);
}
BOOST_AUTO_TEST_CASE(test_is_xxx)
{
BOOST_CHECK(toml::detail::is_container<std::list<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std_array_type>::value);
BOOST_CHECK(toml::detail::is_container<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::is_container<dummy_container<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::list<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::forward_list<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::deque<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::vector<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std_array_type>::value);
BOOST_TEST(toml::detail::is_container<std::set<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::unordered_set<std::string>>::value);
BOOST_TEST(toml::detail::is_container<dummy_container<dummy_type>>::value);
BOOST_CHECK(!toml::detail::is_container<std_map_type>::value);
BOOST_CHECK(!toml::detail::is_container<std_unordered_map_type>::value);
BOOST_TEST(!toml::detail::is_container<std_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_CHECK(toml::detail::is_map<std_unordered_map_type>::value);
BOOST_TEST(toml::detail::is_map<std_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::array<int,1> non_resizable_type;
BOOST_CHECK(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<resizable_type>::value);
BOOST_TEST(!toml::detail::has_resize_method<non_resizable_type>::value);
}
{
bool thrown = false;
std::vector<int> v;
try
{
toml::resize(v, 10);
}
catch(std::exception& ex)
{
thrown = true;
}
BOOST_CHECK(!thrown);
BOOST_CHECK_EQUAL(v.size(), 10u);
toml::resize(v, 10);
BOOST_TEST(v.size() == 10u);
}
{
bool thrown = false;
std::array<int, 15> a;
try
{
toml::resize(a, 10);
}
catch(std::exception& ex)
{
thrown = true;
}
BOOST_CHECK(!thrown);
BOOST_CHECK_EQUAL(a.size(), 15u);
toml::resize(a, 10);
BOOST_TEST(a.size() == 15u);
}
{
bool thrown = false;
std::array<int, 15> a;
try
{
toml::resize(a, 20);
}
catch(std::exception& ex)
{
thrown = true;
}
BOOST_CHECK(thrown);
BOOST_CHECK_THROW(toml::resize(a, 20), std::invalid_argument);
}
}
BOOST_AUTO_TEST_CASE(test_concat_to_string)
{
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)
{
{
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");
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

@@ -34,9 +34,8 @@
#endif
#include "toml/parser.hpp"
#include "toml/literal.hpp"
#include "toml/serializer.hpp"
#include "toml/to_toml.hpp"
#include "toml/from_toml.hpp"
#include "toml/get.hpp"
#endif// TOML_FOR_MODERN_CPP

View File

@@ -9,7 +9,10 @@
#include <type_traits>
#include <iterator>
#include <limits>
#include <array>
#include <iomanip>
#include <cstdio>
#include <cassert>
#include <cctype>
// they scans characters and returns region if it matches to the condition.
@@ -38,10 +41,12 @@ inline std::string show_char(const char c)
}
else
{
std::ostringstream oss;
oss << "0x" << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int>(c);
return oss.str();
std::array<char, 5> buf;
buf.fill('\0');
const auto r = std::snprintf(
buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
assert(r == static_cast<int>(buf.size()) - 1);
return std::string(buf.data());
}
}
@@ -51,26 +56,24 @@ struct character
static constexpr char target = C;
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
if(loc.iter() == loc.end()) {return none();}
const auto first = loc.iter();
const char c = *(loc.iter());
if(c != target)
{
return err(concat_to_string("expected '", show_char(target),
"' but got '", show_char(c), "'."));
return none();
}
++(loc.iter()); // update location
loc.advance(); // update location
return ok(region<Cont>(loc, first, loc.iter()));
}
static std::string pattern() {return show_char(target);}
};
template<char C>
constexpr char character<C>::target;
@@ -86,30 +89,24 @@ struct in_range
static constexpr char lower = Low;
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
if(loc.iter() == loc.end()) {return none();}
const auto first = loc.iter();
const char c = *(loc.iter());
if(c < lower || upper < c)
{
return err(concat_to_string("expected character in range "
"[", show_char(lower), ", ", show_char(upper), "] but got ",
"'", show_char(c), "'."));
return none();
}
++(loc.iter());
loc.advance();
return ok(region<Cont>(loc, first, loc.iter()));
}
static std::string pattern()
{
return concat_to_string("[",show_char(lower),"-",show_char(upper),"]");
}
};
template<char L, char U> constexpr char in_range<L, U>::upper;
template<char L, char U> constexpr char in_range<L, U>::lower;
@@ -120,30 +117,24 @@ template<typename Combinator>
struct exclude
{
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
if(loc.iter() == loc.end()) {return none();}
auto first = loc.iter();
auto rslt = Combinator::invoke(loc);
if(rslt.is_ok())
{
loc.iter() = first; // rollback
return err(concat_to_string(
"invalid pattern (", Combinator::pattern(), ") appeared ",
rslt.unwrap().str()));
loc.reset(first);
return none();
}
loc.iter() = std::next(first);
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
return ok(region<Cont>(loc, first, loc.iter()));
}
static std::string pattern()
{
return concat_to_string("^(", Combinator::pattern(), ')');
}
};
// increment `iter`, if matches. otherwise, just return empty string.
@@ -151,7 +142,8 @@ template<typename Combinator>
struct maybe
{
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
@@ -163,11 +155,6 @@ struct maybe
}
return ok(region<Cont>(loc));
}
static std::string pattern()
{
return concat_to_string('(', Combinator::pattern(), ")?");
}
};
template<typename ... Ts>
@@ -177,7 +164,8 @@ template<typename Head, typename ... Tail>
struct sequence<Head, Tail...>
{
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
@@ -186,31 +174,26 @@ struct sequence<Head, Tail...>
const auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.iter() = first;
return err(rslt.unwrap_err());
loc.reset(first);
return none();
}
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
}
// called from the above function only, recursively.
template<typename Cont, typename Iterator>
static result<region<Cont>, std::string>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
{
const auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.iter() = first;
return err(rslt.unwrap_err());
loc.reset(first);
return none();
}
reg += rslt.unwrap(); // concat regions
return sequence<Tail...>::invoke(loc, std::move(reg), first);
}
static std::string pattern()
{
return concat_to_string(Head::pattern(), sequence<Tail...>::pattern());
}
};
template<typename Head>
@@ -218,19 +201,18 @@ struct sequence<Head>
{
// would be called from sequence<T ...>::invoke only.
template<typename Cont, typename Iterator>
static result<region<Cont>, std::string>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
{
const auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.iter() = first;
return err(rslt.unwrap_err());
loc.reset(first);
return none();
}
reg += rslt.unwrap(); // concat regions
return ok(reg);
}
static std::string pattern() {return Head::pattern();}
};
template<typename ... Ts>
@@ -240,7 +222,8 @@ template<typename Head, typename ... Tail>
struct either<Head, Tail...>
{
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
@@ -249,26 +232,18 @@ struct either<Head, Tail...>
if(rslt.is_ok()) {return rslt;}
return either<Tail...>::invoke(loc);
}
static std::string pattern()
{
return concat_to_string('(', Head::pattern(), ")|", either<Tail...>::pattern());
}
};
template<typename Head>
struct either<Head>
{
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");
return Head::invoke(loc);
}
static std::string pattern()
{
return concat_to_string('(', Head::pattern(), ')');
}
};
template<typename T, typename N>
@@ -282,7 +257,8 @@ template<typename T, std::size_t N>
struct repeat<T, exactly<N>>
{
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
const auto first = loc.iter();
@@ -291,24 +267,21 @@ struct repeat<T, exactly<N>>
auto rslt = T::invoke(loc);
if(rslt.is_err())
{
loc.iter() = first;
return err(rslt.unwrap_err());
loc.reset(first);
return none();
}
retval += rslt.unwrap();
}
return ok(std::move(retval));
}
static std::string pattern()
{
return concat_to_string('(', T::pattern(), "){", N, '}');
}
};
template<typename T, std::size_t N>
struct repeat<T, at_least<N>>
{
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
@@ -318,8 +291,8 @@ struct repeat<T, at_least<N>>
auto rslt = T::invoke(loc);
if(rslt.is_err())
{
loc.iter() = first;
return err(rslt.unwrap_err());
loc.reset(first);
return none();
}
retval += rslt.unwrap();
}
@@ -333,17 +306,14 @@ struct repeat<T, at_least<N>>
retval += rslt.unwrap();
}
}
static std::string pattern()
{
return concat_to_string('(',T::pattern(), "){", N, ",}");
}
};
template<typename T>
struct repeat<T, unlimited>
{
template<typename Cont>
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
while(true)
@@ -356,7 +326,6 @@ struct repeat<T, unlimited>
retval += rslt.unwrap();
}
}
static std::string pattern() {return concat_to_string('(', T::pattern(), ")*");}
};
} // detail

416
toml/comments.hpp Normal file
View File

@@ -0,0 +1,416 @@
// 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&, const preserve_comments&);
friend bool operator!=(const preserve_comments&, const preserve_comments&);
friend bool operator< (const preserve_comments&, const preserve_comments&);
friend bool operator<=(const preserve_comments&, const preserve_comments&);
friend bool operator> (const preserve_comments&, const preserve_comments&);
friend bool operator>=(const preserve_comments&, const preserve_comments&);
friend void swap(preserve_comments&, std::vector<std::string>&);
friend void swap(std::vector<std::string>&, preserve_comments&);
private:
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;
}
inline void swap(preserve_comments& lhs, std::vector<std::string>& rhs)
{
lhs.comments.swap(rhs);
return;
}
inline void swap(std::vector<std::string>& lhs, preserve_comments& rhs)
{
lhs.swap(rhs.comments);
return;
}
template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const preserve_comments& com)
{
for(const auto& c : com)
{
os << '#' << c << '\n';
}
return os;
}
namespace detail
{
// 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;}
template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const discard_comments&)
{
return os;
}
} // toml11
#endif// TOML11_COMMENTS_HPP

View File

@@ -1,7 +1,7 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_DATETIME
#define TOML11_DATETIME
#ifndef TOML11_DATETIME_HPP
#define TOML11_DATETIME_HPP
#include <chrono>
#include <tuple>
#include <array>
@@ -25,26 +25,28 @@ inline std::tm localtime_s(const std::time_t* src)
{
std::tm dst;
const auto result = ::localtime_r(src, &dst);
if(!result)
{
throw std::runtime_error("localtime_r failed.");
}
if (!result) { throw std::runtime_error("localtime_r failed."); }
return dst;
}
#elif _MSC_VER
inline std::tm localtime_s(const std::time_t* src)
{
std::tm dst;
const auto result = ::localtime_s(&dst, src);
if (result) { throw std::runtime_error("localtime_s failed."); }
return dst;
}
#else
// XXX: On Windows, std::localtime is thread-safe because they uses thread-local
// storage to store the instance of std::tm. On the other platforms, it may not
// be thread-safe.
inline std::tm localtime_s(const std::time_t* src)
{
const auto result = std::localtime(src);
if(!result) {throw std::runtime_error("localtime failed.");}
if (!result) { throw std::runtime_error("localtime failed."); }
return *result;
}
#endif
} // detail
enum class month_t : std::int8_t
enum class month_t : std::uint8_t
{
Jan = 0,
Feb = 1,
@@ -96,9 +98,9 @@ struct local_date
t.tm_sec = 0;
t.tm_min = 0;
t.tm_hour = 0;
t.tm_mday = this->day;
t.tm_mon = this->month;
t.tm_year = this->year - 1900;
t.tm_mday = static_cast<int>(this->day);
t.tm_mon = static_cast<int>(this->month);
t.tm_year = static_cast<int>(this->year) - 1900;
t.tm_wday = 0; // the value will be ignored
t.tm_yday = 0; // the value will be ignored
t.tm_isdst = -1;
@@ -186,22 +188,22 @@ struct local_time
explicit local_time(const std::chrono::duration<Rep, Period>& t)
{
const auto h = std::chrono::duration_cast<std::chrono::hours>(t);
this->hour = h.count();
this->hour = static_cast<std::uint8_t>(h.count());
const auto t2 = t - h;
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 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 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 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 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
@@ -332,17 +334,10 @@ operator<<(std::basic_ostream<charT, traits>& os, const time_offset& offset)
os << 'Z';
return os;
}
if(static_cast<int>(offset.hour) * static_cast<int>(offset.minute) < 0)
{
const int min = static_cast<int>(offset.hour) * 60 + offset.minute;
if(min < 0){os << '-';} else {os << '+';}
os << std::setfill('0') << std::setw(2) << min / 60 << ':';
os << std::setfill('0') << std::setw(2) << min % 60;
return os;
}
if(offset.hour < 0){os << '-';} else {os << '+';}
os << std::setfill('0') << std::setw(2) << static_cast<int>(offset.hour) << ':';
os << std::setfill('0') << std::setw(2) << static_cast<int>(offset.minute);
int minute = static_cast<int>(offset.hour) * 60 + offset.minute;
if(minute < 0){os << '-'; minute = std::abs(minute);} else {os << '+';}
os << std::setfill('0') << std::setw(2) << minute / 60 << ':';
os << std::setfill('0') << std::setw(2) << minute % 60;
return os;
}
@@ -358,21 +353,21 @@ struct local_datetime
explicit local_datetime(const std::chrono::system_clock::time_point& tp)
{
const auto t = std::chrono::system_clock::to_time_t(tp);
std::tm time = detail::localtime_s(&t);
std::tm ltime = detail::localtime_s(&t);
this->date = local_date(time);
this->time = local_time(time);
this->date = local_date(ltime);
this->time = local_time(ltime);
// std::tm lacks subsecond information, so diff between tp and tm
// can be used to get millisecond & microsecond information.
const auto t_diff = tp -
std::chrono::system_clock::from_time_t(std::mktime(&time));
this->time.millisecond = std::chrono::duration_cast<
std::chrono::milliseconds>(t_diff).count();
this->time.microsecond = std::chrono::duration_cast<
std::chrono::microseconds>(t_diff).count();
this->time.nanosecond = std::chrono::duration_cast<
std::chrono::nanoseconds >(t_diff).count();
std::chrono::system_clock::from_time_t(std::mktime(&ltime));
this->time.millisecond = static_cast<std::uint16_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(t_diff).count());
this->time.microsecond = static_cast<std::uint16_t>(
std::chrono::duration_cast<std::chrono::microseconds>(t_diff).count());
this->time.nanosecond = static_cast<std::uint16_t>(
std::chrono::duration_cast<std::chrono::nanoseconds >(t_diff).count());
}
explicit local_datetime(const std::time_t t)

View File

@@ -1,7 +1,7 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_EXCEPTION
#define TOML11_EXCEPTION
#ifndef TOML11_EXCEPTION_HPP
#define TOML11_EXCEPTION_HPP
#include <stdexcept>
#include <string>

20
toml/from.hpp Normal file
View File

@@ -0,0 +1,20 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_FROM_HPP
#define TOML11_FROM_HPP
#include "traits.hpp"
namespace toml
{
template<typename T>
struct from;
// {
// static T from_toml(const toml::value& v)
// {
// // User-defined conversions ...
// }
// };
} // toml
#endif // TOML11_FROM_HPP

View File

@@ -1,71 +0,0 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_FROM_TOML
#define TOML11_FROM_TOML
#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& ...> tie, const toml::value& v)
{
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

20
toml/into.hpp Normal file
View File

@@ -0,0 +1,20 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_INTO_HPP
#define TOML11_INTO_HPP
#include "traits.hpp"
namespace toml
{
template<typename T>
struct into;
// {
// static toml::value into_toml(const T& user_defined_type)
// {
// // User-defined conversions ...
// }
// };
} // toml
#endif // TOML11_INTO_HPP

86
toml/literal.hpp Normal file
View File

@@ -0,0 +1,86 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_LITERAL_HPP
#define TOML11_LITERAL_HPP
#include "parser.hpp"
namespace toml
{
inline namespace literals
{
inline namespace toml_literals
{
inline ::toml::value operator"" _toml(const char* str, std::size_t len)
{
::toml::detail::location<std::vector<char>>
loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
/* contents = */ std::vector<char>(str, str + len));
// if there are some comments or empty lines, skip them.
using skip_line = ::toml::detail::repeat<toml::detail::sequence<
::toml::detail::maybe<::toml::detail::lex_ws>,
::toml::detail::maybe<::toml::detail::lex_comment>,
::toml::detail::lex_newline
>, ::toml::detail::at_least<1>>;
skip_line::invoke(loc);
// if there are some whitespaces before a value, skip them.
using skip_ws = ::toml::detail::repeat<
::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
skip_ws::invoke(loc);
// to distinguish arrays and tables, first check it is a table or not.
//
// "[1,2,3]"_toml; // this is an array
// "[table]"_toml; // a table that has an empty table named "table" inside.
// "[[1,2,3]]"_toml; // this is an array of arrays
// "[[table]]"_toml; // this is a table that has an array of tables inside.
//
// "[[1]]"_toml; // this can be both... (currently it becomes a table)
// "1 = [{}]"_toml; // this is a table that has an array of table named 1.
// "[[1,]]"_toml; // this is an array of arrays.
// "[[1],]"_toml; // this also.
const auto the_front = loc.iter();
const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
loc.reset(the_front);
const bool is_aots_key = ::toml::detail::lex_array_table::invoke(loc);
loc.reset(the_front);
// If it is neither a table-key or a array-of-table-key, it may be a value.
if(!is_table_key && !is_aots_key)
{
if(auto data = ::toml::detail::parse_value<::toml::value>(loc))
{
return data.unwrap();
}
}
// Note that still it can be a table, because the literal might be something
// like the following.
// ```cpp
// R"( // c++11 raw string literals
// key = "value"
// int = 42
// )"_toml;
// ```
// It is a valid toml file.
// It should be parsed as if we parse a file with this content.
if(auto data = ::toml::detail::parse_toml_file<::toml::value>(loc))
{
return data.unwrap();
}
else // none of them.
{
throw ::toml::syntax_error(data.unwrap_err());
}
}
} // toml_literals
} // literals
} // toml
#endif//TOML11_LITERAL_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_REGION_H
#define TOML11_REGION_H
#ifndef TOML11_REGION_HPP
#define TOML11_REGION_HPP
#include "exception.hpp"
#include <memory>
#include <vector>
@@ -9,13 +9,14 @@
#include <initializer_list>
#include <iterator>
#include <iomanip>
#include <cassert>
namespace toml
{
namespace detail
{
// helper function to avoid std::string(0, 'c')
// helper function to avoid std::string(0, 'c') or std::string(iter, iter)
template<typename Iterator>
std::string make_string(Iterator first, Iterator last)
{
@@ -28,9 +29,7 @@ inline std::string make_string(std::size_t len, char c)
return std::string(len, c);
}
// region in a container, normally in a file content.
// shared_ptr points the resource that the iter points.
// combinators returns this.
// region_base is a base class of location and region that are defined below.
// it will be used to generate better error messages.
struct region_base
{
@@ -48,25 +47,39 @@ struct region_base
virtual std::string line() const {return std::string("unknown line");}
virtual std::string line_num() const {return std::string("?");}
virtual std::size_t before() const noexcept {return 0;}
// length of the region
virtual std::size_t size() const noexcept {return 0;}
// number of characters in the line before the region
virtual std::size_t before() const noexcept {return 0;}
// number of characters in the line after the region
virtual std::size_t after() const noexcept {return 0;}
virtual std::vector<std::string> comments()const {return {};}
// ```toml
// # comment_before
// key = "value" # comment_inline
// ```
};
// location in a container, normally in a file content.
// shared_ptr points the resource that the iter points.
// it can be used not only for resource handling, but also error message.
//
// location represents a position in a container, which contains a file content.
// it can be considered as a region that contains only one character.
//
// it contains pointer to the file content and iterator that points the current
// location.
template<typename Container>
struct location final : public region_base
{
using const_iterator = typename Container::const_iterator;
using difference_type = typename const_iterator::difference_type;
using source_ptr = std::shared_ptr<const Container>;
static_assert(std::is_same<char, typename Container::value_type>::value,"");
using const_iterator = typename Container::const_iterator;
using source_ptr = std::shared_ptr<const Container>;
static_assert(std::is_same<std::random_access_iterator_tag,
typename std::iterator_traits<const_iterator>::iterator_category>::value,
"container should be randomly accessible");
location(std::string name, Container cont)
: source_(std::make_shared<Container>(std::move(cont))),
: source_(std::make_shared<Container>(std::move(cont))), line_number_(1),
source_name_(std::move(name)), iter_(source_->cbegin())
{}
location(const location&) = default;
@@ -77,18 +90,58 @@ struct location final : public region_base
bool is_ok() const noexcept override {return static_cast<bool>(source_);}
const_iterator& iter() noexcept {return iter_;}
const_iterator iter() const noexcept {return iter_;}
// this const prohibits codes like `++(loc.iter())`.
const const_iterator iter() const noexcept {return iter_;}
const_iterator begin() const noexcept {return source_->cbegin();}
const_iterator end() const noexcept {return source_->cend();}
const_iterator begin() const noexcept {return source_->cbegin();}
const_iterator end() const noexcept {return source_->cend();}
// XXX `location::line_num()` used to be implemented using `std::count` to
// count a number of '\n'. But with a long toml file (typically, 10k lines),
// it becomes intolerably slow because each time it generates error messages,
// it counts '\n' from thousands of characters. To workaround it, I decided
// to introduce `location::line_number_` member variable and synchronize it
// to the location changes the point to look. So an overload of `iter()`
// which returns mutable reference is removed and `advance()`, `retrace()`
// and `reset()` is added.
void advance(difference_type n = 1) noexcept
{
this->line_number_ += static_cast<std::size_t>(
std::count(this->iter_, std::next(this->iter_, n), '\n'));
this->iter_ += n;
return;
}
void retrace(difference_type n = 1) noexcept
{
this->line_number_ -= static_cast<std::size_t>(
std::count(std::prev(this->iter_, n), this->iter_, '\n'));
this->iter_ -= n;
return;
}
void reset(const_iterator rollback) noexcept
{
// since c++11, std::distance works in both ways for random-access
// iterators and returns a negative value if `first > last`.
if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
{
this->line_number_ -= static_cast<std::size_t>(
std::count(rollback, this->iter_, '\n'));
}
else // iter < rollback [[unlikely]]
{
this->line_number_ += static_cast<std::size_t>(
std::count(this->iter_, rollback, '\n'));
}
this->iter_ = rollback;
return;
}
std::string str() const override {return make_string(1, *this->iter());}
std::string name() const override {return source_name_;}
std::string line_num() const override
{
return std::to_string(1+std::count(this->begin(), this->iter(), '\n'));
return std::to_string(this->line_number_);
}
std::string line() const override
@@ -114,11 +167,15 @@ struct location final : public region_base
}
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
{
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_;}
@@ -127,17 +184,26 @@ struct location final : public region_base
private:
source_ptr source_;
std::size_t line_number_;
std::string source_name_;
const_iterator iter_;
};
// region represents a range in a container, which contains a file content.
//
// it contains pointer to the file content and iterator that points the first
// and last location.
template<typename Container>
struct region final : public region_base
{
static_assert(std::is_same<char, typename Container::value_type>::value,"");
using const_iterator = typename Container::const_iterator;
using source_ptr = std::shared_ptr<const Container>;
static_assert(std::is_same<char, typename Container::value_type>::value,"");
static_assert(std::is_same<std::random_access_iterator_tag,
typename std::iterator_traits<const_iterator>::iterator_category>::value,
"container should be randomly accessible");
// delete default constructor. source_ never be null.
region() = delete;
@@ -193,15 +259,21 @@ struct region final : public region_base
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
{
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
{
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
@@ -230,6 +302,114 @@ struct region final : public region_base
std::string name() const override {return source_name_;}
std::vector<std::string> comments() const override
{
// assuming the current region (`*this`) points a value.
// ```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())
{
iter = std::prev(iter);
// range [line_start, iter) represents the previous line
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 {
return c == ' ' || c == '\t';
}))
{
// unwrap the first '#' by std::next.
auto str = make_string(std::next(comment_found), iter);
if(str.back() == '\r') {str.pop_back();}
com.push_back(std::move(str));
}
else
{
break;
}
iter = line_start;
}
}
}
if(com.size() > 1)
{
std::reverse(com.begin(), com.end());
}
{
// find comments just after the current region.
// ```toml
// # not this.
// a = value # this one.
// a = [ # not this (technically difficult)
//
// ] # and this.
// ```
// The reason why it's difficult is that it requires parsing in the
// following case.
// ```toml
// a = [ 10 # this comment is for `10`. not for `a` but `a[0]`.
// # ...
// ] # this is apparently a comment for a.
//
// b = [
// 3.14 ] # there is no way to add a comment to `3.14` currently.
//
// c = [
// 3.14 # do this if you need a comment here.
// ]
// ```
const auto comment_found =
std::find(this->last(), this->line_end(), '#');
if(comment_found != this->line_end()) // '#' found
{
// table = {key = "value"} # what is this for?
// the above comment is not for "value", but {key="value"}.
if(comment_found == std::find_if(this->last(), comment_found,
[](const char c) noexcept -> bool {
return !(c == ' ' || c == '\t' || c == ',');
}))
{
// unwrap the first '#' by std::next.
auto str = make_string(std::next(comment_found), this->line_end());
if(str.back() == '\r') {str.pop_back();}
com.push_back(std::move(str));
}
}
}
return com;
}
private:
source_ptr source_;
@@ -239,47 +419,42 @@ struct region final : public region_base
// to show a better error message.
inline std::string format_underline(const std::string& message,
std::vector<std::pair<region_base const*, std::string>> reg_com,
std::vector<std::string> helps = {})
const std::vector<std::pair<region_base const*, std::string>>& reg_com,
const std::vector<std::string>& helps = {})
{
assert(!reg_com.empty());
#ifdef _WIN32
const auto newline = "\r\n";
#else
const char newline = '\n';
#endif
const auto line_num_width = std::max_element(reg_com.begin(), reg_com.end(),
const auto line_num_width = static_cast<int>(std::max_element(
reg_com.begin(), reg_com.end(),
[](std::pair<region_base const*, std::string> const& lhs,
std::pair<region_base const*, std::string> const& rhs)
{
return lhs.first->line_num().size() < rhs.first->line_num().size();
}
)->first->line_num().size();
)->first->line_num().size());
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;}
retval << " --> " << reg_com.at(i).first->name() << newline;
if(iter != reg_com.begin()) {retval << '\n';}
retval << " --> " << iter->first->name() << '\n';
}
const region_base* const reg = reg_com.at(i).first;
const std::string& comment = reg_com.at(i).second;
const region_base* const reg = iter->first;
const std::string& comment = iter->second;
retval << ' ' << std::setw(line_num_width) << reg->line_num();
retval << " | " << reg->line() << newline;
retval << make_string(line_num_width + 1, ' ');
retval << " | " << reg->line() << '\n';
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
retval << " | " << make_string(reg->before(), ' ');
if(reg->size() == 1)
@@ -293,22 +468,21 @@ inline std::string format_underline(const std::string& message,
{
// invalid
// ~~~~~~~
retval << make_string(reg->size(), '~');
const auto underline_len = std::min(reg->size(), reg->line().size());
retval << make_string(underline_len, '~');
}
retval << ' ';
retval << comment;
}
if(helps.size() != 0)
if(!helps.empty())
{
retval << newline;
retval << make_string(line_num_width + 1, ' ');
retval << '\n';
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
retval << " | ";
for(const auto help : helps)
{
retval << newline;
retval << "Hint: ";
retval << "\nHint: ";
retval << help;
}
}

View File

@@ -1,7 +1,7 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_RESULT_H
#define TOML11_RESULT_H
#ifndef TOML11_RESULT_HPP
#define TOML11_RESULT_HPP
#include "traits.hpp"
#include <type_traits>
#include <stdexcept>
@@ -113,21 +113,25 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
result(const failure_type& f): is_ok_(false)
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
result(success_type&& s): is_ok_(true)
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
result(failure_type&& f): is_ok_(false)
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
template<typename U>
@@ -135,24 +139,28 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
template<typename U>
result(const failure<U>& f): is_ok_(false)
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
template<typename U>
result(success<U>&& s): is_ok_(true)
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
template<typename U>
result(failure<U>&& f): is_ok_(false)
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
result& operator=(const success_type& s)
@@ -161,6 +169,7 @@ struct result
this->is_ok_ = true;
auto tmp = ::new(std::addressof(this->succ)) success_type(s);
assert(tmp == std::addressof(this->succ));
(void)tmp;
return *this;
}
result& operator=(const failure_type& f)
@@ -169,6 +178,7 @@ struct result
this->is_ok_ = false;
auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
assert(tmp == std::addressof(this->fail));
(void)tmp;
return *this;
}
result& operator=(success_type&& s)
@@ -177,6 +187,7 @@ struct result
this->is_ok_ = true;
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
assert(tmp == std::addressof(this->succ));
(void)tmp;
return *this;
}
result& operator=(failure_type&& f)
@@ -185,6 +196,7 @@ struct result
this->is_ok_ = false;
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
assert(tmp == std::addressof(this->fail));
(void)tmp;
return *this;
}
@@ -195,6 +207,7 @@ struct result
this->is_ok_ = true;
auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
assert(tmp == std::addressof(this->succ));
(void)tmp;
return *this;
}
template<typename U>
@@ -204,6 +217,7 @@ struct result
this->is_ok_ = false;
auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
assert(tmp == std::addressof(this->fail));
(void)tmp;
return *this;
}
template<typename U>
@@ -213,6 +227,7 @@ struct result
this->is_ok_ = true;
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
assert(tmp == std::addressof(this->succ));
(void)tmp;
return *this;
}
template<typename U>
@@ -222,6 +237,7 @@ struct result
this->is_ok_ = false;
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
assert(tmp == std::addressof(this->fail));
(void)tmp;
return *this;
}
@@ -233,11 +249,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
}
result(result&& other): is_ok_(other.is_ok())
@@ -246,11 +264,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
}
@@ -261,11 +281,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
}
template<typename U, typename F>
@@ -275,11 +297,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
}
@@ -290,11 +314,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
is_ok_ = other.is_ok();
return *this;
@@ -306,11 +332,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
is_ok_ = other.is_ok();
return *this;
@@ -324,11 +352,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
is_ok_ = other.is_ok();
return *this;
@@ -341,11 +371,13 @@ struct result
{
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
assert(tmp == std::addressof(this->succ));
(void)tmp;
}
else
{
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
assert(tmp == std::addressof(this->fail));
(void)tmp;
}
is_ok_ = other.is_ok();
return *this;
@@ -660,5 +692,26 @@ void swap(result<T, E>& lhs, result<T, E>& rhs)
// return lhs.is_ok() ? lhs : rhs;
// }
// ----------------------------------------------------------------------------
// re-use result<T, E> as a optional<T> with none_t
namespace detail
{
struct none_t {};
inline bool operator==(const none_t&, const none_t&) noexcept {return true;}
inline bool operator!=(const none_t&, const none_t&) noexcept {return false;}
inline bool operator< (const none_t&, const none_t&) noexcept {return false;}
inline bool operator<=(const none_t&, const none_t&) noexcept {return true;}
inline bool operator> (const none_t&, const none_t&) noexcept {return false;}
inline bool operator>=(const none_t&, const none_t&) noexcept {return true;}
template<typename charT, typename traitsT>
std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&)
{
os << "none";
return os;
}
inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};}
} // detail
} // toml11
#endif// TOML11_RESULT_H

View File

@@ -10,30 +10,88 @@
namespace toml
{
// This function serialize a key. It checks a string is a bare key and
// escapes special characters if the string is not compatible to a bare key.
// ```cpp
// std::string k("non.bare.key"); // the key itself includes `.`s.
// std::string formatted = toml::format_key(k);
// assert(formatted == "\"non.bare.key\"");
// ```
//
// This function is exposed to make it easy to write a user-defined serializer.
// Since toml restricts characters available in a bare key, generally a string
// should be escaped. But checking whether a string needs to be surrounded by
// a `"` and escaping some special character is boring.
inline std::string format_key(const toml::key& key)
{
detail::location<toml::key> loc(key, key);
detail::lex_unquoted_key::invoke(loc);
if(loc.iter() == loc.end())
{
return key; // all the tokens are consumed. the key is unquoted-key.
}
std::string token("\"");
for(const char c : key)
{
switch(c)
{
case '\\': {token += "\\\\"; break;}
case '\"': {token += "\\\""; break;}
case '\b': {token += "\\b"; break;}
case '\t': {token += "\\t"; break;}
case '\f': {token += "\\f"; break;}
case '\n': {token += "\\n"; break;}
case '\r': {token += "\\r"; break;}
default : {token += c; break;}
}
}
token += "\"";
return token;
}
template<typename Comment,
template<typename ...> class Table,
template<typename ...> class Array>
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 bool can_be_inlined = false,
const bool no_comment = false,
std::vector<toml::key> ks = {})
: can_be_inlined_(can_be_inlined), float_prec_(float_prec), width_(w),
keys_(std::move(ks))
: can_be_inlined_(can_be_inlined), no_comment_(no_comment),
float_prec_(float_prec), width_(w), keys_(std::move(ks))
{}
~serializer() = default;
std::string operator()(const toml::boolean& b) const
std::string operator()(const boolean_type& b) const
{
return b ? "true" : "false";
}
std::string operator()(const integer i) const
std::string operator()(const integer_type i) const
{
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 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::string token(buf.begin(), std::prev(buf.end()));
@@ -41,16 +99,27 @@ struct serializer
{
token += '0';
}
const auto e = std::find_if(token.cbegin(), token.cend(),
[](const char c) -> bool {
return c == 'E' || c == 'e';
const auto e = std::find_if(
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.
}
// 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.
bool sign_exists = false;
std::size_t zero_prefix = 0;
@@ -64,11 +133,12 @@ struct serializer
{
const auto offset = std::distance(token.cbegin(), e) +
(sign_exists ? 2 : 1);
token.erase(offset, zero_prefix);
token.erase(static_cast<typename std::string::size_type>(offset),
zero_prefix);
}
return token;
}
std::string operator()(const string& s) const
std::string operator()(const string_type& s) const
{
if(s.kind == string_t::basic)
{
@@ -130,37 +200,44 @@ struct serializer
}
}
std::string operator()(const local_date& d) const
std::string operator()(const local_date_type& d) const
{
std::ostringstream oss;
oss << d;
return oss.str();
}
std::string operator()(const local_time& t) const
std::string operator()(const local_time_type& t) const
{
std::ostringstream oss;
oss << t;
return oss.str();
}
std::string operator()(const local_datetime& dt) const
std::string operator()(const local_datetime_type& dt) const
{
std::ostringstream oss;
oss << dt;
return oss.str();
}
std::string operator()(const offset_datetime& odt) const
std::string operator()(const offset_datetime_type& odt) const
{
std::ostringstream oss;
oss << odt;
return oss.str();
}
std::string operator()(const array& v) const
std::string operator()(const array_type& v) const
{
if(!v.empty() && v.front().is(value_t::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]]`.
// but if it can be inlined, we need `table.key = [...]`.
// but if it can be inlined,
// ```
// table.key = [
// {...},
// # comment
// {...},
// ]
// ```
if(this->can_be_inlined_)
{
std::string token;
@@ -169,37 +246,62 @@ struct serializer
token += this->serialize_key(keys_.back());
token += " = ";
}
bool width_exceeds = false;
bool failed = false;
token += "[\n";
for(const auto& item : v)
{
const auto t =
this->make_inline_table(item.cast<value_t::Table>());
// if an element of the table has a comment, the table
// cannot be inlined.
if(this->has_comment_inside(item.as_table()))
{
failed = true;
break;
}
if(!no_comment_)
{
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 {...},
std::find(t.cbegin(), t.cend(), '\n') != t.cend())
{
width_exceeds = true;
failed = true;
break;
}
token += t;
token += ",\n";
}
if(!width_exceeds)
if(!failed)
{
token += "]\n";
return token;
}
// if width_exceeds, serialize it as [[array.of.tables]].
// if failed, serialize them as [[array.of.tables]].
}
std::string token;
for(const auto& item : v)
{
if(!no_comment_)
{
for(const auto& c : item.comments())
{
token += '#';
token += c;
token += '\n';
}
}
token += "[[";
token += this->serialize_dotted_key(keys_);
token += "]]\n";
token += this->make_multiline_table(item.cast<value_t::Table>());
token += this->make_multiline_table(item.as_table());
}
return token;
}
@@ -208,7 +310,9 @@ struct serializer
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);
if(inl.size() < this->width_ &&
@@ -218,16 +322,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 current_line;
token += "[\n";
for(const auto& item : v)
{
auto next_elem = toml::visit(*this, item);
// newline between array-value and comma is not allowed
if(next_elem.back() == '\n'){next_elem.pop_back();}
if(!item.comments().empty() && !no_comment_)
{
// 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_)
{
current_line += next_elem;
@@ -235,12 +377,13 @@ struct serializer
}
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 += ",\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() == ',');
token += current_line;
@@ -258,9 +401,12 @@ struct serializer
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;
if(!this->keys_.empty())
@@ -269,7 +415,8 @@ struct serializer
token += " = ";
}
token += this->make_inline_table(v);
if(token.size() < this->width_)
if(token.size() < this->width_ &&
token.end() == std::find(token.begin(), token.end(), '\n'))
{
return token;
}
@@ -290,16 +437,7 @@ struct serializer
std::string serialize_key(const toml::key& key) const
{
detail::location<toml::key> loc(key, key);
detail::lex_unquoted_key::invoke(loc);
if(loc.iter() == loc.end())
{
return key; // all the tokens are consumed. the key is unquoted-key.
}
std::string token("\"");
token += this->escape_basic_string(key);
token += "\"";
return token;
return ::toml::format_key(key);
}
std::string serialize_dotted_key(const std::vector<toml::key>& keys) const
@@ -369,8 +507,33 @@ struct serializer
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
{
// if no_comment is set, comments would not be written.
if(this->no_comment_) {return false;}
for(const auto& v : a)
{
if(!v.comments().empty()) {return true;}
}
return false;
}
bool has_comment_inside(const table_type& t) const noexcept
{
// if no_comment is set, comments would not be written.
if(this->no_comment_) {return false;}
for(const auto& kv : t)
{
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;
token += '[';
bool is_first = true;
@@ -384,8 +547,9 @@ struct serializer
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_);
std::string token;
token += '{';
@@ -403,7 +567,7 @@ struct serializer
return token;
}
std::string make_multiline_table(const table& v) const
std::string make_multiline_table(const table_type& v) const
{
std::string token;
@@ -411,11 +575,20 @@ struct serializer
// remaining non-table values will be assigned into [foo.bar], not [foo]
for(const auto kv : v)
{
if(kv.second.is(value_t::Table) || is_array_of_tables(kv.second))
if(kv.second.is_table() || is_array_of_tables(kv.second))
{
continue;
}
if(!kv.second.comments().empty() && !no_comment_)
{
for(const auto& c : kv.second.comments())
{
token += '#';
token += c;
token += '\n';
}
}
const auto key_and_sep = this->serialize_key(kv.first) + " = ";
const auto residual_width = (this->width_ > key_and_sep.size()) ?
this->width_ - key_and_sep.size() : 0;
@@ -438,7 +611,7 @@ struct serializer
bool multiline_table_printed = false;
for(const auto& kv : v)
{
if(!kv.second.is(value_t::Table) && !is_array_of_tables(kv.second))
if(!kv.second.is_table() && !is_array_of_tables(kv.second))
{
continue; // other stuff are already serialized. skip them.
}
@@ -446,8 +619,8 @@ struct serializer
std::vector<toml::key> ks(this->keys_);
ks.push_back(kv.first);
auto tmp = visit(serializer(
this->width_, this->float_prec_, !multiline_table_printed, ks),
auto tmp = visit(serializer(this->width_, this->float_prec_,
!multiline_table_printed, this->no_comment_, ks),
kv.second);
if((!multiline_table_printed) &&
@@ -460,50 +633,132 @@ struct serializer
// still inline tables only.
tmp += '\n';
}
if(!kv.second.comments().empty() && !no_comment_)
{
for(const auto& c : kv.second.comments())
{
token += '#';
token += c;
token += '\n';
}
}
token += tmp;
}
return token;
}
bool is_array_of_tables(const value& v) const
bool is_array_of_tables(const value_type& v) const
{
if(!v.is(value_t::Array)) {return false;}
const auto& a = v.cast<value_t::Array>();
return !a.empty() && a.front().is(value_t::Table);
if(!v.is_array()) {return false;}
const auto& a = v.as_array();
return !a.empty() && a.front().is_table();
}
private:
bool can_be_inlined_;
bool no_comment_;
int float_prec_;
std::size_t width_;
std::vector<toml::key> keys_;
};
inline std::string
format(const value& v, std::size_t w = 80,
int fprec = std::numeric_limits<toml::floating>::max_digits10)
template<typename C,
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,
bool no_comment = false, bool force_inline = false)
{
return visit(serializer(w, fprec, true), v);
// if value is a table, it is considered to be a root object.
// the root object can't be an inline table.
if(v.is_table())
{
std::ostringstream oss;
if(!v.comments().empty())
{
oss << v.comments();
oss << '\n'; // to split the file comment from the first element
}
oss << visit(serializer<C, M, V>(w, fprec, no_comment, false), v);
return oss.str();
}
return visit(serializer<C, M, V>(w, fprec, force_inline), v);
}
inline std::string
format(const table& t, std::size_t w = 80,
int fprec = std::numeric_limits<toml::floating>::max_digits10)
namespace detail
{
return serializer(w, fprec, true)(t);
template<typename charT, typename traits>
int comment_index(std::basic_ostream<charT, traits>&)
{
static const int index = std::ios_base::xalloc();
return index;
}
} // detail
template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
nocomment(std::basic_ostream<charT, traits>& os)
{
// by default, it is zero. and by defalut, it shows comments.
os.iword(detail::comment_index(os)) = 1;
return os;
}
template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const value& v)
showcomment(std::basic_ostream<charT, traits>& os)
{
// by default, it is zero. and by defalut, it shows comments.
os.iword(detail::comment_index(os)) = 0;
return os;
}
template<typename charT, typename traits, typename C,
template<typename ...> class M, template<typename ...> class V>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const basic_value<C, M, V>& v)
{
// get status of std::setw().
const std::size_t w = os.width();
const int fprec = os.precision();
const auto w = static_cast<std::size_t>(os.width());
const int fprec = static_cast<int>(os.precision());
os.width(0);
// by defualt, iword is initialized byl 0. And by default, toml11 outputs
// comments. So `0` means showcomment. 1 means nocommnet.
const bool no_comment = (1 == os.iword(detail::comment_index(os)));
if(!no_comment && v.is_table() && !v.comments().empty())
{
os << v.comments();
os << '\n'; // to split the file comment from the first element
}
// 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, no_comment), v);
// if v is a non-table value, and has only one comment, then
// put a comment just after a value. in the following way.
//
// ```toml
// key = "value" # comment.
// ```
//
// Since the top-level toml object is a table, one who want to put a
// non-table toml value must use this in a following way.
//
// ```cpp
// toml::value v;
// std::cout << "user-defined-key = " << v << std::endl;
// ```
//
// In this case, it is impossible to put comments before key-value pair.
// The only way to preserve comments is to put all of them after a value.
if(!no_comment && !v.is_table() && !v.comments().empty())
{
os << " #";
for(const auto& c : v.comments()) {os << c;}
}
return os;
}

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

@@ -1,9 +1,14 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_STRING_H
#define TOML11_STRING_H
#ifndef TOML11_STRING_HPP
#define TOML11_STRING_HPP
#include <string>
#include <cstdint>
#if __cplusplus >= 201703L
#if __has_include(<string_view>)
#include <string_view>
#endif
#endif
namespace toml
{
@@ -40,6 +45,17 @@ struct string
operator std::string const& () const& noexcept {return str;}
operator std::string&& () && noexcept {return std::move(str);}
#if __cplusplus >= 201703L
explicit string(std::string_view s): kind(string_t::basic), str(s){}
string(std::string_view s, string_t k): kind(k), str(s){}
string& operator=(std::string_view s)
{kind = string_t::basic; str = s; return *this;}
explicit operator std::string_view() const noexcept
{return std::string_view(str);}
#endif
string_t kind;
std::string str;
};
@@ -123,9 +139,74 @@ operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.s
template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const string& str)
operator<<(std::basic_ostream<charT, traits>& os, const string& s)
{
os << str.str;
if(s.kind == string_t::basic)
{
if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
{
// it contains newline. make it multiline string.
os << "\"\"\"\n";
for(auto i=s.str.cbegin(), e=s.str.cend(); i!=e; ++i)
{
switch(*i)
{
case '\\': {os << "\\\\"; break;}
case '\"': {os << "\\\""; break;}
case '\b': {os << "\\b"; break;}
case '\t': {os << "\\t"; break;}
case '\f': {os << "\\f"; break;}
case '\n': {os << '\n'; break;}
case '\r':
{
// since it is a multiline string,
// CRLF is not needed to be escaped.
if(std::next(i) != e && *std::next(i) == '\n')
{
os << "\r\n";
++i;
}
else
{
os << "\\r";
}
break;
}
default: {os << *i; break;}
}
}
os << "\\\n\"\"\"";
return os;
}
// no newline. make it inline.
os << "\"";
for(const auto c : s.str)
{
switch(c)
{
case '\\': {os << "\\\\"; break;}
case '\"': {os << "\\\""; break;}
case '\b': {os << "\\b"; break;}
case '\t': {os << "\\t"; break;}
case '\f': {os << "\\f"; break;}
case '\n': {os << "\\n"; break;}
case '\r': {os << "\\r"; break;}
default : {os << c; break;}
}
}
os << "\"";
return os;
}
// the string `s` is literal-string.
if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
{
// contains newline or single quote. make it multiline.
os << "'''\n" << s.str << "'''";
return os;
}
// normal literal string
os << '\'' << s.str << '\'';
return os;
}

View File

@@ -1,49 +0,0 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_TO_TOML
#define TOML11_TO_TOML
#include "value.hpp"
namespace toml
{
template<typename T>
TOML11_MARK_AS_DEPRECATED
inline value to_toml(T&& x)
{
return value(std::forward<T>(x));
}
template<typename T>
TOML11_MARK_AS_DEPRECATED
inline value to_toml(T&& x, string_t kind)
{
return value(std::forward<T>(x), kind);
}
TOML11_MARK_AS_DEPRECATED
inline value to_toml(local_date d, local_time t)
{
return value(local_datetime(d, t));
}
TOML11_MARK_AS_DEPRECATED
inline value to_toml(local_date d, local_time t, time_offset ofs)
{
return value(offset_datetime(d, t, ofs));
}
template<typename ... Ts>
TOML11_MARK_AS_DEPRECATED
inline value to_toml(Ts&& ... xs)
{
return value(toml::array{toml::value(std::forward<Ts>(xs)) ... });
}
TOML11_MARK_AS_DEPRECATED
inline value to_toml(std::initializer_list<std::pair<std::string, toml::value>> xs)
{
return value(toml::table(xs.begin(), xs.end()));
}
} // toml
#endif // TOML11_TO_TOML

View File

@@ -1,20 +1,25 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_TRAITS
#define TOML11_TRAITS
#ifndef TOML11_TRAITS_HPP
#define TOML11_TRAITS_HPP
#include <type_traits>
#include <utility>
#include <chrono>
#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
{
template<typename C, template<typename ...> class T, template<typename ...> class A>
class basic_value;
namespace detail
{
template<typename T>
using unwrap_t = typename std::decay<T>::type;
// ---------------------------------------------------------------------------
// check whether type T is a kind of container/map class
@@ -45,6 +50,32 @@ struct has_resize_method_impl
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
{
template<typename T, typename C,
template<typename ...> class Tb, template<typename ...> class A>
static std::true_type check(
decltype(std::declval<T>().from_toml(
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(...);
};
struct has_into_toml_method_impl
{
template<typename T>
static std::true_type check(decltype(std::declval<T>().into_toml())*);
template<typename T>
static std::false_type check(...);
};
/// Intel C++ compiler can not use decltype in parent class declaration, here
/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076
#ifdef __INTEL_COMPILER
@@ -61,6 +92,17 @@ template<typename T>
struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
template<typename T>
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
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
: decltype(has_from_toml_method_impl::check<T, C, Tb, A>(nullptr)){};
template<typename T>
struct has_into_toml_method
: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
#ifdef __INTEL_COMPILER
#undef decltype(...)
@@ -87,7 +129,7 @@ template<typename T>
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 T1, typename T2>
@@ -101,6 +143,42 @@ template<typename T> struct is_chrono_duration: std::false_type{};
template<typename Rep, typename Period>
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
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
@@ -127,6 +205,11 @@ struct index_sequence_maker<0>
template<std::size_t N>
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
@@ -142,6 +225,21 @@ using return_type_of_t = typename std::result_of<F(Args...)>::type;
#endif
// ---------------------------------------------------------------------------
// is_string_literal
//
// to use this, pass `typename remove_reference<T>::type` to T.
template<typename T>
struct is_string_literal:
disjunction<
std::is_same<const char*, T>,
conjunction<
std::is_array<T>,
std::is_same<const char, typename std::remove_extent<T>::type>
>
>{};
}// detail
}//toml
#endif // TOML_TRAITS

View File

@@ -1,54 +1,55 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_TYPES_H
#define TOML11_TYPES_H
#ifndef TOML11_TYPES_HPP
#define TOML11_TYPES_HPP
#include "datetime.hpp"
#include "string.hpp"
#include "traits.hpp"
#include "comments.hpp"
#include <vector>
#include <unordered_map>
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 Boolean = bool;
using Integer = std::int64_t;
using Float = double;
using String = ::toml::string;
using Datetime = offset_datetime;
using OffsetDatetime = offset_datetime;
using LocalDatetime = local_datetime;
using LocalDate = local_date;
using LocalTime = local_time;
using Array = std::vector<value>;
using Table = std::unordered_map<key, value>;
using boolean = bool;
using integer = std::int64_t;
using floating = double; // "float" is a keyward, cannot use it here.
// the following stuffs are structs defined here, so aliases are not needed.
// - string
// - offset_datetime
// - offset_datetime
// - local_datetime
// - local_date
// - local_time
// alias for snake_case, consistency with STL/Boost, toml::key, toml::value
using boolean = Boolean;
using integer = Integer;
using floating = Float; // XXX `float` is keyword. we can't use it here
using array = Array;
using table = Table;
// default toml::value and default array/table. these are defined after defining
// basic_value itself.
// using value = basic_value<discard_comments, std::unordered_map, std::vector>;
// using array = typename value::array_type;
// using table = typename value::table_type;
enum class value_t : std::uint8_t
{
Empty = 0,
Boolean = 1,
Integer = 2,
Float = 3,
String = 4,
OffsetDatetime = 5,
LocalDatetime = 6,
LocalDate = 7,
LocalTime = 8,
Array = 9,
Table = 10,
Unknown = 255,
empty = 0,
boolean = 1,
integer = 2,
floating = 3,
string = 4,
offset_datetime = 5,
local_datetime = 6,
local_date = 7,
local_time = 8,
array = 9,
table = 10,
};
template<typename charT, typename traits>
@@ -57,27 +58,27 @@ operator<<(std::basic_ostream<charT, traits>& os, value_t t)
{
switch(t)
{
case toml::value_t::Boolean : os << "boolean"; return os;
case toml::value_t::Integer : os << "integer"; return os;
case toml::value_t::Float : os << "float"; return os;
case toml::value_t::String : os << "string"; return os;
case toml::value_t::OffsetDatetime: os << "offset_datetime"; return os;
case toml::value_t::LocalDatetime : os << "local_datetime"; return os;
case toml::value_t::LocalDate : os << "local_date"; return os;
case toml::value_t::LocalTime : os << "local_time"; return os;
case toml::value_t::Array : os << "array"; return os;
case toml::value_t::Table : os << "table"; return os;
case toml::value_t::Empty : os << "empty"; return os;
case toml::value_t::Unknown : os << "unknown"; return os;
default : os << "nothing"; return os;
case value_t::boolean : os << "boolean"; return os;
case value_t::integer : os << "integer"; return os;
case value_t::floating : os << "floating"; return os;
case value_t::string : os << "string"; return os;
case value_t::offset_datetime : os << "offset_datetime"; return os;
case value_t::local_datetime : os << "local_datetime"; return os;
case value_t::local_date : os << "local_date"; return os;
case value_t::local_time : os << "local_time"; return os;
case value_t::array : os << "array"; return os;
case value_t::table : os << "table"; return os;
case value_t::empty : os << "empty"; return os;
default : os << "unknown"; 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>>
inline std::basic_string<charT, traits, alloc> stringize(value_t t)
{
std::ostringstream oss;
std::basic_ostringstream<charT, traits, alloc> oss;
oss << t;
return oss.str();
}
@@ -85,101 +86,63 @@ inline std::basic_string<charT, traits, alloc> stringize(value_t t)
namespace detail
{
template<typename T>
constexpr inline value_t check_type()
{
using type = typename std::remove_cv<
typename std::remove_reference<T>::type
>::type;
return std::is_same<type, toml::boolean>::value ? value_t::Boolean :
std::is_integral<type>::value ? value_t::Integer :
std::is_floating_point<type>::value ? value_t::Float :
std::is_same<type, std::string>::value ? value_t::String :
std::is_same<type, toml::string>::value ? value_t::String :
std::is_same<type, toml::local_date>::value ? value_t::LocalDate :
std::is_same<type, toml::local_time>::value ? value_t::LocalTime :
is_chrono_duration<type>::value ? value_t::LocalTime :
std::is_same<type, toml::local_datetime>::value ? value_t::LocalDatetime :
std::is_same<type, toml::offset_datetime>::value ? value_t::OffsetDatetime :
std::is_same<type, std::chrono::system_clock::time_point>::value ? value_t::OffsetDatetime :
std::is_convertible<type, toml::array>::value ? value_t::Array :
std::is_convertible<type, toml::table>::value ? value_t::Table :
value_t::Unknown;
}
// helper to define a type that represents a value_t value.
template<value_t V>
using value_t_constant = std::integral_constant<value_t, V>;
constexpr inline bool is_valid(value_t vt)
{
return vt != value_t::Unknown;
}
// 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.
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;
template<> struct toml_default_type<value_t::Boolean > {typedef boolean type;};
template<> struct toml_default_type<value_t::Integer > {typedef integer type;};
template<> struct toml_default_type<value_t::Float > {typedef floating type;};
template<> struct toml_default_type<value_t::String > {typedef string type;};
template<> struct toml_default_type<value_t::OffsetDatetime>{typedef offset_datetime type;};
template<> struct toml_default_type<value_t::LocalDatetime> {typedef local_datetime type;};
template<> struct toml_default_type<value_t::LocalDate> {typedef local_date type;};
template<> struct toml_default_type<value_t::LocalTime> {typedef local_time type;};
template<> struct toml_default_type<value_t::Array > {typedef array type;};
template<> struct toml_default_type<value_t::Table > {typedef table type;};
template<> struct toml_default_type<value_t::Empty > {typedef void type;};
template<> struct toml_default_type<value_t::Unknown > {typedef void type;};
// meta-function that converts from an exact toml type to the enum that corresponds to.
template<typename T, typename Value>
struct type_to_enum : std::conditional<
std::is_same<T, typename Value::array_type>::value, // if T == array_type,
value_t_constant<value_t::array>, // then value_t::array
typename std::conditional< // else...
std::is_same<T, typename Value::table_type>::value, // if T == table_type
value_t_constant<value_t::table>, // then value_t::table
value_t_constant<value_t::empty> // else value_t::empty
>::type
>::type {};
template<typename Value> struct type_to_enum<boolean , Value>: value_t_constant<value_t::boolean > {};
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 ;};
template<> struct toml_value_t<Boolean >{static constexpr value_t value = value_t::Boolean ;};
template<> struct toml_value_t<Integer >{static constexpr value_t value = value_t::Integer ;};
template<> struct toml_value_t<Float >{static constexpr value_t value = value_t::Float ;};
template<> struct toml_value_t<String >{static constexpr value_t value = value_t::String ;};
template<> struct toml_value_t<OffsetDatetime>{static constexpr value_t value = value_t::OffsetDatetime;};
template<> struct toml_value_t<LocalDatetime >{static constexpr value_t value = value_t::LocalDatetime ;};
template<> struct toml_value_t<LocalDate >{static constexpr value_t value = value_t::LocalDate ;};
template<> struct toml_value_t<LocalTime >{static constexpr value_t value = value_t::LocalTime ;};
template<> struct toml_value_t<Array >{static constexpr value_t value = value_t::Array ;};
template<> struct toml_value_t<Table >{static constexpr value_t value = value_t::Table ;};
template<typename T>
// meta-function that checks the type T is the same as one of the toml::* types.
template<typename T, typename Value>
struct is_exact_toml_type : disjunction<
std::is_same<T, Boolean >,
std::is_same<T, Integer >,
std::is_same<T, Float >,
std::is_same<T, String >,
std::is_same<T, boolean >,
std::is_same<T, integer >,
std::is_same<T, floating >,
std::is_same<T, string >,
std::is_same<T, offset_datetime>,
std::is_same<T, local_datetime>,
std::is_same<T, local_date>,
std::is_same<T, local_time>,
std::is_same<T, Array >,
std::is_same<T, Table >
std::is_same<T, local_datetime >,
std::is_same<T, local_date >,
std::is_same<T, local_time >,
std::is_same<T, typename Value::array_type>,
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> struct is_exact_toml_type<T const&> : is_exact_toml_type<T>{};
template<typename T> struct is_exact_toml_type<T volatile&> : is_exact_toml_type<T>{};
template<typename T> struct is_exact_toml_type<T const volatile&>: is_exact_toml_type<T>{};
template<typename T>
struct is_map : conjunction<
has_iterator<T>,
has_value_type<T>,
has_key_type<T>,
has_mapped_type<T>
>{};
template<typename T> struct is_map<T&> : is_map<T>{};
template<typename T> struct is_map<T const&> : is_map<T>{};
template<typename T> struct is_map<T volatile&> : is_map<T>{};
template<typename T> struct is_map<T const volatile&> : is_map<T>{};
template<typename T>
struct is_container : conjunction<
negation<is_map<T>>,
negation<std::is_same<T, std::string>>,
has_iterator<T>,
has_value_type<T>
>{};
template<typename T> struct is_container<T&> : is_container<T>{};
template<typename T> struct is_container<T const&> : is_container<T>{};
template<typename T> struct is_container<T volatile&> : is_container<T>{};
template<typename T> struct is_container<T const volatile&> : is_container<T>{};
template<typename T, typename V> struct is_exact_toml_type<T&, V> : is_exact_toml_type<T, V>{};
template<typename T, typename V> struct is_exact_toml_type<T const&, V> : is_exact_toml_type<T, V>{};
template<typename T, typename V> struct is_exact_toml_type<T volatile&, V> : is_exact_toml_type<T, V>{};
template<typename T, typename V> struct is_exact_toml_type<T const volatile&, V>: is_exact_toml_type<T, V>{};
} // detail
} // toml

View File

@@ -1,18 +1,18 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_UTILITY
#define TOML11_UTILITY
#ifndef TOML11_UTILITY_HPP
#define TOML11_UTILITY_HPP
#include "traits.hpp"
#include <utility>
#include <memory>
#include <sstream>
#if __cplusplus >= 201402L
# define TOML11_MARK_AS_DEPRECATED [[deprecated]]
# define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]]
#elif defined(__GNUC__)
# define TOML11_MARK_AS_DEPRECATED __attribute__((deprecated))
# define TOML11_MARK_AS_DEPRECATED(msg) __attribute__((deprecated(msg)))
#elif defined(_MSC_VER)
# define TOML11_MARK_AS_DEPRECATED __declspec(deprecated)
# define TOML11_MARK_AS_DEPRECATED(msg) __declspec(deprecated(msg))
#else
# define TOML11_MARK_AS_DEPRECATED
#endif
@@ -79,7 +79,7 @@ std::string concat_to_string(Ts&& ... args)
template<typename T, typename U>
T from_string(const std::string& str, U&& opt)
{
T v(std::forward<U>(opt));
T v(static_cast<T>(std::forward<U>(opt)));
std::istringstream iss(str);
iss >> v;
return v;

File diff suppressed because it is too large Load Diff