mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87be890e07 | ||
|
|
d72dc706d0 | ||
|
|
4cbbcd8f62 | ||
|
|
a2631ecacb | ||
|
|
4bcc5e8375 | ||
|
|
90f84000ba | ||
|
|
20a13754a7 | ||
|
|
aa7b9a3965 | ||
|
|
84ac1d10f3 | ||
|
|
0d623856a7 | ||
|
|
ec0d4e4e8c | ||
|
|
80ea736b3f | ||
|
|
ebaa5dfb51 | ||
|
|
f3bdf083fe | ||
|
|
1ce54a9cf9 | ||
|
|
6383a93ce7 | ||
|
|
01aa2ef5b2 | ||
|
|
819351f5a4 | ||
|
|
2967cebfb3 | ||
|
|
32e9a2c1c7 | ||
|
|
8e0a40a1aa | ||
|
|
e460826084 | ||
|
|
aa3445f38c | ||
|
|
408b7bf35e | ||
|
|
6185dfee14 | ||
|
|
37aa2739a5 | ||
|
|
d061c33a16 | ||
|
|
0c7d2d07d4 | ||
|
|
62cf4373bd | ||
|
|
a74ad23514 | ||
|
|
2d9b4992ec | ||
|
|
82e8c1e68b | ||
|
|
46be054ce9 | ||
|
|
789d784769 | ||
|
|
81deb8efde | ||
|
|
072dccd05d | ||
|
|
637c99d637 | ||
|
|
0f48852730 | ||
|
|
0499b2907d | ||
|
|
61e69c9251 | ||
|
|
4a560ea1e5 | ||
|
|
c5b6ee6f81 | ||
|
|
1a7bf63622 | ||
|
|
8847cdc0a9 | ||
|
|
c82e76a111 | ||
|
|
4db486d76d | ||
|
|
91966a6917 | ||
|
|
b3917aaadf | ||
|
|
ba307003c4 | ||
|
|
21fd1271d9 | ||
|
|
f9ab7d6f56 | ||
|
|
0a3a41a708 | ||
|
|
6c2a536fa5 |
57
.travis.yml
57
.travis.yml
@@ -5,7 +5,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-5"
|
env: COMPILER="g++-5" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -16,7 +16,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-6"
|
env: COMPILER="g++-6" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -27,7 +27,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-7"
|
env: COMPILER="g++-7" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -38,7 +38,18 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-8"
|
env: COMPILER="g++-8" CXX_STANDARD=11
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
env: COMPILER="g++-8" CXX_STANDARD=17
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -49,7 +60,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-3.7"
|
env: COMPILER="clang++-3.7" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -61,7 +72,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-4.0"
|
env: COMPILER="clang++-4.0" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -73,7 +84,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-5.0"
|
env: COMPILER="clang++-5.0" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -85,7 +96,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-6.0"
|
env: COMPILER="clang++-6.0" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -97,7 +108,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-7"
|
env: COMPILER="clang++-7" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -109,7 +120,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-8"
|
env: COMPILER="clang++-8" CXX_STANDARD=11
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -118,14 +129,38 @@ matrix:
|
|||||||
packages:
|
packages:
|
||||||
- clang-8
|
- clang-8
|
||||||
- libboost-all-dev
|
- libboost-all-dev
|
||||||
|
- os: linux
|
||||||
|
language: cpp
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER="clang++-8" CXX_STANDARD=17
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-trusty-8
|
||||||
|
packages:
|
||||||
|
- clang-8
|
||||||
|
- g++-8
|
||||||
|
- libboost-all-dev
|
||||||
- os: osx
|
- os: osx
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
|
env: CXX_STANDARD=11
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
- |
|
||||||
|
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||||
|
mkdir -p cmake
|
||||||
|
travis_retry wget "https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.tar.gz"
|
||||||
|
tar xf cmake-3.11.2-Linux-x86_64.tar.gz -C cmake --strip-components=1
|
||||||
|
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
|
||||||
|
else
|
||||||
|
brew upgrade cmake
|
||||||
|
fi
|
||||||
|
- cmake --version
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- git clone https://github.com/toml-lang/toml.git
|
- git clone https://github.com/toml-lang/toml.git
|
||||||
- cmake -DCMAKE_CXX_COMPILER=$COMPILER ..
|
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD ..
|
||||||
- make
|
- make
|
||||||
- ctest --output-on-failure
|
- ctest --output-on-failure
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ project(toml11)
|
|||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
if(NOT DEFINED CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
endif()
|
||||||
set(CXX_STANDARD_REQUIRED ON)
|
set(CXX_STANDARD_REQUIRED ON)
|
||||||
else()
|
else()
|
||||||
# Manually check for C++11 compiler flag.
|
# Manually check for C++11 compiler flag.
|
||||||
|
|||||||
113
README.md
113
README.md
@@ -63,6 +63,7 @@ int main()
|
|||||||
- [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types)
|
- [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types)
|
||||||
- [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints)
|
- [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints)
|
||||||
- [Formatting user-defined error messages](#formatting-user-defined-error-messages)
|
- [Formatting user-defined error messages](#formatting-user-defined-error-messages)
|
||||||
|
- [Getting comments related to a value](#getting-comments)
|
||||||
- [Serializing TOML data](#serializing-toml-data)
|
- [Serializing TOML data](#serializing-toml-data)
|
||||||
- [Underlying types](#underlying-types)
|
- [Underlying types](#underlying-types)
|
||||||
- [Running Tests](#running-tests)
|
- [Running Tests](#running-tests)
|
||||||
@@ -187,6 +188,12 @@ See also [underlying types](#underlying-types).
|
|||||||
|
|
||||||
NOTE: To enable to get a reference, conversions between Float and Integer are not supported.
|
NOTE: To enable to get a reference, conversions between Float and Integer are not supported.
|
||||||
|
|
||||||
|
After C++17, you can use `std::string_view` to get a string from a `toml::value`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto sv = toml::get<std::string_view>(tab.at("key"));
|
||||||
|
```
|
||||||
|
|
||||||
### In the case of type error
|
### In the case of type error
|
||||||
|
|
||||||
If you pass an invalid type to `toml::get`, `toml::type_error` will be thrown.
|
If you pass an invalid type to `toml::get`, `toml::type_error` will be thrown.
|
||||||
@@ -500,9 +507,9 @@ You can check what type of value does `toml::value` contains by `is_*` function.
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
toml::value v = /* ... */;
|
toml::value v = /* ... */;
|
||||||
if(v.is_integer() && toml::get<int>(v) == 42)
|
if(v.is_integer())
|
||||||
{
|
{
|
||||||
std::cout << "value is 42" << std::endl;
|
std::cout << "value is an integer" << std::endl;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -546,6 +553,36 @@ toml::value v = /* ... */;
|
|||||||
if(v.is(toml::value_t::Boolean)) // ...
|
if(v.is(toml::value_t::Boolean)) // ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Casting value
|
||||||
|
|
||||||
|
So far, `toml::get` is introduced, but if you don't need any type conversion,
|
||||||
|
`as_*` is simpler to use.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
toml::value v = /* ... */;
|
||||||
|
if(v.is_integer() && v.as_integer() == 42)
|
||||||
|
{
|
||||||
|
std::cout << "value is 42" << std::endl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The complete list of the functions is below.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const toml::value v(/*...*/);
|
||||||
|
v.as_boolean();
|
||||||
|
v.as_integer();
|
||||||
|
v.as_float();
|
||||||
|
v.as_string();
|
||||||
|
v.as_offset_datetime();
|
||||||
|
v.as_local_datetime();
|
||||||
|
v.as_local_date();
|
||||||
|
v.as_local_time();
|
||||||
|
v.as_array();
|
||||||
|
v.as_table();
|
||||||
|
v.as_uninitialized();
|
||||||
|
```
|
||||||
|
|
||||||
## Visiting a toml::value
|
## Visiting a toml::value
|
||||||
|
|
||||||
toml11 provides `toml::visit` to apply a function to `toml::value` in the
|
toml11 provides `toml::visit` to apply a function to `toml::value` in the
|
||||||
@@ -603,6 +640,27 @@ toml::value operator""_toml(const char* str, std::size_t len);
|
|||||||
Access to the operator can be gained with `using namespace toml::literals;`,
|
Access to the operator can be gained with `using namespace toml::literals;`,
|
||||||
`using namespace toml::toml_literals`, and `using namespace toml::literals::toml_literals`.
|
`using namespace toml::toml_literals`, and `using namespace toml::literals::toml_literals`.
|
||||||
|
|
||||||
|
Note that a key that is composed only of digits is allowed in TOML.
|
||||||
|
And, unlike the file parser, toml-literal allows a bare value without a key.
|
||||||
|
Thus it is difficult to distinguish arrays having integers and definitions of
|
||||||
|
tables that are named as digits.
|
||||||
|
Currently, literal `[1]` becomes a table named "1".
|
||||||
|
To ensure a literal to be considered as an array with one element, you need to
|
||||||
|
add a comma after the first element (like `[1,]`).
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
"[1,2,3]"_toml; // This is an array
|
||||||
|
"[table]"_toml; // This is 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 literal is ambiguous.
|
||||||
|
// Currently, it becomes a table that has array of table "1".
|
||||||
|
"1 = [{}]"_toml; // This is a table that has an array of table named 1.
|
||||||
|
"[[1,]]"_toml; // This is an array of arrays.
|
||||||
|
"[[1],]"_toml; // ditto.
|
||||||
|
```
|
||||||
|
|
||||||
## Conversion between toml value and arbitrary types
|
## Conversion between toml value and arbitrary types
|
||||||
|
|
||||||
You can also use `toml::get` and other related functions with the types you defined
|
You can also use `toml::get` and other related functions with the types you defined
|
||||||
@@ -810,6 +868,53 @@ you will get an error message like this.
|
|||||||
| ~~ maximum number here
|
| ~~ maximum number here
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Getting comments
|
||||||
|
|
||||||
|
Since toml11 keeps a file data until all the values are destructed, you can
|
||||||
|
also extract a comment related to a value by calling `toml::value::comment()`.
|
||||||
|
|
||||||
|
If there is a comment just after a value (within the same line), you can get
|
||||||
|
the specific comment by `toml::value::comment_inline()`.
|
||||||
|
|
||||||
|
If there are comments just before a value (without any newline between them),
|
||||||
|
you can get the comments by `toml::value::comment_before()`.
|
||||||
|
|
||||||
|
`toml::value::comment()` returns the results of both functions after
|
||||||
|
concatenating them.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
a = 42 # comment for a.
|
||||||
|
|
||||||
|
# comment for b.
|
||||||
|
# this is also a comment for b.
|
||||||
|
b = "foo"
|
||||||
|
|
||||||
|
c = [ # comment for c.
|
||||||
|
3.14, # this is not a comment for c, but for 3.14.
|
||||||
|
] # this is also a comment for c.
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// "# comment for a."
|
||||||
|
const std::string com1 = toml::find(data, "a").comment();
|
||||||
|
|
||||||
|
// "# comment for b."
|
||||||
|
const std::string com2 = toml::find(data, "b").comment();
|
||||||
|
|
||||||
|
// "# comment for c.\n# this is also a comment for c."
|
||||||
|
const std::string com3 = toml::find(data, "c").comment();
|
||||||
|
|
||||||
|
// "# this is not a comment for c, but for 3.14."
|
||||||
|
const std::string com3 = toml::find<toml::array>(data, "c").front().comment();
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that once a data in a value is modified, the related file region
|
||||||
|
information would be deleted. Thus after modifying a data, you cannot find any
|
||||||
|
comments.
|
||||||
|
|
||||||
|
Also note that currently it does not support any way to set a comment to a value.
|
||||||
|
And currently, serializer does not take comments into account.
|
||||||
|
|
||||||
## Serializing TOML data
|
## Serializing TOML data
|
||||||
|
|
||||||
toml11 (after v2.1.0) enables you to serialize data into toml format.
|
toml11 (after v2.1.0) enables you to serialize data into toml format.
|
||||||
@@ -961,11 +1066,13 @@ I appreciate the help of the contributors who introduced the great feature to th
|
|||||||
- Quentin Khan (@xaxousis)
|
- Quentin Khan (@xaxousis)
|
||||||
- Found & Fixed a bug around ODR
|
- Found & Fixed a bug around ODR
|
||||||
- Improved error messages for invaild keys to show the location where the parser fails
|
- Improved error messages for invaild keys to show the location where the parser fails
|
||||||
|
- Petr Beneš (@wbenny)
|
||||||
|
- Fixed warnings on MSVC
|
||||||
|
|
||||||
## Licensing terms
|
## Licensing terms
|
||||||
|
|
||||||
This product is licensed under the terms of the [MIT License](LICENSE).
|
This product is licensed under the terms of the [MIT License](LICENSE).
|
||||||
|
|
||||||
- Copyright (c) 2017 Toru Niina
|
- Copyright (c) 2017-2019 Toru Niina
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ set(TEST_NAMES
|
|||||||
test_parse_key
|
test_parse_key
|
||||||
test_parse_table_key
|
test_parse_table_key
|
||||||
test_literals
|
test_literals
|
||||||
|
test_comments
|
||||||
test_get
|
test_get
|
||||||
test_get_related_func
|
test_get_related_func
|
||||||
test_from_toml
|
test_from_toml
|
||||||
|
|||||||
125
tests/test_comments.cpp
Normal file
125
tests/test_comments.cpp
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#define BOOST_TEST_MODULE "test_comments"
|
||||||
|
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#else
|
||||||
|
#define BOOST_TEST_NO_LIB
|
||||||
|
#include <boost/test/included/unit_test.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <toml.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_comment_before)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
# comment for a.
|
||||||
|
a = 42
|
||||||
|
# comment for b.
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), u8"# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), u8"# comment for b.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), "");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8"# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b.");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
# comment for a.
|
||||||
|
# another comment for a.
|
||||||
|
a = 42
|
||||||
|
# comment for b.
|
||||||
|
# also comment for b.
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), u8R"(# comment for a.
|
||||||
|
# another comment for a.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), u8R"(# comment for b.
|
||||||
|
# also comment for b.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8"");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a.
|
||||||
|
# another comment for a.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8R"(# comment for b.
|
||||||
|
# also comment for b.)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_comment_inline)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
a = 42 # comment for a.
|
||||||
|
b = "baz" # comment for b.
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8"# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"# comment for b.");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8"# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b.");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
a = [ # comment for a.
|
||||||
|
42,
|
||||||
|
] # this also.
|
||||||
|
b = [ # comment for b.
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
c = [
|
||||||
|
3.14, # this is not a comment for c, but 3.14.
|
||||||
|
] # comment for c.
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), "");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "c").comment_before(), "");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8R"(# comment for a.
|
||||||
|
# this also.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"# comment for b.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "c").comment_inline(), u8"# comment for c.");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a.
|
||||||
|
# this also.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "c").comment(), u8"# comment for c.");
|
||||||
|
|
||||||
|
const auto& c0 = toml::find<toml::array>(v, "c").at(0);
|
||||||
|
BOOST_CHECK_EQUAL(c0.comment(), u8"# this is not a comment for c, but 3.14.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_comment_both)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
{
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
# comment for a.
|
||||||
|
a = 42 # inline comment for a.
|
||||||
|
# comment for b.
|
||||||
|
b = "baz" # inline comment for b.
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), "# comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), "# comment for b.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), "# inline comment for a.");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), "# inline comment for b.");
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a.
|
||||||
|
# inline comment for a.)");
|
||||||
|
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8R"(# comment for b.
|
||||||
|
# inline comment for b.)");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_exact)
|
BOOST_AUTO_TEST_CASE(test_get_exact)
|
||||||
@@ -166,6 +169,17 @@ BOOST_AUTO_TEST_CASE(test_get_string_type)
|
|||||||
toml::get<std::string>(v) += "bar";
|
toml::get<std::string>(v) += "bar";
|
||||||
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v));
|
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
{
|
||||||
|
toml::value v("foo", toml::string_t::basic);
|
||||||
|
BOOST_CHECK_EQUAL("foo", toml::get<std::string_view>(v));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
toml::value v("foo", toml::string_t::literal);
|
||||||
|
BOOST_CHECK_EQUAL("foo", toml::get<std::string_view>(v));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_get_toml_array)
|
BOOST_AUTO_TEST_CASE(test_get_toml_array)
|
||||||
|
|||||||
@@ -33,6 +33,18 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
|
|||||||
b = "baz"
|
b = "baz"
|
||||||
)"_toml;
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(r, v);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value r{
|
||||||
|
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
|
||||||
|
};
|
||||||
|
const toml::value v = u8R"(
|
||||||
|
[table]
|
||||||
|
a = 42
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(r, v);
|
BOOST_CHECK_EQUAL(r, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,6 +103,19 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
|
|||||||
|
|
||||||
BOOST_CHECK(v1.is_array());
|
BOOST_CHECK(v1.is_array());
|
||||||
BOOST_CHECK((toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3}));
|
BOOST_CHECK((toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3}));
|
||||||
|
|
||||||
|
const toml::value v2 = u8R"([1,])"_toml;
|
||||||
|
|
||||||
|
BOOST_CHECK(v2.is_array());
|
||||||
|
BOOST_CHECK((toml::get<std::vector<int>>(v2) == std::vector<int>{1}));
|
||||||
|
|
||||||
|
const toml::value v3 = u8R"([[1,]])"_toml;
|
||||||
|
BOOST_CHECK(v3.is_array());
|
||||||
|
BOOST_CHECK((toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1}));
|
||||||
|
|
||||||
|
const toml::value v4 = u8R"([[1],])"_toml;
|
||||||
|
BOOST_CHECK(v4.is_array());
|
||||||
|
BOOST_CHECK((toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1}));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const toml::value v1 = u8R"({a = 42})"_toml;
|
const toml::value v1 = u8R"({a = 42})"_toml;
|
||||||
|
|||||||
@@ -9,6 +9,11 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_boolean)
|
BOOST_AUTO_TEST_CASE(test_value_boolean)
|
||||||
{
|
{
|
||||||
toml::value v1(true);
|
toml::value v1(true);
|
||||||
@@ -25,6 +30,8 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), false);
|
||||||
|
|
||||||
v1 = false;
|
v1 = false;
|
||||||
v2 = true;
|
v2 = true;
|
||||||
@@ -40,6 +47,8 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), false);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), true);
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
toml::value v4(v2);
|
toml::value v4(v2);
|
||||||
@@ -57,6 +66,8 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), false);
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_boolean(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v4.as_boolean(), true);
|
||||||
|
|
||||||
toml::value v5(std::move(v1));
|
toml::value v5(std::move(v1));
|
||||||
toml::value v6(std::move(v2));
|
toml::value v6(std::move(v2));
|
||||||
@@ -72,6 +83,8 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::Boolean>(), false);
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v5.as_boolean(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v6.as_boolean(), true);
|
||||||
|
|
||||||
v1 = 42;
|
v1 = 42;
|
||||||
v2 = 3.14;
|
v2 = 3.14;
|
||||||
@@ -87,6 +100,8 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 42);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 42);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Float>(), 3.14);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Float>(), 3.14);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_integer(), 42);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_float(), 3.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_integer)
|
BOOST_AUTO_TEST_CASE(test_value_integer)
|
||||||
@@ -105,6 +120,8 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), -42);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), -42);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), 42u);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), 42u);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_integer(), -42);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_integer(), 42u);
|
||||||
|
|
||||||
v1 = 54;
|
v1 = 54;
|
||||||
v2 = -54;
|
v2 = -54;
|
||||||
@@ -120,6 +137,8 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), -54);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), -54);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_integer(), -54);
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
toml::value v4(v2);
|
toml::value v4(v2);
|
||||||
@@ -137,6 +156,8 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Integer>(), -54);
|
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Integer>(), -54);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v4.as_integer(), -54);
|
||||||
|
|
||||||
toml::value v5(std::move(v1));
|
toml::value v5(std::move(v1));
|
||||||
toml::value v6(std::move(v2));
|
toml::value v6(std::move(v2));
|
||||||
@@ -152,6 +173,8 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Integer>(), -54);
|
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Integer>(), -54);
|
||||||
|
BOOST_CHECK_EQUAL(v5.as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v6.as_integer(), -54);
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
v2 = false;
|
v2 = false;
|
||||||
@@ -167,6 +190,8 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_float)
|
BOOST_AUTO_TEST_CASE(test_value_float)
|
||||||
@@ -183,8 +208,10 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v1.is_float());
|
BOOST_CHECK(v1.is_float());
|
||||||
BOOST_CHECK(v2.is_float());
|
BOOST_CHECK(v2.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Float>(), 3.14);
|
BOOST_CHECK_EQUAL (v1.cast<toml::value_t::Float>(), 3.14);
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v2.cast<toml::value_t::Float>(), 3.14, 1e-2);
|
BOOST_CHECK_CLOSE_FRACTION(v2.cast<toml::value_t::Float>(), 3.14, 1e-2);
|
||||||
|
BOOST_CHECK_EQUAL (v1.as_float(), 3.14);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v2.as_float(), 3.14, 1e-2);
|
||||||
|
|
||||||
v1 = 2.718f;
|
v1 = 2.718f;
|
||||||
v2 = 2.718;
|
v2 = 2.718;
|
||||||
@@ -199,7 +226,9 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v2.is_float());
|
BOOST_CHECK(v2.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v1.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
BOOST_CHECK_CLOSE_FRACTION(v1.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Float>(), 2.718);
|
BOOST_CHECK_EQUAL (v2.cast<toml::value_t::Float>(), 2.718);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v1.as_float(), 2.718, 1e-3);
|
||||||
|
BOOST_CHECK_EQUAL (v2.as_float(), 2.718);
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
toml::value v4(v2);
|
toml::value v4(v2);
|
||||||
@@ -216,7 +245,9 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v4.is_float());
|
BOOST_CHECK(v4.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v3.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
BOOST_CHECK_CLOSE_FRACTION(v3.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::Float>(), 2.718);
|
BOOST_CHECK_EQUAL (v4.cast<toml::value_t::Float>(), 2.718);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v3.as_float(), 2.718, 1e-3);
|
||||||
|
BOOST_CHECK_EQUAL (v4.as_float(), 2.718);
|
||||||
|
|
||||||
toml::value v5(std::move(v1));
|
toml::value v5(std::move(v1));
|
||||||
toml::value v6(std::move(v2));
|
toml::value v6(std::move(v2));
|
||||||
@@ -231,7 +262,9 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v6.is_float());
|
BOOST_CHECK(v6.is_float());
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v5.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
BOOST_CHECK_CLOSE_FRACTION(v5.cast<toml::value_t::Float>(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::Float>(), 2.718);
|
BOOST_CHECK_EQUAL (v6.cast<toml::value_t::Float>(), 2.718);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v5.as_float(), 2.718, 1e-3);
|
||||||
|
BOOST_CHECK_EQUAL (v6.as_float(), 2.718);
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
v2 = false;
|
v2 = false;
|
||||||
@@ -247,6 +280,8 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_string)
|
BOOST_AUTO_TEST_CASE(test_value_string)
|
||||||
@@ -271,6 +306,10 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "foo");
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "foo");
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "foo");
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "foo");
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "foo");
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_string(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_string(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_string(), "foo");
|
||||||
|
|
||||||
|
|
||||||
v1 = "bar";
|
v1 = "bar";
|
||||||
v2 = "bar";
|
v2 = "bar";
|
||||||
@@ -289,6 +328,10 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::String>(), "bar");
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::String>(), "bar");
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::String>(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_string(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_string(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_string(), "bar");
|
||||||
|
|
||||||
|
|
||||||
toml::value v4(v1);
|
toml::value v4(v1);
|
||||||
toml::value v5(v2);
|
toml::value v5(v2);
|
||||||
@@ -313,6 +356,10 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String>(), "bar");
|
||||||
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::String>(), "bar");
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::String>(), "bar");
|
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::String>(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v4.as_string(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v5.as_string(), "bar");
|
||||||
|
BOOST_CHECK_EQUAL(v6.as_string(), "bar");
|
||||||
|
|
||||||
|
|
||||||
v4.cast<toml::value_t::String>().str.at(2) = 'z';
|
v4.cast<toml::value_t::String>().str.at(2) = 'z';
|
||||||
v5.cast<toml::value_t::String>().str.at(2) = 'z';
|
v5.cast<toml::value_t::String>().str.at(2) = 'z';
|
||||||
@@ -331,9 +378,9 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK(v5.is_string());
|
BOOST_CHECK(v5.is_string());
|
||||||
BOOST_CHECK(v6.is_string());
|
BOOST_CHECK(v6.is_string());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v4.cast<toml::value_t::String>(), "baz");
|
BOOST_CHECK_EQUAL(v4.as_string(), "baz");
|
||||||
BOOST_CHECK_EQUAL(v5.cast<toml::value_t::String>(), "baz");
|
BOOST_CHECK_EQUAL(v5.as_string(), "baz");
|
||||||
BOOST_CHECK_EQUAL(v6.cast<toml::value_t::String>(), "baz");
|
BOOST_CHECK_EQUAL(v6.as_string(), "baz");
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
v2 = true;
|
v2 = true;
|
||||||
@@ -355,6 +402,28 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Boolean>(), true);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_boolean(), true);
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
std::string_view sv = "foo";
|
||||||
|
|
||||||
|
toml::value v7(sv);
|
||||||
|
toml::value v8(sv, toml::string_t::literal);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v7.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK_EQUAL(v8.type(), toml::value_t::String);
|
||||||
|
BOOST_CHECK(v7.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v8.is(toml::value_t::String));
|
||||||
|
BOOST_CHECK(v7.is<toml::String>());
|
||||||
|
BOOST_CHECK(v8.is<toml::String>());
|
||||||
|
BOOST_CHECK(v7.is_string());
|
||||||
|
BOOST_CHECK(v8.is_string());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(v7.cast<toml::value_t::String>(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v8.cast<toml::value_t::String>(), "foo");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_date)
|
BOOST_AUTO_TEST_CASE(test_value_local_date)
|
||||||
@@ -368,6 +437,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_date)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31));
|
toml::local_date(2018, toml::month_t::Jan, 31));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_date(),
|
||||||
|
toml::local_date(2018, toml::month_t::Jan, 31));
|
||||||
|
|
||||||
v1 = toml::local_date(2018, toml::month_t::Apr, 1);
|
v1 = toml::local_date(2018, toml::month_t::Apr, 1);
|
||||||
|
|
||||||
@@ -378,6 +449,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_date)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalDate>(),
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1));
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_date(),
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
|
||||||
toml::value v2(v1);
|
toml::value v2(v1);
|
||||||
BOOST_CHECK(v2 == v1);
|
BOOST_CHECK(v2 == v1);
|
||||||
@@ -389,6 +462,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_date)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalDate>(),
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalDate>(),
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1));
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_local_date(),
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1));
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
@@ -396,6 +471,7 @@ BOOST_AUTO_TEST_CASE(test_value_local_date)
|
|||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v1.is_boolean());
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_time)
|
BOOST_AUTO_TEST_CASE(test_value_local_time)
|
||||||
@@ -415,10 +491,18 @@ BOOST_AUTO_TEST_CASE(test_value_local_time)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
||||||
toml::local_time(12, 30, 45));
|
toml::local_time(12, 30, 45));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_time(),
|
||||||
|
toml::local_time(12, 30, 45));
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::LocalTime>(),
|
||||||
toml::local_time(12, 30, 45));
|
toml::local_time(12, 30, 45));
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_local_time(),
|
||||||
|
toml::local_time(12, 30, 45));
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
||||||
v2.cast<toml::value_t::LocalTime>());
|
v2.cast<toml::value_t::LocalTime>());
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_time(),
|
||||||
|
v2.as_local_time());
|
||||||
|
|
||||||
v1 = toml::local_time(1, 30, 0, /*ms*/ 100, /*us*/ 0);
|
v1 = toml::local_time(1, 30, 0, /*ms*/ 100, /*us*/ 0);
|
||||||
|
|
||||||
@@ -428,6 +512,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_time)
|
|||||||
BOOST_CHECK(v1.is_local_time());
|
BOOST_CHECK(v1.is_local_time());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::LocalTime>(),
|
||||||
toml::local_time(1, 30, 0, 100, 0));
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_time(),
|
||||||
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
BOOST_CHECK(v3 == v1);
|
BOOST_CHECK(v3 == v1);
|
||||||
@@ -439,6 +525,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_time)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::LocalTime>(),
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::LocalTime>(),
|
||||||
toml::local_time(1, 30, 0, 100, 0));
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_local_time(),
|
||||||
|
toml::local_time(1, 30, 0, 100, 0));
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
@@ -446,6 +534,7 @@ BOOST_AUTO_TEST_CASE(test_value_local_time)
|
|||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v1.is_boolean());
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
||||||
@@ -464,6 +553,10 @@ BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
|||||||
toml::local_datetime(
|
toml::local_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Jan, 31),
|
toml::local_date(2018, toml::month_t::Jan, 31),
|
||||||
toml::local_time(12, 30, 45)));
|
toml::local_time(12, 30, 45)));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_datetime(),
|
||||||
|
toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Jan, 31),
|
||||||
|
toml::local_time(12, 30, 45)));
|
||||||
|
|
||||||
v1 = toml::local_datetime(
|
v1 = toml::local_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
@@ -478,6 +571,10 @@ BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
|||||||
toml::local_datetime(
|
toml::local_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
toml::local_time(1, 15, 30)));
|
toml::local_time(1, 15, 30)));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_datetime(),
|
||||||
|
toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30)));
|
||||||
|
|
||||||
toml::value v2(v1);
|
toml::value v2(v1);
|
||||||
BOOST_CHECK(v2 == v1);
|
BOOST_CHECK(v2 == v1);
|
||||||
@@ -491,6 +588,11 @@ BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
|||||||
toml::local_datetime(
|
toml::local_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
toml::local_time(1, 15, 30)));
|
toml::local_time(1, 15, 30)));
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_local_datetime(),
|
||||||
|
toml::local_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30)));
|
||||||
|
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
@@ -498,6 +600,7 @@ BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
|||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v1.is_boolean());
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
||||||
@@ -519,6 +622,12 @@ BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
|||||||
toml::local_time(12, 30, 45),
|
toml::local_time(12, 30, 45),
|
||||||
toml::time_offset(9, 0)
|
toml::time_offset(9, 0)
|
||||||
));
|
));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_offset_datetime(),
|
||||||
|
toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Jan, 31),
|
||||||
|
toml::local_time(12, 30, 45),
|
||||||
|
toml::time_offset(9, 0)
|
||||||
|
));
|
||||||
|
|
||||||
v1 = toml::offset_datetime(
|
v1 = toml::offset_datetime(
|
||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
@@ -535,6 +644,12 @@ BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
|||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
toml::local_time(1, 15, 30),
|
toml::local_time(1, 15, 30),
|
||||||
toml::time_offset(9, 0)));
|
toml::time_offset(9, 0)));
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_offset_datetime(),
|
||||||
|
toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30),
|
||||||
|
toml::time_offset(9, 0)));
|
||||||
|
|
||||||
|
|
||||||
toml::value v2(v1);
|
toml::value v2(v1);
|
||||||
BOOST_CHECK(v2 == v1);
|
BOOST_CHECK(v2 == v1);
|
||||||
@@ -549,12 +664,19 @@ BOOST_AUTO_TEST_CASE(test_value_offset_datetime)
|
|||||||
toml::local_date(2018, toml::month_t::Apr, 1),
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
toml::local_time(1, 15, 30),
|
toml::local_time(1, 15, 30),
|
||||||
toml::time_offset(9, 0)));
|
toml::time_offset(9, 0)));
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_offset_datetime(),
|
||||||
|
toml::offset_datetime(
|
||||||
|
toml::local_date(2018, toml::month_t::Apr, 1),
|
||||||
|
toml::local_time(1, 15, 30),
|
||||||
|
toml::time_offset(9, 0)));
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
BOOST_CHECK(v1.is(toml::value_t::Boolean));
|
||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v1.is_boolean());
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_array)
|
BOOST_AUTO_TEST_CASE(test_value_array)
|
||||||
@@ -578,6 +700,12 @@ BOOST_AUTO_TEST_CASE(test_value_array)
|
|||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(0).as_integer(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(1).as_integer(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(2).as_integer(), 3);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(3).as_integer(), 4);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(4).as_integer(), 5);
|
||||||
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 6);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 7);
|
||||||
@@ -603,12 +731,24 @@ BOOST_AUTO_TEST_CASE(test_value_array)
|
|||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(0).as_integer(), 6);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(1).as_integer(), 7);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(2).as_integer(), 8);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(3).as_integer(), 9);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array().at(4).as_integer(), 0);
|
||||||
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 1);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(0).cast<toml::value_t::Integer>(), 1);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 2);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(1).cast<toml::value_t::Integer>(), 2);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 3);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 4);
|
||||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 5);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(0).as_integer(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(1).as_integer(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(2).as_integer(), 3);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(3).as_integer(), 4);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_array().at(4).as_integer(), 5);
|
||||||
|
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
BOOST_CHECK(v3 == v1);
|
BOOST_CHECK(v3 == v1);
|
||||||
@@ -623,6 +763,12 @@ BOOST_AUTO_TEST_CASE(test_value_array)
|
|||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(2).cast<toml::value_t::Integer>(), 8);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(3).cast<toml::value_t::Integer>(), 9);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Array>().at(4).cast<toml::value_t::Integer>(), 0);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(0).as_integer(), 6);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(1).as_integer(), 7);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(2).as_integer(), 8);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(3).as_integer(), 9);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_array().at(4).as_integer(), 0);
|
||||||
|
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
@@ -630,6 +776,7 @@ BOOST_AUTO_TEST_CASE(test_value_array)
|
|||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v1.is_boolean());
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_table)
|
BOOST_AUTO_TEST_CASE(test_value_table)
|
||||||
@@ -644,6 +791,10 @@ BOOST_AUTO_TEST_CASE(test_value_table)
|
|||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Integer>(), 42);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Integer>(), 42);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Float>(), 3.14);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Float>(), 3.14);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "qux");
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "qux");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("foo").as_integer(), 42);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_float(), 3.14);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "qux");
|
||||||
|
|
||||||
|
|
||||||
v1 = toml::table{{"foo", 2.71}, {"bar", 54}, {"baz", "quux"}};
|
v1 = toml::table{{"foo", 2.71}, {"bar", 54}, {"baz", "quux"}};
|
||||||
|
|
||||||
@@ -655,6 +806,10 @@ BOOST_AUTO_TEST_CASE(test_value_table)
|
|||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Float>(), 2.71);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Float>(), 2.71);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "quux");
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "quux");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("foo").as_float(), 2.71);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "quux");
|
||||||
|
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
BOOST_CHECK(v3 == v1);
|
BOOST_CHECK(v3 == v1);
|
||||||
@@ -667,6 +822,10 @@ BOOST_AUTO_TEST_CASE(test_value_table)
|
|||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Float>(), 2.71);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("foo").cast<toml::value_t::Float>(), 2.71);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Integer>(), 54);
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("bar").cast<toml::value_t::Integer>(), 54);
|
||||||
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "quux");
|
BOOST_CHECK_EQUAL(v3.cast<toml::value_t::Table>().at("baz").cast<toml::value_t::String>().str, "quux");
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_table().at("foo").as_float(), 2.71);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_table().at("bar").as_integer(), 54);
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_table().at("baz").as_string().str, "quux");
|
||||||
|
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
BOOST_CHECK_EQUAL(v1.type(), toml::value_t::Boolean);
|
||||||
@@ -674,6 +833,7 @@ BOOST_AUTO_TEST_CASE(test_value_table)
|
|||||||
BOOST_CHECK(v1.is<toml::Boolean>());
|
BOOST_CHECK(v1.is<toml::Boolean>());
|
||||||
BOOST_CHECK(v1.is_boolean());
|
BOOST_CHECK(v1.is_boolean());
|
||||||
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
BOOST_CHECK_EQUAL(v1.cast<toml::value_t::Boolean>(), true);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_empty)
|
BOOST_AUTO_TEST_CASE(test_value_empty)
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <array>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
// they scans characters and returns region if it matches to the condition.
|
// they scans characters and returns region if it matches to the condition.
|
||||||
@@ -38,10 +41,12 @@ inline std::string show_char(const char c)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::array<char, 5> buf;
|
||||||
oss << "0x" << std::hex << std::setfill('0') << std::setw(2)
|
buf.fill('\0');
|
||||||
<< static_cast<int>(c);
|
const auto r = std::snprintf(
|
||||||
return oss.str();
|
buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
|
||||||
|
assert(r == buf.size() - 1);
|
||||||
|
return std::string(buf.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +56,8 @@ struct character
|
|||||||
static constexpr char target = C;
|
static constexpr char target = C;
|
||||||
|
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -62,8 +68,12 @@ struct character
|
|||||||
const char c = *(loc.iter());
|
const char c = *(loc.iter());
|
||||||
if(c != target)
|
if(c != target)
|
||||||
{
|
{
|
||||||
return err(concat_to_string("expected '", show_char(target),
|
if(msg)
|
||||||
"' but got '", show_char(c), "'."));
|
{
|
||||||
|
return err(concat_to_string("expected '", show_char(target),
|
||||||
|
"' but got '", show_char(c), "'."));
|
||||||
|
}
|
||||||
|
return err("");
|
||||||
}
|
}
|
||||||
loc.advance(); // update location
|
loc.advance(); // update location
|
||||||
|
|
||||||
@@ -86,7 +96,8 @@ struct in_range
|
|||||||
static constexpr char lower = Low;
|
static constexpr char lower = Low;
|
||||||
|
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -97,9 +108,13 @@ struct in_range
|
|||||||
const char c = *(loc.iter());
|
const char c = *(loc.iter());
|
||||||
if(c < lower || upper < c)
|
if(c < lower || upper < c)
|
||||||
{
|
{
|
||||||
return err(concat_to_string("expected character in range "
|
if(msg)
|
||||||
"[", show_char(lower), ", ", show_char(upper), "] but got ",
|
{
|
||||||
"'", show_char(c), "'."));
|
return err(concat_to_string("expected character in range "
|
||||||
|
"[", show_char(lower), ", ", show_char(upper), "] but got ",
|
||||||
|
"'", show_char(c), "'."));
|
||||||
|
}
|
||||||
|
return err("");
|
||||||
}
|
}
|
||||||
|
|
||||||
loc.advance();
|
loc.advance();
|
||||||
@@ -120,7 +135,8 @@ template<typename Combinator>
|
|||||||
struct exclude
|
struct exclude
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -128,13 +144,16 @@ struct exclude
|
|||||||
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
||||||
auto first = loc.iter();
|
auto first = loc.iter();
|
||||||
|
|
||||||
auto rslt = Combinator::invoke(loc);
|
auto rslt = Combinator::invoke(loc, msg);
|
||||||
if(rslt.is_ok())
|
if(rslt.is_ok())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(concat_to_string(
|
if(msg)
|
||||||
"invalid pattern (", Combinator::pattern(), ") appeared ",
|
{
|
||||||
rslt.unwrap().str()));
|
return err(concat_to_string("invalid pattern (",
|
||||||
|
Combinator::pattern(), ") appeared ", rslt.unwrap().str()));
|
||||||
|
}
|
||||||
|
return err("");
|
||||||
}
|
}
|
||||||
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region<Cont>(loc, first, loc.iter()));
|
||||||
@@ -151,12 +170,13 @@ template<typename Combinator>
|
|||||||
struct maybe
|
struct maybe
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
const auto rslt = Combinator::invoke(loc);
|
const auto rslt = Combinator::invoke(loc, msg);
|
||||||
if(rslt.is_ok())
|
if(rslt.is_ok())
|
||||||
{
|
{
|
||||||
return rslt;
|
return rslt;
|
||||||
@@ -177,34 +197,36 @@ template<typename Head, typename ... Tail>
|
|||||||
struct sequence<Head, Tail...>
|
struct sequence<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return err(rslt.unwrap_err());
|
||||||
}
|
}
|
||||||
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
|
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from the above function only, recursively.
|
// called from the above function only, recursively.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Cont, typename Iterator>
|
||||||
static result<region<Cont>, std::string>
|
static result<region<Cont>, std::string>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first,
|
||||||
|
const bool msg = false)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return err(rslt.unwrap_err());
|
||||||
}
|
}
|
||||||
reg += rslt.unwrap(); // concat regions
|
reg += rslt.unwrap(); // concat regions
|
||||||
return sequence<Tail...>::invoke(loc, std::move(reg), first);
|
return sequence<Tail...>::invoke(loc, std::move(reg), first, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
static std::string pattern()
|
||||||
@@ -219,9 +241,10 @@ struct sequence<Head>
|
|||||||
// would be called from sequence<T ...>::invoke only.
|
// would be called from sequence<T ...>::invoke only.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Cont, typename Iterator>
|
||||||
static result<region<Cont>, std::string>
|
static result<region<Cont>, std::string>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first,
|
||||||
|
const bool msg = false)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
@@ -240,14 +263,15 @@ template<typename Head, typename ... Tail>
|
|||||||
struct either<Head, Tail...>
|
struct either<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc, msg);
|
||||||
if(rslt.is_ok()) {return rslt;}
|
if(rslt.is_ok()) {return rslt;}
|
||||||
return either<Tail...>::invoke(loc);
|
return either<Tail...>::invoke(loc, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
static std::string pattern()
|
||||||
@@ -259,11 +283,12 @@ template<typename Head>
|
|||||||
struct either<Head>
|
struct either<Head>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
return Head::invoke(loc);
|
return Head::invoke(loc, msg);
|
||||||
}
|
}
|
||||||
static std::string pattern()
|
static std::string pattern()
|
||||||
{
|
{
|
||||||
@@ -282,13 +307,14 @@ template<typename T, std::size_t N>
|
|||||||
struct repeat<T, exactly<N>>
|
struct repeat<T, exactly<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
for(std::size_t i=0; i<N; ++i)
|
for(std::size_t i=0; i<N; ++i)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
@@ -308,14 +334,15 @@ template<typename T, std::size_t N>
|
|||||||
struct repeat<T, at_least<N>>
|
struct repeat<T, at_least<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
for(std::size_t i=0; i<N; ++i)
|
for(std::size_t i=0; i<N; ++i)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
@@ -325,7 +352,7 @@ struct repeat<T, at_least<N>>
|
|||||||
}
|
}
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
return ok(std::move(retval));
|
return ok(std::move(retval));
|
||||||
@@ -343,12 +370,13 @@ template<typename T>
|
|||||||
struct repeat<T, unlimited>
|
struct repeat<T, unlimited>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
return ok(std::move(retval));
|
return ok(std::move(retval));
|
||||||
|
|||||||
@@ -25,20 +25,22 @@ inline std::tm localtime_s(const std::time_t* src)
|
|||||||
{
|
{
|
||||||
std::tm dst;
|
std::tm dst;
|
||||||
const auto result = ::localtime_r(src, &dst);
|
const auto result = ::localtime_r(src, &dst);
|
||||||
if(!result)
|
if (!result) { throw std::runtime_error("localtime_r failed."); }
|
||||||
{
|
return dst;
|
||||||
throw std::runtime_error("localtime_r failed.");
|
}
|
||||||
}
|
#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;
|
return dst;
|
||||||
}
|
}
|
||||||
#else
|
#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)
|
inline std::tm localtime_s(const std::time_t* src)
|
||||||
{
|
{
|
||||||
const auto result = std::localtime(src);
|
const auto result = std::localtime(src);
|
||||||
if(!result) {throw std::runtime_error("localtime failed.");}
|
if (!result) { throw std::runtime_error("localtime failed."); }
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -360,12 +362,12 @@ struct local_datetime
|
|||||||
// can be used to get millisecond & microsecond information.
|
// can be used to get millisecond & microsecond information.
|
||||||
const auto t_diff = tp -
|
const auto t_diff = tp -
|
||||||
std::chrono::system_clock::from_time_t(std::mktime(&time));
|
std::chrono::system_clock::from_time_t(std::mktime(&time));
|
||||||
this->time.millisecond = std::chrono::duration_cast<
|
this->time.millisecond = static_cast<std::uint16_t>(
|
||||||
std::chrono::milliseconds>(t_diff).count();
|
std::chrono::duration_cast<std::chrono::milliseconds>(t_diff).count());
|
||||||
this->time.microsecond = std::chrono::duration_cast<
|
this->time.microsecond = static_cast<std::uint16_t>(
|
||||||
std::chrono::microseconds>(t_diff).count();
|
std::chrono::duration_cast<std::chrono::microseconds>(t_diff).count());
|
||||||
this->time.nanosecond = std::chrono::duration_cast<
|
this->time.nanosecond = static_cast<std::uint16_t>(
|
||||||
std::chrono::nanoseconds >(t_diff).count();
|
std::chrono::duration_cast<std::chrono::nanoseconds >(t_diff).count());
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit local_datetime(const std::time_t t)
|
explicit local_datetime(const std::time_t t)
|
||||||
|
|||||||
73
toml/get.hpp
73
toml/get.hpp
@@ -108,6 +108,18 @@ inline std::string get(value&& v)
|
|||||||
return std::move(v.cast<value_t::String>().str);
|
return std::move(v.cast<value_t::String>().str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// std::string_view
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
template<typename T, typename std::enable_if<
|
||||||
|
std::is_same<T, std::string_view>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
inline std::string_view get(const value& v)
|
||||||
|
{
|
||||||
|
return std::string_view(v.cast<value_t::String>().str);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// std::chrono::duration from toml::local_time.
|
// std::chrono::duration from toml::local_time.
|
||||||
|
|
||||||
@@ -546,67 +558,6 @@ T get_or(const toml::value& v, T&& opt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// get_or(table, key, fallback)
|
|
||||||
//
|
|
||||||
// DEPRECATED: use find_or instead.
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
|
|
||||||
auto get_or(const toml::table& tab, const toml::key& ky, T&& opt)
|
|
||||||
-> decltype(get_or(std::declval<value const&>(), std::forward<T>(opt)))
|
|
||||||
{
|
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
|
||||||
return ::toml::get_or(tab.at(ky), std::forward<T>(opt));
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
|
|
||||||
auto get_or(toml::table& tab, const toml::key& ky, T&& opt)
|
|
||||||
-> decltype(get_or(std::declval<value&>(), std::forward<T>(opt)))
|
|
||||||
{
|
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
|
||||||
return ::toml::get_or(tab[ky], std::forward<T>(opt));
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
TOML11_MARK_AS_DEPRECATED("use toml::find_or(table, key, opt) instead.")
|
|
||||||
auto get_or(toml::table&& tab, const toml::key& ky, T&& opt)
|
|
||||||
-> decltype(get_or(std::declval<value&&>(), std::forward<T>(opt)))
|
|
||||||
{
|
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
|
||||||
return ::toml::get_or(std::move(tab[ky]), std::forward<T>(opt));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
|
|
||||||
auto get_or(const toml::value& v, const toml::key& ky, T&& opt)
|
|
||||||
-> decltype(get_or(std::declval<value const&>(), std::forward<T>(opt)))
|
|
||||||
{
|
|
||||||
if(!v.is_table()) {return opt;}
|
|
||||||
const auto& tab = toml::get<toml::table>(v);
|
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
|
||||||
return ::toml::get_or(tab.at(ky), std::forward<T>(opt));
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
|
|
||||||
auto get_or(toml::value& v, const toml::key& ky, T&& opt)
|
|
||||||
-> decltype(get_or(std::declval<value&>(), std::forward<T>(opt)))
|
|
||||||
{
|
|
||||||
if(!v.is_table()) {return opt;}
|
|
||||||
auto& tab = toml::get<toml::table>(v);
|
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
|
||||||
return ::toml::get_or(tab[ky], std::forward<T>(opt));
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
TOML11_MARK_AS_DEPRECATED("use toml::find_or(value, key, opt) instead.")
|
|
||||||
auto get_or(toml::value&& v, const toml::key& ky, T&& opt)
|
|
||||||
-> decltype(get_or(std::declval<value&&>(), std::forward<T>(opt)))
|
|
||||||
{
|
|
||||||
if(!v.is_table()) {return opt;}
|
|
||||||
auto tab = toml::get<toml::table>(std::move(v));
|
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
|
||||||
return ::toml::get_or(std::move(tab[ky]), std::forward<T>(opt));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// find_or(value, key, fallback)
|
// find_or(value, key, fallback)
|
||||||
|
|
||||||
|
|||||||
@@ -30,16 +30,52 @@ inline ::toml::value operator""_toml(const char* str, std::size_t len)
|
|||||||
::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
|
::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
|
||||||
skip_ws::invoke(loc);
|
skip_ws::invoke(loc);
|
||||||
|
|
||||||
// literal may be a bare value. try them first.
|
// to distinguish arrays and tables, first check it is a table or not.
|
||||||
if(auto data = ::toml::detail::parse_value(loc))
|
//
|
||||||
|
// "[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)
|
||||||
{
|
{
|
||||||
return data.unwrap();
|
if(auto data = ::toml::detail::parse_value(loc))
|
||||||
|
{
|
||||||
|
return data.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// literal is a TOML file (i.e. multiline table).
|
// Note that still it can be a table, because the literal might be something
|
||||||
|
// like the following.
|
||||||
|
// ```cpp
|
||||||
|
// R"( // c++11 raw string literals
|
||||||
|
// key = "value"
|
||||||
|
// int = 42
|
||||||
|
// )"_toml;
|
||||||
|
// ```
|
||||||
|
// It is a valid toml file.
|
||||||
|
// It should be parsed as if we parse a file with this content.
|
||||||
|
|
||||||
if(auto data = ::toml::detail::parse_toml_file(loc))
|
if(auto data = ::toml::detail::parse_toml_file(loc))
|
||||||
{
|
{
|
||||||
loc.reset(loc.begin()); // rollback to the top of the literal
|
loc.reset(loc.begin()); // rollback to the top of the literal
|
||||||
|
// skip needless characters for error message
|
||||||
|
skip_line::invoke(loc); // skip the first several needless lines
|
||||||
|
skip_ws::invoke(loc); // skip the first several needless whitespaces
|
||||||
return ::toml::value(std::move(data.unwrap()),
|
return ::toml::value(std::move(data.unwrap()),
|
||||||
::toml::detail::region<std::vector<char>>(std::move(loc)));
|
::toml::detail::region<std::vector<char>>(std::move(loc)));
|
||||||
}
|
}
|
||||||
|
|||||||
176
toml/parser.hpp
176
toml/parser.hpp
@@ -116,10 +116,28 @@ parse_integer(location<Container>& loc)
|
|||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
if(first != loc.end() && *first == '0')
|
if(first != loc.end() && *first == '0')
|
||||||
{
|
{
|
||||||
if(const auto bin = parse_binary_integer (loc)) {return bin;}
|
const auto second = std::next(first);
|
||||||
if(const auto oct = parse_octal_integer (loc)) {return oct;}
|
if(second == loc.end()) // the token is just zero.
|
||||||
if(const auto hex = parse_hexadecimal_integer(loc)) {return hex;}
|
{
|
||||||
// else, maybe just zero.
|
return ok(std::make_pair(0, region<Container>(loc, first, second)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*second == 'b') {return parse_binary_integer (loc);} // 0b1100
|
||||||
|
if(*second == 'o') {return parse_octal_integer (loc);} // 0o775
|
||||||
|
if(*second == 'x') {return parse_hexadecimal_integer(loc);} // 0xC0FFEE
|
||||||
|
|
||||||
|
if(std::isdigit(*second))
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] toml::parse_integer: "
|
||||||
|
"leading zero in an Integer is not allowed.",
|
||||||
|
{{std::addressof(loc), "leading zero"}}));
|
||||||
|
}
|
||||||
|
else if(std::isalpha(*second))
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] toml::parse_integer: "
|
||||||
|
"unknown integer prefix appeared.",
|
||||||
|
{{std::addressof(loc), "none of 0x, 0o, 0b"}}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(const auto token = lex_dec_int::invoke(loc))
|
if(const auto token = lex_dec_int::invoke(loc))
|
||||||
@@ -308,7 +326,7 @@ result<std::string, std::string> parse_escape_sequence(location<Container>& loc)
|
|||||||
{
|
{
|
||||||
return err(format_underline("[error] parse_escape_sequence: "
|
return err(format_underline("[error] parse_escape_sequence: "
|
||||||
"invalid token found in UTF-8 codepoint uXXXX.",
|
"invalid token found in UTF-8 codepoint uXXXX.",
|
||||||
{{std::addressof(loc), token.unwrap_err()}}));
|
{{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'U':
|
case 'U':
|
||||||
@@ -321,7 +339,7 @@ result<std::string, std::string> parse_escape_sequence(location<Container>& loc)
|
|||||||
{
|
{
|
||||||
return err(format_underline("[error] parse_escape_sequence: "
|
return err(format_underline("[error] parse_escape_sequence: "
|
||||||
"invalid token found in UTF-8 codepoint Uxxxxxxxx",
|
"invalid token found in UTF-8 codepoint Uxxxxxxxx",
|
||||||
{{std::addressof(loc), token.unwrap_err()}}));
|
{{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,7 +406,9 @@ parse_ml_basic_string(location<Container>& loc)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(token.unwrap_err());
|
return err(format_underline("[error] toml::parse_ml_basic_string: "
|
||||||
|
"the next token is not a multiline string",
|
||||||
|
{{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +457,9 @@ parse_basic_string(location<Container>& loc)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
loc.reset(first); // rollback
|
loc.reset(first); // rollback
|
||||||
return err(token.unwrap_err());
|
return err(format_underline("[error] toml::parse_basic_string: "
|
||||||
|
"the next token is not a string",
|
||||||
|
{{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,7 +498,9 @@ parse_ml_literal_string(location<Container>& loc)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
loc.reset(first); // rollback
|
loc.reset(first); // rollback
|
||||||
return err(token.unwrap_err());
|
return err(format_underline("[error] toml::parse_ml_literal_string: "
|
||||||
|
"the next token is not a multiline literal string",
|
||||||
|
{{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,7 +537,9 @@ parse_literal_string(location<Container>& loc)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
loc.reset(first); // rollback
|
loc.reset(first); // rollback
|
||||||
return err(token.unwrap_err());
|
return err(format_underline("[error] toml::parse_literal_string: "
|
||||||
|
"the next token is not a literal string",
|
||||||
|
{{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,10 +547,30 @@ template<typename Container>
|
|||||||
result<std::pair<toml::string, region<Container>>, std::string>
|
result<std::pair<toml::string, region<Container>>, std::string>
|
||||||
parse_string(location<Container>& loc)
|
parse_string(location<Container>& loc)
|
||||||
{
|
{
|
||||||
if(const auto rslt = parse_ml_basic_string(loc)) {return rslt;}
|
if(loc.iter() != loc.end() && *(loc.iter()) == '"')
|
||||||
if(const auto rslt = parse_ml_literal_string(loc)) {return rslt;}
|
{
|
||||||
if(const auto rslt = parse_basic_string(loc)) {return rslt;}
|
if(loc.iter() + 1 != loc.end() && *(loc.iter() + 1) == '"' &&
|
||||||
if(const auto rslt = parse_literal_string(loc)) {return rslt;}
|
loc.iter() + 2 != loc.end() && *(loc.iter() + 2) == '"')
|
||||||
|
{
|
||||||
|
return parse_ml_basic_string(loc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return parse_basic_string(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(loc.iter() != loc.end() && *(loc.iter()) == '\'')
|
||||||
|
{
|
||||||
|
if(loc.iter() + 1 != loc.end() && *(loc.iter() + 1) == '\'' &&
|
||||||
|
loc.iter() + 2 != loc.end() && *(loc.iter() + 2) == '\'')
|
||||||
|
{
|
||||||
|
return parse_ml_literal_string(loc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return parse_literal_string(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
return err(format_underline("[error] toml::parse_string: ",
|
return err(format_underline("[error] toml::parse_string: ",
|
||||||
{{std::addressof(loc), "the next token is not a string"}}));
|
{{std::addressof(loc), "the next token is not a string"}}));
|
||||||
}
|
}
|
||||||
@@ -758,7 +804,7 @@ parse_offset_datetime(location<Container>& loc)
|
|||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(format_underline("[error]: toml::parse_offset_datetime: ",
|
return err(format_underline("[error]: toml::parse_offset_datetime: ",
|
||||||
{{std::addressof(loc), "the next token is not a local_datetime"}}));
|
{{std::addressof(loc), "the next token is not a offset_datetime"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1360,10 +1406,16 @@ parse_inline_table(location<Container>& loc)
|
|||||||
return ok(std::make_pair(
|
return ok(std::make_pair(
|
||||||
retval, region<Container>(loc, first, loc.iter())));
|
retval, region<Container>(loc, first, loc.iter())));
|
||||||
}
|
}
|
||||||
|
else if(*loc.iter() == '#' || *loc.iter() == '\r' || *loc.iter() == '\n')
|
||||||
|
{
|
||||||
|
throw syntax_error(format_underline("[error] "
|
||||||
|
"toml::parse_inline_table: missing curly brace `}`",
|
||||||
|
{{std::addressof(loc), "should be `}`"}}));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw syntax_error(format_underline("[error] "
|
throw syntax_error(format_underline("[error] "
|
||||||
"toml:::parse_inline_table: missing table separator `,` ",
|
"toml::parse_inline_table: missing table separator `,` ",
|
||||||
{{std::addressof(loc), "should be `,`"}}));
|
{{std::addressof(loc), "should be `,`"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1374,6 +1426,46 @@ parse_inline_table(location<Container>& loc)
|
|||||||
{{std::addressof(loc), "should be closed"}}));
|
{{std::addressof(loc), "should be closed"}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
value_t guess_number_type(const location<Container>& l)
|
||||||
|
{
|
||||||
|
location<Container> loc = l;
|
||||||
|
|
||||||
|
if(lex_offset_date_time::invoke(loc)) {return value_t::OffsetDatetime;}
|
||||||
|
loc.reset(l.iter());
|
||||||
|
|
||||||
|
if(lex_local_date_time::invoke(loc)) {return value_t::LocalDatetime;}
|
||||||
|
loc.reset(l.iter());
|
||||||
|
|
||||||
|
if(lex_local_date::invoke(loc)) {return value_t::LocalDate;}
|
||||||
|
loc.reset(l.iter());
|
||||||
|
|
||||||
|
if(lex_local_time::invoke(loc)) {return value_t::LocalTime;}
|
||||||
|
loc.reset(l.iter());
|
||||||
|
|
||||||
|
if(lex_float::invoke(loc)) {return value_t::Float;}
|
||||||
|
loc.reset(l.iter());
|
||||||
|
|
||||||
|
return value_t::Integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
value_t guess_value_type(const location<Container>& loc)
|
||||||
|
{
|
||||||
|
switch(*loc.iter())
|
||||||
|
{
|
||||||
|
case '"' : {return value_t::String; }
|
||||||
|
case '\'': {return value_t::String; }
|
||||||
|
case 't' : {return value_t::Boolean;}
|
||||||
|
case 'f' : {return value_t::Boolean;}
|
||||||
|
case '[' : {return value_t::Array; }
|
||||||
|
case '{' : {return value_t::Table; }
|
||||||
|
case 'i' : {return value_t::Float; } // inf.
|
||||||
|
case 'n' : {return value_t::Float; } // nan.
|
||||||
|
default : {return guess_number_type(loc);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
result<value, std::string> parse_value(location<Container>& loc)
|
result<value, std::string> parse_value(location<Container>& loc)
|
||||||
{
|
{
|
||||||
@@ -1383,31 +1475,27 @@ result<value, std::string> parse_value(location<Container>& loc)
|
|||||||
return err(format_underline("[error] toml::parse_value: input is empty",
|
return err(format_underline("[error] toml::parse_value: input is empty",
|
||||||
{{std::addressof(loc), ""}}));
|
{{std::addressof(loc), ""}}));
|
||||||
}
|
}
|
||||||
if(auto r = parse_string (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_array (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_inline_table (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_boolean (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_offset_datetime(loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_local_datetime (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_local_date (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_local_time (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_floating (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
if(auto r = parse_integer (loc))
|
|
||||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
|
||||||
|
|
||||||
const auto msg = format_underline("[error] toml::parse_value: "
|
switch(guess_value_type(loc))
|
||||||
"unknown token appeared", {{std::addressof(loc), "unknown"}});
|
{
|
||||||
loc.reset(first);
|
case value_t::Boolean : {return parse_boolean(loc); }
|
||||||
return err(msg);
|
case value_t::Integer : {return parse_integer(loc); }
|
||||||
|
case value_t::Float : {return parse_floating(loc); }
|
||||||
|
case value_t::String : {return parse_string(loc); }
|
||||||
|
case value_t::OffsetDatetime : {return parse_offset_datetime(loc);}
|
||||||
|
case value_t::LocalDatetime : {return parse_local_datetime(loc); }
|
||||||
|
case value_t::LocalDate : {return parse_local_date(loc); }
|
||||||
|
case value_t::LocalTime : {return parse_local_time(loc); }
|
||||||
|
case value_t::Array : {return parse_array(loc); }
|
||||||
|
case value_t::Table : {return parse_inline_table(loc); }
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
const auto msg = format_underline("[error] toml::parse_value: "
|
||||||
|
"unknown token appeared", {{std::addressof(loc), "unknown"}});
|
||||||
|
loc.reset(first);
|
||||||
|
return err(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
@@ -1463,7 +1551,8 @@ parse_table_key(location<Container>& loc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return err(token.unwrap_err());
|
return err(format_underline("[error] toml::parse_table_key: "
|
||||||
|
"not a valid table key", {{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1471,7 +1560,7 @@ template<typename Container>
|
|||||||
result<std::pair<std::vector<key>, region<Container>>, std::string>
|
result<std::pair<std::vector<key>, region<Container>>, std::string>
|
||||||
parse_array_table_key(location<Container>& loc)
|
parse_array_table_key(location<Container>& loc)
|
||||||
{
|
{
|
||||||
if(auto token = lex_array_table::invoke(loc))
|
if(auto token = lex_array_table::invoke(loc, true))
|
||||||
{
|
{
|
||||||
location<std::string> inner_loc(loc.name(), token.unwrap().str());
|
location<std::string> inner_loc(loc.name(), token.unwrap().str());
|
||||||
|
|
||||||
@@ -1516,7 +1605,8 @@ parse_array_table_key(location<Container>& loc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return err(token.unwrap_err());
|
return err(format_underline("[error] toml::parse_array_table_key: "
|
||||||
|
"not a valid table key", {{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
105
toml/region.hpp
105
toml/region.hpp
@@ -52,6 +52,14 @@ struct region_base
|
|||||||
virtual std::size_t before() const noexcept {return 0;}
|
virtual std::size_t before() const noexcept {return 0;}
|
||||||
// number of characters in the line after the region
|
// number of characters in the line after the region
|
||||||
virtual std::size_t after() const noexcept {return 0;}
|
virtual std::size_t after() const noexcept {return 0;}
|
||||||
|
|
||||||
|
virtual std::string comment_before() const {return "";} // just before
|
||||||
|
virtual std::string comment_inline() const {return "";} // in the same line
|
||||||
|
virtual std::string comment() const {return "";} // concatenate
|
||||||
|
// ```toml
|
||||||
|
// # comment_before
|
||||||
|
// key = "value" # comment_inline
|
||||||
|
// ```
|
||||||
};
|
};
|
||||||
|
|
||||||
// location represents a position in a container, which contains a file content.
|
// location represents a position in a container, which contains a file content.
|
||||||
@@ -71,7 +79,7 @@ struct location final : public region_base
|
|||||||
"container should be randomly accessible");
|
"container should be randomly accessible");
|
||||||
|
|
||||||
location(std::string name, Container cont)
|
location(std::string name, Container cont)
|
||||||
: source_(std::make_shared<Container>(std::move(cont))), line_number_(0),
|
: source_(std::make_shared<Container>(std::move(cont))), line_number_(1),
|
||||||
source_name_(std::move(name)), iter_(source_->cbegin())
|
source_name_(std::move(name)), iter_(source_->cbegin())
|
||||||
{}
|
{}
|
||||||
location(const location&) = default;
|
location(const location&) = default;
|
||||||
@@ -88,7 +96,7 @@ struct location final : public region_base
|
|||||||
const_iterator begin() const noexcept {return source_->cbegin();}
|
const_iterator begin() const noexcept {return source_->cbegin();}
|
||||||
const_iterator end() const noexcept {return source_->cend();}
|
const_iterator end() const noexcept {return source_->cend();}
|
||||||
|
|
||||||
// XXX At first, `location::line_num()` is implemented using `std::count` to
|
// 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),
|
// 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 becomes intolerably slow because each time it generates error messages,
|
||||||
// it counts '\n' from thousands of characters. To workaround it, I decided
|
// it counts '\n' from thousands of characters. To workaround it, I decided
|
||||||
@@ -110,8 +118,8 @@ struct location final : public region_base
|
|||||||
}
|
}
|
||||||
void reset(const_iterator rollback) noexcept
|
void reset(const_iterator rollback) noexcept
|
||||||
{
|
{
|
||||||
// since c++11, std::distance works in both ways and returns a negative
|
// since c++11, std::distance works in both ways for random-access
|
||||||
// value if `first` is ahead from `last`.
|
// iterators and returns a negative value if `first > last`.
|
||||||
if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
|
if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
|
||||||
{
|
{
|
||||||
this->line_number_ -= std::count(rollback, this->iter_, '\n');
|
this->line_number_ -= std::count(rollback, this->iter_, '\n');
|
||||||
@@ -280,6 +288,92 @@ struct region final : public region_base
|
|||||||
|
|
||||||
std::string name() const override {return source_name_;}
|
std::string name() const override {return source_name_;}
|
||||||
|
|
||||||
|
std::string comment_before() const override
|
||||||
|
{
|
||||||
|
auto iter = this->line_begin(); // points the first element
|
||||||
|
std::vector<std::pair<decltype(iter), decltype(iter)>> comments;
|
||||||
|
while(iter != this->begin())
|
||||||
|
{
|
||||||
|
iter = std::prev(iter);
|
||||||
|
using rev_iter = std::reverse_iterator<decltype(iter)>;
|
||||||
|
auto line_before = std::find(rev_iter(iter), rev_iter(this->begin()),
|
||||||
|
'\n').base();
|
||||||
|
// range [line_before, iter) represents the previous line
|
||||||
|
|
||||||
|
auto comment_found = std::find(line_before, iter, '#');
|
||||||
|
if(iter != comment_found && std::all_of(line_before, comment_found,
|
||||||
|
[](const char c) noexcept -> bool {
|
||||||
|
return c == ' ' || c == '\t';
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
// the line before this range contains only a comment.
|
||||||
|
comments.push_back(std::make_pair(comment_found, iter));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iter = line_before;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string com;
|
||||||
|
for(auto i = comments.crbegin(), e = comments.crend(); i!=e; ++i)
|
||||||
|
{
|
||||||
|
if(i != comments.crbegin()) {com += '\n';}
|
||||||
|
com += std::string(i->first, i->second);
|
||||||
|
}
|
||||||
|
return com;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string comment_inline() const override
|
||||||
|
{
|
||||||
|
if(this->contain_newline())
|
||||||
|
{
|
||||||
|
std::string com;
|
||||||
|
// check both the first and the last line.
|
||||||
|
const auto first_line_end =
|
||||||
|
std::find(this->line_begin(), this->last(), '\n');
|
||||||
|
const auto first_comment_found =
|
||||||
|
std::find(this->line_begin(), first_line_end, '#');
|
||||||
|
|
||||||
|
if(first_comment_found != first_line_end)
|
||||||
|
{
|
||||||
|
com += std::string(first_comment_found, first_line_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto last_comment_found =
|
||||||
|
std::find(this->last(), this->line_end(), '#');
|
||||||
|
if(last_comment_found != this->line_end())
|
||||||
|
{
|
||||||
|
if(!com.empty()){com += '\n';}
|
||||||
|
com += std::string(last_comment_found, this->line_end());
|
||||||
|
}
|
||||||
|
return com;
|
||||||
|
}
|
||||||
|
const auto comment_found =
|
||||||
|
std::find(this->line_begin(), this->line_end(), '#');
|
||||||
|
return std::string(comment_found, this->line_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string comment() const override
|
||||||
|
{
|
||||||
|
std::string com_bef = this->comment_before();
|
||||||
|
std::string com_inl = this->comment_inline();
|
||||||
|
if(!com_bef.empty() && !com_inl.empty())
|
||||||
|
{
|
||||||
|
com_bef += '\n';
|
||||||
|
return com_bef + com_inl;
|
||||||
|
}
|
||||||
|
else if(com_bef.empty())
|
||||||
|
{
|
||||||
|
return com_inl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return com_bef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
source_ptr source_;
|
source_ptr source_;
|
||||||
@@ -343,7 +437,8 @@ inline std::string format_underline(const std::string& message,
|
|||||||
{
|
{
|
||||||
// invalid
|
// invalid
|
||||||
// ~~~~~~~
|
// ~~~~~~~
|
||||||
retval << make_string(reg->size(), '~');
|
const auto underline_len = std::min(reg->size(), reg->line().size());
|
||||||
|
retval << make_string(underline_len, '~');
|
||||||
}
|
}
|
||||||
|
|
||||||
retval << ' ';
|
retval << ' ';
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
#define TOML11_STRING_HPP
|
#define TOML11_STRING_HPP
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#if __has_include(<string_view>)
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
@@ -40,6 +45,17 @@ struct string
|
|||||||
operator std::string const& () const& noexcept {return str;}
|
operator std::string const& () const& noexcept {return str;}
|
||||||
operator std::string&& () && noexcept {return std::move(str);}
|
operator std::string&& () && noexcept {return std::move(str);}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
explicit string(std::string_view s): kind(string_t::basic), str(s){}
|
||||||
|
string(std::string_view s, string_t k): kind(k), str(s){}
|
||||||
|
|
||||||
|
string& operator=(std::string_view s)
|
||||||
|
{kind = string_t::basic; str = s; return *this;}
|
||||||
|
|
||||||
|
explicit operator std::string_view() const noexcept
|
||||||
|
{return std::string_view(str);}
|
||||||
|
#endif
|
||||||
|
|
||||||
string_t kind;
|
string_t kind;
|
||||||
std::string str;
|
std::string str;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,11 @@
|
|||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#if __has_include(<string_view>)
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
@@ -172,6 +177,9 @@ template<typename T>
|
|||||||
struct is_container : conjunction<
|
struct is_container : conjunction<
|
||||||
negation<is_map<T>>,
|
negation<is_map<T>>,
|
||||||
negation<std::is_same<T, std::string>>,
|
negation<std::is_same<T, std::string>>,
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
negation<std::is_same<T, std::string_view>>,
|
||||||
|
#endif
|
||||||
has_iterator<T>,
|
has_iterator<T>,
|
||||||
has_value_type<T>
|
has_value_type<T>
|
||||||
>{};
|
>{};
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
@@ -293,6 +296,29 @@ class value
|
|||||||
assigner(this->string_, toml::string(std::string(s), kind));
|
assigner(this->string_, toml::string(std::string(s), kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
value(std::string_view s)
|
||||||
|
: type_(value_t::String),
|
||||||
|
region_info_(std::make_shared<region_base>(region_base{}))
|
||||||
|
{
|
||||||
|
assigner(this->string_, toml::string(s));
|
||||||
|
}
|
||||||
|
value& operator=(std::string_view s)
|
||||||
|
{
|
||||||
|
this->cleanup();
|
||||||
|
this->type_ = value_t::String;
|
||||||
|
this->region_info_ = std::make_shared<region_base>(region_base{});
|
||||||
|
assigner(this->string_, toml::string(s));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
value(std::string_view s, string_t kind)
|
||||||
|
: type_(value_t::String),
|
||||||
|
region_info_(std::make_shared<region_base>(region_base{}))
|
||||||
|
{
|
||||||
|
assigner(this->string_, toml::string(s, kind));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// local date ===========================================================
|
// local date ===========================================================
|
||||||
|
|
||||||
value(const local_date& ld)
|
value(const local_date& ld)
|
||||||
@@ -572,6 +598,14 @@ class value
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for internal use ------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename T, typename Container, typename std::enable_if<
|
||||||
|
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
|
value(std::pair<T, detail::region<Container>> parse_result)
|
||||||
|
: value(std::move(parse_result.first), std::move(parse_result.second))
|
||||||
|
{}
|
||||||
|
|
||||||
// type checking and casting ============================================
|
// type checking and casting ============================================
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -599,6 +633,41 @@ class value
|
|||||||
template<value_t T>
|
template<value_t T>
|
||||||
typename detail::toml_default_type<T>::type&& cast() &&;
|
typename detail::toml_default_type<T>::type&& cast() &&;
|
||||||
|
|
||||||
|
boolean const& as_boolean() const {return this->cast<value_t::Boolean >();}
|
||||||
|
integer const& as_integer() const {return this->cast<value_t::Integer >();}
|
||||||
|
floating const& as_float() const {return this->cast<value_t::Float >();}
|
||||||
|
string const& as_string() const {return this->cast<value_t::String >();}
|
||||||
|
offset_datetime const& as_offset_datetime() const {return this->cast<value_t::OffsetDatetime>();}
|
||||||
|
local_datetime const& as_local_datetime() const {return this->cast<value_t::LocalDatetime >();}
|
||||||
|
local_date const& as_local_date() const {return this->cast<value_t::LocalDate >();}
|
||||||
|
local_time const& as_local_time() const {return this->cast<value_t::LocalTime >();}
|
||||||
|
array const& as_array() const {return this->cast<value_t::Array >();}
|
||||||
|
table const& as_table() const {return this->cast<value_t::Table >();}
|
||||||
|
|
||||||
|
boolean& as_boolean() {return this->cast<value_t::Boolean >();}
|
||||||
|
integer& as_integer() {return this->cast<value_t::Integer >();}
|
||||||
|
floating& as_float() {return this->cast<value_t::Float >();}
|
||||||
|
string& as_string() {return this->cast<value_t::String >();}
|
||||||
|
offset_datetime& as_offset_datetime() {return this->cast<value_t::OffsetDatetime>();}
|
||||||
|
local_datetime& as_local_datetime() {return this->cast<value_t::LocalDatetime >();}
|
||||||
|
local_date& as_local_date() {return this->cast<value_t::LocalDate >();}
|
||||||
|
local_time& as_local_time() {return this->cast<value_t::LocalTime >();}
|
||||||
|
array& as_array() {return this->cast<value_t::Array >();}
|
||||||
|
table& as_table() {return this->cast<value_t::Table >();}
|
||||||
|
|
||||||
|
std::string comment() const
|
||||||
|
{
|
||||||
|
return this->region_info_->comment();
|
||||||
|
}
|
||||||
|
std::string comment_before() const
|
||||||
|
{
|
||||||
|
return this->region_info_->comment_before();
|
||||||
|
}
|
||||||
|
std::string comment_inline() const
|
||||||
|
{
|
||||||
|
return this->region_info_->comment_inline();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void cleanup() noexcept
|
void cleanup() noexcept
|
||||||
|
|||||||
Reference in New Issue
Block a user