mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bf9e42835 | ||
|
|
4a2c823d56 | ||
|
|
24c28c7f4f | ||
|
|
cab3144507 | ||
|
|
dee32e7d5e | ||
|
|
53a185e7a9 | ||
|
|
fd980a8c5d | ||
|
|
73ac43d70c | ||
|
|
adcd75e017 | ||
|
|
569341a514 | ||
|
|
0357d8fb57 | ||
|
|
00d40140ac | ||
|
|
1bfe8f1f54 | ||
|
|
bc143263cd | ||
|
|
1b19d5f1eb | ||
|
|
fd7da05798 | ||
|
|
cbaaaaca7c | ||
|
|
cf1c9371b6 | ||
|
|
62e8d58d8d | ||
|
|
acbc2a73cb | ||
|
|
b2daf916b3 | ||
|
|
e66bb3d359 | ||
|
|
cfaa94f072 | ||
|
|
2f4f3efbf0 | ||
|
|
06ae67502a | ||
|
|
57cb806e14 | ||
|
|
d6f3654185 | ||
|
|
8befe3f1ad | ||
|
|
2d43119ac7 | ||
|
|
436af12815 | ||
|
|
4f4d4380f2 | ||
|
|
31debcb8aa | ||
|
|
2afa0ff0c3 | ||
|
|
46047c48bf | ||
|
|
897aecf5d4 | ||
|
|
7db8388d17 | ||
|
|
62c993e096 | ||
|
|
014d882f8f | ||
|
|
2cbb93d86e | ||
|
|
a19b94511b | ||
|
|
70d0049511 |
@@ -1,7 +1,17 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
project(toml11)
|
project(toml11)
|
||||||
|
|
||||||
|
set(toml11_VERSION_MAYOR 2)
|
||||||
|
set(toml11_VERSION_MINOR 4)
|
||||||
|
set(toml11_VERSION_PATCH 0)
|
||||||
|
set(toml11_VERSION
|
||||||
|
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}"
|
||||||
|
)
|
||||||
|
|
||||||
|
option(toml11_BUILD_TEST "Build toml tests" ON)
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
@@ -34,5 +44,62 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR})
|
# Set some common directories
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
set(toml11_install_cmake_dir ${CMAKE_INSTALL_LIBDIR}/cmake/toml11)
|
||||||
|
set(toml11_install_include_dir ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
set(toml11_config_dir ${CMAKE_CURRENT_BINARY_DIR}/cmake/)
|
||||||
|
set(toml11_config ${toml11_config_dir}/toml11Config.cmake)
|
||||||
|
set(toml11_config_version ${toml11_config_dir}/toml11ConfigVersion.cmake)
|
||||||
|
|
||||||
|
add_library(toml11 INTERFACE)
|
||||||
|
target_include_directories(toml11 INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${toml11_install_include_dir}>
|
||||||
|
)
|
||||||
|
add_library(toml11::toml11 ALIAS toml11)
|
||||||
|
|
||||||
|
# Write config and version config files
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
write_basic_package_version_file(
|
||||||
|
${toml11_config_version}
|
||||||
|
VERSION ${toml11_VERSION}
|
||||||
|
COMPATIBILITY SameMajorVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_package_config_file(
|
||||||
|
cmake/toml11Config.cmake.in
|
||||||
|
${toml11_config}
|
||||||
|
INSTALL_DESTINATION ${toml11_install_cmake_dir}
|
||||||
|
PATH_VARS toml11_install_cmake_dir
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install config files
|
||||||
|
install(FILES ${toml11_config} ${toml11_config_version}
|
||||||
|
DESTINATION ${toml11_install_cmake_dir}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install header files
|
||||||
|
install(
|
||||||
|
FILES toml.hpp
|
||||||
|
DESTINATION "${toml11_install_include_dir}"
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
DIRECTORY "toml"
|
||||||
|
DESTINATION "${toml11_install_include_dir}"
|
||||||
|
FILES_MATCHING PATTERN "*.hpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Export targets and install them
|
||||||
|
install(TARGETS toml11
|
||||||
|
EXPORT toml11Targets
|
||||||
|
)
|
||||||
|
install(EXPORT toml11Targets
|
||||||
|
FILE toml11Targets.cmake
|
||||||
|
DESTINATION ${toml11_install_cmake_dir}
|
||||||
|
NAMESPACE toml11::
|
||||||
|
)
|
||||||
|
|
||||||
|
if (toml11_BUILD_TEST)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
endif ()
|
||||||
|
|||||||
183
README.md
183
README.md
@@ -144,6 +144,24 @@ terminate called after throwing an instance of 'toml::syntax_error'
|
|||||||
| ~~~~~~~ table defined twice
|
| ~~~~~~~ table defined twice
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When toml11 encounters a malformed value, it tries to detect what type it is.
|
||||||
|
Then it shows hints to fix the format. An error message while reading one of
|
||||||
|
the malformed files in [the language agnostic test suite](https://github.com/BurntSushi/toml-test).
|
||||||
|
is shown below.
|
||||||
|
|
||||||
|
```console
|
||||||
|
what(): [error] bad time: should be HH:MM:SS.subsec
|
||||||
|
--> ./datetime-malformed-no-secs.toml
|
||||||
|
1 | no-secs = 1987-07-05T17:45Z
|
||||||
|
| ^------- HH:MM:SS.subsec
|
||||||
|
|
|
||||||
|
Hint: pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999
|
||||||
|
Hint: fail: 1979-05-27T7:32:00, 1979-05-27 17:32
|
||||||
|
```
|
||||||
|
|
||||||
|
You can find other examples in a job named `output_result` on
|
||||||
|
[CircleCI](https://circleci.com/gh/ToruNiina/toml11).
|
||||||
|
|
||||||
Since the error message generation is generally a difficult task, the current
|
Since the error message generation is generally a difficult task, the current
|
||||||
status is not ideal. If you encounter a weird error message, please let us know
|
status is not ideal. If you encounter a weird error message, please let us know
|
||||||
and contribute to improve the quality!
|
and contribute to improve the quality!
|
||||||
@@ -425,6 +443,10 @@ toml::integer opt = 42;
|
|||||||
toml::integer& i = toml::get_or(v, opt); // this works.
|
toml::integer& i = toml::get_or(v, opt); // this works.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
There is also a function `find_or`, but there is a known issue around overload
|
||||||
|
resolution. To use it, passing a `toml::value`, not a `toml::table`, is strongly
|
||||||
|
recommended.
|
||||||
|
|
||||||
## Expecting conversion
|
## Expecting conversion
|
||||||
|
|
||||||
By using `toml::expect`, you will get your expected value or an error message
|
By using `toml::expect`, you will get your expected value or an error message
|
||||||
@@ -451,36 +473,20 @@ const auto value = toml::expect<int>(data.at("number"))
|
|||||||
|
|
||||||
## Finding a value from a table
|
## Finding a value from a table
|
||||||
|
|
||||||
toml11 provides utility function to find a value from `toml::table`.
|
toml11 provides a utility function to find a value from `toml::value` and `toml::table`.
|
||||||
Of course, you can do this in your own way with `toml::get` because
|
|
||||||
it just searches an `unordered_map` and returns a value if it exists.
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto data = toml::parse("example.toml");
|
const toml::value data = /* ... */;
|
||||||
const auto num = toml::find<int>(data, "num", /*for err msg*/"example.toml");
|
|
||||||
|
// find a value named "num" from `data`.
|
||||||
|
const auto num = toml::find<int>(data, "num");
|
||||||
```
|
```
|
||||||
|
|
||||||
If the value does not exist, it throws `std::out_of_range` with an error message.
|
When you pass a `toml::value`, `toml::find` first casts it to `toml::table`.
|
||||||
|
If casting failed, `toml::type_error` will be thrown.
|
||||||
|
|
||||||
```console
|
When the value does not exist, it throws `std::out_of_range` with an error message.
|
||||||
terminate called after throwing an instance of 'std::out_of_range'
|
By passing a `toml::value`, it shows an informative error message like the following.
|
||||||
what(): [error] key "num" not found in example.toml
|
|
||||||
```
|
|
||||||
|
|
||||||
You can use this with a `toml::value` that is expected to be a `toml::table`.
|
|
||||||
It automatically casts the value to table.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
const auto data = toml::parse("example.toml");
|
|
||||||
const auto num = toml::find<int>(data.at("table"), "num");
|
|
||||||
// expecting the following example.toml
|
|
||||||
// [table]
|
|
||||||
// num = 42
|
|
||||||
```
|
|
||||||
|
|
||||||
In this case, because the value `data.at("table")` knows the locatoin of itself,
|
|
||||||
you don't need to pass where you find the value.
|
|
||||||
`toml::find` will show you an error message including table location.
|
|
||||||
|
|
||||||
```console
|
```console
|
||||||
terminate called after throwing an instance of 'std::out_of_range'
|
terminate called after throwing an instance of 'std::out_of_range'
|
||||||
@@ -490,17 +496,36 @@ terminate called after throwing an instance of 'std::out_of_range'
|
|||||||
| ~~~~~~~ in this table
|
| ~~~~~~~ in this table
|
||||||
```
|
```
|
||||||
|
|
||||||
If it's not a `toml::table`, the same error as "invalid type" would be thrown.
|
Contrary, since `toml::table` is just an alias of `std::unordered_map<toml::key, toml::value>`,
|
||||||
|
you need to pass a name to the function to show the name in the exception with `toml::table`.
|
||||||
There is another utility function, `toml::find_or`.
|
|
||||||
It is almost same as `toml::find`, but returns a default value if the value is
|
|
||||||
not found or has a different type, like `toml::get_or`.
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const auto data = toml::parse("example.toml");
|
const toml::table data = /* ... */;
|
||||||
const auto num = toml::find_or(data.at("table"), "num", 42);
|
|
||||||
|
// you need to pass the name of the table to show it in an error message
|
||||||
|
const auto num = toml::find<int>(data, "num", "[data]");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
terminate called after throwing an instance of 'std::out_of_range'
|
||||||
|
what(): [error] key "num" not found in [data]
|
||||||
|
# table name is needed to show this part ^^^^^^
|
||||||
|
```
|
||||||
|
|
||||||
|
By default (w/o template parameter), `toml::find` returns a `toml::value`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const toml::value& subtable = toml::find(table, "subtable");
|
||||||
|
```
|
||||||
|
|
||||||
|
__NOTE__:
|
||||||
|
A new feature, recursive toml::find was planned to be introduced, but it was
|
||||||
|
found that the change breaks a code that was previously compiled fine. So the
|
||||||
|
change was reverted.
|
||||||
|
The reason is that the overload resolution was ambiguous. To support this,
|
||||||
|
in the next major update, overloads of `toml::find` for `toml::table` possibly
|
||||||
|
be removed.
|
||||||
|
|
||||||
## Checking value type
|
## Checking value type
|
||||||
|
|
||||||
You can check what type of value does `toml::value` contains by `is_*` function.
|
You can check what type of value does `toml::value` contains by `is_*` function.
|
||||||
@@ -516,20 +541,27 @@ if(v.is_integer())
|
|||||||
The complete list of the functions is below.
|
The complete list of the functions is below.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const toml::value v(/*...*/);
|
namespace toml {
|
||||||
v.is_boolean();
|
class value {
|
||||||
v.is_integer();
|
// ...
|
||||||
v.is_float();
|
bool is_boolean() const noexcept;
|
||||||
v.is_string();
|
bool is_integer() const noexcept;
|
||||||
v.is_offset_datetime();
|
bool is_floating() const noexcept;
|
||||||
v.is_local_datetime();
|
bool is_string() const noexcept;
|
||||||
v.is_local_date();
|
bool is_offset_datetime() const noexcept;
|
||||||
v.is_local_time();
|
bool is_local_datetime() const noexcept;
|
||||||
v.is_array();
|
bool is_local_date() const noexcept;
|
||||||
v.is_table();
|
bool is_local_time() const noexcept;
|
||||||
v.is_uninitialized();
|
bool is_array() const noexcept;
|
||||||
|
bool is_table() const noexcept;
|
||||||
|
bool is_uninitialized() const noexcept;
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
} // toml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
__NOTE__: `is_float` is marked as deprecated since v2.4.0 to make the function names consistent with snake case typenames. Please use `is_floating` instead.
|
||||||
|
|
||||||
Also, you can get `enum class` value from `toml::value`.
|
Also, you can get `enum class` value from `toml::value`.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
@@ -566,23 +598,56 @@ if(v.is_integer() && v.as_integer() == 42)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The complete list of the functions is below.
|
`as_*` functions internally checks the current contained type for safety and
|
||||||
|
throws `toml::type_error` if the contained value type is different (after toml11
|
||||||
|
v2.4.0). If you already confirmed that the value has the type you will cast
|
||||||
|
into, you can skip the additional checking by passing `std::nothrow` object to it.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const toml::value v(/*...*/);
|
toml::value v = /* ... */;
|
||||||
v.as_boolean();
|
if(v.is_integer() && v.as_integer(std::nothrow) == 42) // never fail
|
||||||
v.as_integer();
|
{
|
||||||
v.as_float();
|
std::cout << "value is 42" << std::endl;
|
||||||
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();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The full list of the functions is below.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace toml {
|
||||||
|
class value {
|
||||||
|
// ...
|
||||||
|
const boolean& as_boolean() const&;
|
||||||
|
const integer& as_integer() const&;
|
||||||
|
const floating& as_floating() const&;
|
||||||
|
const string& as_string() const&;
|
||||||
|
const offset_datetime& as_offset_datetime() const&;
|
||||||
|
const local_datetime& as_local_datetime() const&;
|
||||||
|
const local_date& as_local_date() const&;
|
||||||
|
const local_time& as_local_time() const&;
|
||||||
|
const array& as_array() const&;
|
||||||
|
const table& as_table() const&;
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// non-const version
|
||||||
|
boolean& as_boolean() &;
|
||||||
|
// ditto...
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// rvalue version
|
||||||
|
boolean&& as_boolean() &&;
|
||||||
|
// ditto...
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// noexcept versions ...
|
||||||
|
const boolean& as_boolean(const std::nothrow_t&) const& noexcept;
|
||||||
|
boolean& as_boolean(const std::nothrow_t&) & noexcept;
|
||||||
|
boolean&& as_boolean(const std::nothrow_t&) && noexcept;
|
||||||
|
// ditto...
|
||||||
|
};
|
||||||
|
} // toml
|
||||||
|
```
|
||||||
|
|
||||||
|
__NOTE__: `as_float` is marked as deprecated since v2.4.0 to make the function names consistent with snake case typenames. Please use `as_floating` instead.
|
||||||
|
|
||||||
## 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
|
||||||
@@ -1070,6 +1135,10 @@ I appreciate the help of the contributors who introduced the great feature to th
|
|||||||
- Fixed warnings on MSVC
|
- Fixed warnings on MSVC
|
||||||
- Ivan Shynkarenka (@chronoxor)
|
- Ivan Shynkarenka (@chronoxor)
|
||||||
- Fixed Visual Studio 2019 warnings
|
- Fixed Visual Studio 2019 warnings
|
||||||
|
- @khoitd1997
|
||||||
|
- Fixed warnings while type conversion
|
||||||
|
- @KerstinKeller
|
||||||
|
- Added installation script to CMake
|
||||||
|
|
||||||
## Licensing terms
|
## Licensing terms
|
||||||
|
|
||||||
|
|||||||
2
cmake/toml11Config.cmake.in
Normal file
2
cmake/toml11Config.cmake.in
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
@PACKAGE_INIT@
|
||||||
|
include("@PACKAGE_toml11_install_cmake_dir@/toml11Targets.cmake")
|
||||||
@@ -88,7 +88,7 @@ add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST)
|
|||||||
|
|
||||||
foreach(TEST_NAME ${TEST_NAMES})
|
foreach(TEST_NAME ${TEST_NAMES})
|
||||||
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
||||||
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
|
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
|
||||||
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
||||||
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
@@ -105,3 +105,4 @@ endforeach(TEST_NAME)
|
|||||||
add_executable(test_multiple_translation_unit
|
add_executable(test_multiple_translation_unit
|
||||||
test_multiple_translation_unit_1.cpp
|
test_multiple_translation_unit_1.cpp
|
||||||
test_multiple_translation_unit_2.cpp)
|
test_multiple_translation_unit_2.cpp)
|
||||||
|
target_link_libraries(test_multiple_translation_unit toml11::toml11)
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
|
|||||||
const toml::value v1 = u8"3.1415"_toml;
|
const toml::value v1 = u8"3.1415"_toml;
|
||||||
const toml::value v2 = u8"6.02e+23"_toml;
|
const toml::value v2 = u8"6.02e+23"_toml;
|
||||||
|
|
||||||
BOOST_CHECK(v1.is_float());
|
BOOST_CHECK(v1.is_floating());
|
||||||
BOOST_CHECK(v2.is_float());
|
BOOST_CHECK(v2.is_floating());
|
||||||
BOOST_CHECK_CLOSE(toml::get<double>(v1), 3.1415, 0.00001);
|
BOOST_CHECK_CLOSE(toml::get<double>(v1), 3.1415, 0.00001);
|
||||||
BOOST_CHECK_CLOSE(toml::get<double>(v2), 6.02e23, 0.0001);
|
BOOST_CHECK_CLOSE(toml::get<double>(v2), 6.02e23, 0.0001);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
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(v1.as_boolean(), true);
|
||||||
BOOST_CHECK_EQUAL(v2.as_boolean(), false);
|
BOOST_CHECK_EQUAL(v2.as_boolean(), false);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_boolean(std::nothrow), true);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_boolean(std::nothrow), false);
|
||||||
|
|
||||||
v1 = false;
|
v1 = false;
|
||||||
v2 = true;
|
v2 = true;
|
||||||
@@ -96,12 +98,12 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
|||||||
BOOST_CHECK(v1.is<toml::Integer>());
|
BOOST_CHECK(v1.is<toml::Integer>());
|
||||||
BOOST_CHECK(v2.is<toml::Float>());
|
BOOST_CHECK(v2.is<toml::Float>());
|
||||||
BOOST_CHECK(v1.is_integer());
|
BOOST_CHECK(v1.is_integer());
|
||||||
BOOST_CHECK(v2.is_float());
|
BOOST_CHECK(v2.is_floating());
|
||||||
|
|
||||||
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(v1.as_integer(), 42);
|
||||||
BOOST_CHECK_EQUAL(v2.as_float(), 3.14);
|
BOOST_CHECK_EQUAL(v2.as_floating(), 3.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_integer)
|
BOOST_AUTO_TEST_CASE(test_value_integer)
|
||||||
@@ -122,6 +124,8 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
|||||||
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(v1.as_integer(), -42);
|
||||||
BOOST_CHECK_EQUAL(v2.as_integer(), 42u);
|
BOOST_CHECK_EQUAL(v2.as_integer(), 42u);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_integer(std::nothrow), -42);
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_integer(std::nothrow), 42u);
|
||||||
|
|
||||||
v1 = 54;
|
v1 = 54;
|
||||||
v2 = -54;
|
v2 = -54;
|
||||||
@@ -205,13 +209,15 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Float));
|
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v1.is<toml::Float>());
|
BOOST_CHECK(v1.is<toml::Float>());
|
||||||
BOOST_CHECK(v2.is<toml::Float>());
|
BOOST_CHECK(v2.is<toml::Float>());
|
||||||
BOOST_CHECK(v1.is_float());
|
BOOST_CHECK(v1.is_floating());
|
||||||
BOOST_CHECK(v2.is_float());
|
BOOST_CHECK(v2.is_floating());
|
||||||
|
|
||||||
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_EQUAL (v1.as_floating(), 3.14);
|
||||||
BOOST_CHECK_CLOSE_FRACTION(v2.as_float(), 3.14, 1e-2);
|
BOOST_CHECK_CLOSE_FRACTION(v2.as_floating(), 3.14, 1e-2);
|
||||||
|
BOOST_CHECK_EQUAL (v1.as_floating(std::nothrow), 3.14);
|
||||||
|
BOOST_CHECK_CLOSE_FRACTION(v2.as_floating(std::nothrow), 3.14, 1e-2);
|
||||||
|
|
||||||
v1 = 2.718f;
|
v1 = 2.718f;
|
||||||
v2 = 2.718;
|
v2 = 2.718;
|
||||||
@@ -222,13 +228,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v2.is(toml::value_t::Float));
|
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v1.is<toml::Float>());
|
BOOST_CHECK(v1.is<toml::Float>());
|
||||||
BOOST_CHECK(v2.is<toml::Float>());
|
BOOST_CHECK(v2.is<toml::Float>());
|
||||||
BOOST_CHECK(v1.is_float());
|
BOOST_CHECK(v1.is_floating());
|
||||||
BOOST_CHECK(v2.is_float());
|
BOOST_CHECK(v2.is_floating());
|
||||||
|
|
||||||
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_CLOSE_FRACTION(v1.as_floating(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL (v2.as_float(), 2.718);
|
BOOST_CHECK_EQUAL (v2.as_floating(), 2.718);
|
||||||
|
|
||||||
toml::value v3(v1);
|
toml::value v3(v1);
|
||||||
toml::value v4(v2);
|
toml::value v4(v2);
|
||||||
@@ -241,13 +247,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v4.is(toml::value_t::Float));
|
BOOST_CHECK(v4.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v3.is<toml::Float>());
|
BOOST_CHECK(v3.is<toml::Float>());
|
||||||
BOOST_CHECK(v4.is<toml::Float>());
|
BOOST_CHECK(v4.is<toml::Float>());
|
||||||
BOOST_CHECK(v3.is_float());
|
BOOST_CHECK(v3.is_floating());
|
||||||
BOOST_CHECK(v4.is_float());
|
BOOST_CHECK(v4.is_floating());
|
||||||
|
|
||||||
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_CLOSE_FRACTION(v3.as_floating(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL (v4.as_float(), 2.718);
|
BOOST_CHECK_EQUAL (v4.as_floating(), 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));
|
||||||
@@ -258,13 +264,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
|||||||
BOOST_CHECK(v6.is(toml::value_t::Float));
|
BOOST_CHECK(v6.is(toml::value_t::Float));
|
||||||
BOOST_CHECK(v5.is<toml::Float>());
|
BOOST_CHECK(v5.is<toml::Float>());
|
||||||
BOOST_CHECK(v6.is<toml::Float>());
|
BOOST_CHECK(v6.is<toml::Float>());
|
||||||
BOOST_CHECK(v5.is_float());
|
BOOST_CHECK(v5.is_floating());
|
||||||
BOOST_CHECK(v6.is_float());
|
BOOST_CHECK(v6.is_floating());
|
||||||
|
|
||||||
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_CLOSE_FRACTION(v5.as_floating(), 2.718, 1e-3);
|
||||||
BOOST_CHECK_EQUAL (v6.as_float(), 2.718);
|
BOOST_CHECK_EQUAL (v6.as_floating(), 2.718);
|
||||||
|
|
||||||
v1 = true;
|
v1 = true;
|
||||||
v2 = false;
|
v2 = false;
|
||||||
@@ -309,7 +315,9 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
|||||||
BOOST_CHECK_EQUAL(v1.as_string(), "foo");
|
BOOST_CHECK_EQUAL(v1.as_string(), "foo");
|
||||||
BOOST_CHECK_EQUAL(v2.as_string(), "foo");
|
BOOST_CHECK_EQUAL(v2.as_string(), "foo");
|
||||||
BOOST_CHECK_EQUAL(v3.as_string(), "foo");
|
BOOST_CHECK_EQUAL(v3.as_string(), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_string(std::nothrow), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v2.as_string(std::nothrow), "foo");
|
||||||
|
BOOST_CHECK_EQUAL(v3.as_string(std::nothrow), "foo");
|
||||||
|
|
||||||
v1 = "bar";
|
v1 = "bar";
|
||||||
v2 = "bar";
|
v2 = "bar";
|
||||||
@@ -439,6 +447,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_date)
|
|||||||
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(),
|
BOOST_CHECK_EQUAL(v1.as_local_date(),
|
||||||
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(std::nothrow),
|
||||||
|
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);
|
||||||
|
|
||||||
@@ -503,6 +513,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_time)
|
|||||||
v2.cast<toml::value_t::LocalTime>());
|
v2.cast<toml::value_t::LocalTime>());
|
||||||
BOOST_CHECK_EQUAL(v1.as_local_time(),
|
BOOST_CHECK_EQUAL(v1.as_local_time(),
|
||||||
v2.as_local_time());
|
v2.as_local_time());
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_local_time(std::nothrow),
|
||||||
|
v2.as_local_time(std::nothrow));
|
||||||
|
|
||||||
v1 = toml::local_time(1, 30, 0, /*ms*/ 100, /*us*/ 0);
|
v1 = toml::local_time(1, 30, 0, /*ms*/ 100, /*us*/ 0);
|
||||||
|
|
||||||
@@ -557,6 +569,11 @@ 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(std::nothrow),
|
||||||
|
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),
|
||||||
@@ -628,6 +645,13 @@ 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(std::nothrow),
|
||||||
|
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),
|
||||||
@@ -705,7 +729,11 @@ BOOST_AUTO_TEST_CASE(test_value_array)
|
|||||||
BOOST_CHECK_EQUAL(v1.as_array().at(2).as_integer(), 3);
|
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(3).as_integer(), 4);
|
||||||
BOOST_CHECK_EQUAL(v1.as_array().at(4).as_integer(), 5);
|
BOOST_CHECK_EQUAL(v1.as_array().at(4).as_integer(), 5);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array(std::nothrow).at(0).as_integer(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array(std::nothrow).at(1).as_integer(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array(std::nothrow).at(2).as_integer(), 3);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array(std::nothrow).at(3).as_integer(), 4);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_array(std::nothrow).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);
|
||||||
@@ -792,8 +820,11 @@ BOOST_AUTO_TEST_CASE(test_value_table)
|
|||||||
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("foo").as_integer(), 42);
|
||||||
BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_float(), 3.14);
|
BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_floating(), 3.14);
|
||||||
BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "qux");
|
BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "qux");
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table(std::nothrow).at("foo").as_integer(), 42);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table(std::nothrow).at("bar").as_floating(), 3.14);
|
||||||
|
BOOST_CHECK_EQUAL(v1.as_table(std::nothrow).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"}};
|
||||||
@@ -806,7 +837,7 @@ 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("foo").as_floating(), 2.71);
|
||||||
BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_integer(), 54);
|
BOOST_CHECK_EQUAL(v1.as_table().at("bar").as_integer(), 54);
|
||||||
BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "quux");
|
BOOST_CHECK_EQUAL(v1.as_table().at("baz").as_string().str, "quux");
|
||||||
|
|
||||||
@@ -822,7 +853,7 @@ 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("foo").as_floating(), 2.71);
|
||||||
BOOST_CHECK_EQUAL(v3.as_table().at("bar").as_integer(), 54);
|
BOOST_CHECK_EQUAL(v3.as_table().at("bar").as_integer(), 54);
|
||||||
BOOST_CHECK_EQUAL(v3.as_table().at("baz").as_string().str, "quux");
|
BOOST_CHECK_EQUAL(v3.as_table().at("baz").as_string().str, "quux");
|
||||||
|
|
||||||
@@ -841,4 +872,15 @@ BOOST_AUTO_TEST_CASE(test_value_empty)
|
|||||||
toml::value v1;
|
toml::value v1;
|
||||||
BOOST_CHECK(v1.is_uninitialized());
|
BOOST_CHECK(v1.is_uninitialized());
|
||||||
BOOST_CHECK(v1.is(toml::value_t::Empty));
|
BOOST_CHECK(v1.is(toml::value_t::Empty));
|
||||||
|
|
||||||
|
BOOST_CHECK_THROW(v1.as_boolean(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_integer(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_floating(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_string(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_offset_datetime(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_local_datetime(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_local_date(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_local_time(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_array(), toml::type_error);
|
||||||
|
BOOST_CHECK_THROW(v1.as_table(), toml::type_error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ inline std::string show_char(const char c)
|
|||||||
buf.fill('\0');
|
buf.fill('\0');
|
||||||
const auto r = std::snprintf(
|
const auto r = std::snprintf(
|
||||||
buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
|
buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
|
||||||
assert(r == buf.size() - 1);
|
assert(r == static_cast<int>(buf.size()) - 1);
|
||||||
return std::string(buf.data());
|
return std::string(buf.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
toml/get.hpp
41
toml/get.hpp
@@ -519,7 +519,7 @@ std::string get_or(toml::value&& v, T&& opt)
|
|||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return opt;
|
return std::forward<T>(opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename T, typename std::enable_if<
|
template<typename T, typename std::enable_if<
|
||||||
@@ -541,9 +541,12 @@ std::string get_or(const toml::value& v, T&& opt)
|
|||||||
// others (require type conversion and return type cannot be lvalue reference)
|
// others (require type conversion and return type cannot be lvalue reference)
|
||||||
|
|
||||||
template<typename T, typename std::enable_if<detail::conjunction<
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
detail::negation<detail::is_exact_toml_type<T>>,
|
detail::negation<detail::is_exact_toml_type<
|
||||||
detail::negation<std::is_same<T, std::string>>,
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
||||||
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
detail::negation<std::is_same<std::string,
|
||||||
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
||||||
|
detail::negation<detail::is_string_literal<
|
||||||
|
typename std::remove_reference<T>::type>>
|
||||||
>::value, std::nullptr_t>::type = nullptr>
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
T get_or(const toml::value& v, T&& opt)
|
T get_or(const toml::value& v, T&& opt)
|
||||||
{
|
{
|
||||||
@@ -554,7 +557,7 @@ T get_or(const toml::value& v, T&& opt)
|
|||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
return opt;
|
return T(std::move(opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,9 +620,9 @@ template<typename T, typename std::enable_if<
|
|||||||
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
std::string find_or(toml::value&& v, const toml::key& ky, T&& opt)
|
std::string find_or(toml::value&& v, const toml::key& ky, T&& opt)
|
||||||
{
|
{
|
||||||
if(!v.is_table()) {return opt;}
|
if(!v.is_table()) {return std::forward<T>(opt);}
|
||||||
auto tab = toml::get<toml::table>(std::move(v));
|
auto tab = toml::get<toml::table>(std::move(v));
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||||
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,9 +642,12 @@ std::string find_or(const toml::value& v, const toml::key& ky, T&& opt)
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// others (require type conversion and return type cannot be lvalue reference)
|
// others (require type conversion and return type cannot be lvalue reference)
|
||||||
template<typename T, typename std::enable_if<detail::conjunction<
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
detail::negation<detail::is_exact_toml_type<T>>,
|
detail::negation<detail::is_exact_toml_type<
|
||||||
detail::negation<std::is_same<T, std::string>>,
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
||||||
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
detail::negation<std::is_same<std::string,
|
||||||
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
||||||
|
detail::negation<detail::is_string_literal<
|
||||||
|
typename std::remove_reference<T>::type>>
|
||||||
>::value, std::nullptr_t>::type = nullptr>
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
T find_or(const toml::value& v, const toml::key& ky, T&& opt)
|
T find_or(const toml::value& v, const toml::key& ky, T&& opt)
|
||||||
{
|
{
|
||||||
@@ -651,8 +657,8 @@ T find_or(const toml::value& v, const toml::key& ky, T&& opt)
|
|||||||
return get_or(tab.at(ky), std::forward<T>(opt));
|
return get_or(tab.at(ky), std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===========================================================================
|
// ---------------------------------------------------------------------------
|
||||||
// find_or(table, key, opt)
|
// toml::find(table)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// exact types (return type can be a reference)
|
// exact types (return type can be a reference)
|
||||||
@@ -700,7 +706,7 @@ template<typename T, typename std::enable_if<
|
|||||||
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
std::is_same<T, std::string>::value, std::nullptr_t>::type = nullptr>
|
||||||
std::string find_or(toml::table&& tab, const toml::key& ky, T&& opt)
|
std::string find_or(toml::table&& tab, const toml::key& ky, T&& opt)
|
||||||
{
|
{
|
||||||
if(tab.count(ky) == 0) {return opt;}
|
if(tab.count(ky) == 0) {return std::forward<T>(opt);}
|
||||||
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
return get_or(std::move(tab[ky]), std::forward<T>(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,9 +724,12 @@ std::string find_or(const toml::table& tab, const toml::key& ky, T&& opt)
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// others (require type conversion and return type cannot be lvalue reference)
|
// others (require type conversion and return type cannot be lvalue reference)
|
||||||
template<typename T, typename std::enable_if<detail::conjunction<
|
template<typename T, typename std::enable_if<detail::conjunction<
|
||||||
detail::negation<detail::is_exact_toml_type<T>>,
|
detail::negation<detail::is_exact_toml_type<
|
||||||
detail::negation<std::is_same<T, std::string>>,
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
||||||
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
detail::negation<std::is_same<std::string,
|
||||||
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type>>,
|
||||||
|
detail::negation<detail::is_string_literal<
|
||||||
|
typename std::remove_reference<T>::type>>
|
||||||
>::value, std::nullptr_t>::type = nullptr>
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
T find_or(const toml::table& tab, const toml::key& ky, T&& opt)
|
T find_or(const toml::table& tab, const toml::key& ky, T&& opt)
|
||||||
{
|
{
|
||||||
|
|||||||
154
toml/parser.hpp
154
toml/parser.hpp
@@ -1410,41 +1410,156 @@ parse_inline_table(location<Container>& loc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
value_t guess_number_type(const location<Container>& l)
|
result<value_t, std::string> guess_number_type(const location<Container>& l)
|
||||||
{
|
{
|
||||||
|
// This function tries to find some (common) mistakes by checking characters
|
||||||
|
// that follows the last character of a value. But it is often difficult
|
||||||
|
// because some non-newline characters can appear after a value. E.g.
|
||||||
|
// spaces, tabs, commas (in an array or inline table), closing brackets
|
||||||
|
// (of an array or inline table), comment-sign (#). Since this function
|
||||||
|
// does not parse further, those characters are always allowed to be there.
|
||||||
location<Container> loc = l;
|
location<Container> loc = l;
|
||||||
|
|
||||||
if(lex_offset_date_time::invoke(loc)) {return value_t::OffsetDatetime;}
|
if(lex_offset_date_time::invoke(loc)) {return ok(value_t::OffsetDatetime);}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
if(lex_local_date_time::invoke(loc)) {return value_t::LocalDatetime;}
|
if(lex_local_date_time::invoke(loc))
|
||||||
|
{
|
||||||
|
// bad offset may appear after this.
|
||||||
|
if(loc.iter() != loc.end() && (*loc.iter() == '+' || *loc.iter() == '-'
|
||||||
|
|| *loc.iter() == 'Z' || *loc.iter() == 'z'))
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad offset: should be [+-]HH:MM or Z",
|
||||||
|
{{std::addressof(loc), "[+-]HH:MM or Z"}},
|
||||||
|
{"pass: +09:00, -05:30", "fail: +9:00, -5:30"}));
|
||||||
|
}
|
||||||
|
return ok(value_t::LocalDatetime);
|
||||||
|
}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
if(lex_local_date::invoke(loc)) {return value_t::LocalDate;}
|
if(lex_local_date::invoke(loc))
|
||||||
|
{
|
||||||
|
// bad time may appear after this.
|
||||||
|
// A space is allowed as a delimiter between local time. But there are
|
||||||
|
// both cases in which a space becomes valid or invalid.
|
||||||
|
// - invalid: 2019-06-16 7:00:00
|
||||||
|
// - valid : 2019-06-16 07:00:00
|
||||||
|
if(loc.iter() != loc.end())
|
||||||
|
{
|
||||||
|
const auto c = *loc.iter();
|
||||||
|
if(c == 'T' || c == 't')
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad time: should be HH:MM:SS.subsec",
|
||||||
|
{{std::addressof(loc), "HH:MM:SS.subsec"}},
|
||||||
|
{"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
|
||||||
|
"fail: 1979-05-27T7:32:00, 1979-05-27 17:32"}));
|
||||||
|
}
|
||||||
|
if('0' <= c && c <= '9')
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad time: missing T",
|
||||||
|
{{std::addressof(loc), "T or space required here"}},
|
||||||
|
{"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
|
||||||
|
"fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
|
||||||
|
}
|
||||||
|
if(c == ' ' && std::next(loc.iter()) != loc.end() &&
|
||||||
|
('0' <= *std::next(loc.iter()) && *std::next(loc.iter())<= '9'))
|
||||||
|
{
|
||||||
|
loc.advance();
|
||||||
|
return err(format_underline("[error] bad time: should be HH:MM:SS.subsec",
|
||||||
|
{{std::addressof(loc), "HH:MM:SS.subsec"}},
|
||||||
|
{"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
|
||||||
|
"fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok(value_t::LocalDate);
|
||||||
|
}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
if(lex_local_time::invoke(loc)) {return value_t::LocalTime;}
|
if(lex_local_time::invoke(loc)) {return ok(value_t::LocalTime);}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
if(lex_float::invoke(loc)) {return value_t::Float;}
|
if(lex_float::invoke(loc))
|
||||||
|
{
|
||||||
|
if(loc.iter() != loc.end() && *loc.iter() == '_')
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad float: `_` should be surrounded by digits",
|
||||||
|
{{std::addressof(loc), "here"}},
|
||||||
|
{"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
|
||||||
|
"fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
|
||||||
|
}
|
||||||
|
return ok(value_t::Float);
|
||||||
|
}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
return value_t::Integer;
|
if(lex_integer::invoke(loc))
|
||||||
|
{
|
||||||
|
if(loc.iter() != loc.end())
|
||||||
|
{
|
||||||
|
const auto c = *loc.iter();
|
||||||
|
if(c == '_')
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad integer: `_` should be surrounded by digits",
|
||||||
|
{{std::addressof(loc), "here"}},
|
||||||
|
{"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
|
||||||
|
"fail: 1__000, 0123"}));
|
||||||
|
}
|
||||||
|
if('0' <= c && c <= '9')
|
||||||
|
{
|
||||||
|
// leading zero. point '0'
|
||||||
|
loc.retrace();
|
||||||
|
return err(format_underline("[error] bad integer: leading zero",
|
||||||
|
{{std::addressof(loc), "here"}},
|
||||||
|
{"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
|
||||||
|
"fail: 1__000, 0123"}));
|
||||||
|
}
|
||||||
|
if(c == ':' || c == '-')
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad datetime: invalid format",
|
||||||
|
{{std::addressof(loc), "here"}},
|
||||||
|
{"pass: 1979-05-27T07:32:00-07:00, 1979-05-27 07:32:00.999999Z",
|
||||||
|
"fail: 1979-05-27T7:32:00-7:00, 1979-05-27 7:32-00:30"}));
|
||||||
|
}
|
||||||
|
if(c == '.' || c == 'e' || c == 'E')
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad float: invalid format",
|
||||||
|
{{std::addressof(loc), "here"}},
|
||||||
|
{"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
|
||||||
|
"fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok(value_t::Integer);
|
||||||
|
}
|
||||||
|
if(loc.iter() != loc.end() && *loc.iter() == '.')
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad float: invalid format",
|
||||||
|
{{std::addressof(loc), "integer part required before this"}},
|
||||||
|
{"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
|
||||||
|
"fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
|
||||||
|
}
|
||||||
|
if(loc.iter() != loc.end() && *loc.iter() == '_')
|
||||||
|
{
|
||||||
|
return err(format_underline("[error] bad number: `_` should be surrounded by digits",
|
||||||
|
{{std::addressof(loc), "`_` is not surrounded by digits"}},
|
||||||
|
{"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
|
||||||
|
"fail: 1__000, 0123"}));
|
||||||
|
}
|
||||||
|
return err(format_underline("[error] bad format: unknown value appeared",
|
||||||
|
{{std::addressof(loc), "here"}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
value_t guess_value_type(const location<Container>& loc)
|
result<value_t, std::string> guess_value_type(const location<Container>& loc)
|
||||||
{
|
{
|
||||||
switch(*loc.iter())
|
switch(*loc.iter())
|
||||||
{
|
{
|
||||||
case '"' : {return value_t::String; }
|
case '"' : {return ok(value_t::String); }
|
||||||
case '\'': {return value_t::String; }
|
case '\'': {return ok(value_t::String); }
|
||||||
case 't' : {return value_t::Boolean;}
|
case 't' : {return ok(value_t::Boolean);}
|
||||||
case 'f' : {return value_t::Boolean;}
|
case 'f' : {return ok(value_t::Boolean);}
|
||||||
case '[' : {return value_t::Array; }
|
case '[' : {return ok(value_t::Array); }
|
||||||
case '{' : {return value_t::Table; }
|
case '{' : {return ok(value_t::Table); }
|
||||||
case 'i' : {return value_t::Float; } // inf.
|
case 'i' : {return ok(value_t::Float); } // inf.
|
||||||
case 'n' : {return value_t::Float; } // nan.
|
case 'n' : {return ok(value_t::Float); } // nan.
|
||||||
default : {return guess_number_type(loc);}
|
default : {return guess_number_type(loc);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1459,7 +1574,12 @@ result<value, std::string> parse_value(location<Container>& loc)
|
|||||||
{{std::addressof(loc), ""}}));
|
{{std::addressof(loc), ""}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(guess_value_type(loc))
|
const auto type = guess_value_type(loc);
|
||||||
|
if(!type)
|
||||||
|
{
|
||||||
|
return err(type.unwrap_err());
|
||||||
|
}
|
||||||
|
switch(type.unwrap())
|
||||||
{
|
{
|
||||||
case value_t::Boolean : {return parse_boolean(loc); }
|
case value_t::Boolean : {return parse_boolean(loc); }
|
||||||
case value_t::Integer : {return parse_integer(loc); }
|
case value_t::Integer : {return parse_integer(loc); }
|
||||||
|
|||||||
@@ -6,6 +6,12 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <string>
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#if __has_include(<string_view>)
|
||||||
|
#include <string_view>
|
||||||
|
#endif // has_include(<string_view>)
|
||||||
|
#endif // cplusplus >= C++17
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
@@ -81,7 +87,6 @@ struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
|
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_from_toml_method
|
struct has_from_toml_method
|
||||||
: decltype(has_from_toml_method_impl::check<T>(nullptr)){};
|
: decltype(has_from_toml_method_impl::check<T>(nullptr)){};
|
||||||
@@ -114,7 +119,7 @@ template<typename T>
|
|||||||
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
|
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// normal type checker
|
// type checkers
|
||||||
|
|
||||||
template<typename T> struct is_std_pair : std::false_type{};
|
template<typename T> struct is_std_pair : std::false_type{};
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
@@ -128,6 +133,33 @@ template<typename T> struct is_chrono_duration: std::false_type{};
|
|||||||
template<typename Rep, typename Period>
|
template<typename Rep, typename Period>
|
||||||
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
|
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_map : conjunction< // map satisfies all the following conditions
|
||||||
|
has_iterator<T>, // has T::iterator
|
||||||
|
has_value_type<T>, // has T::value_type
|
||||||
|
has_key_type<T>, // has T::key_type
|
||||||
|
has_mapped_type<T> // has T::mapped_type
|
||||||
|
>{};
|
||||||
|
template<typename T> struct is_map<T&> : is_map<T>{};
|
||||||
|
template<typename T> struct is_map<T const&> : is_map<T>{};
|
||||||
|
template<typename T> struct is_map<T volatile&> : is_map<T>{};
|
||||||
|
template<typename T> struct is_map<T const volatile&> : is_map<T>{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_container : conjunction<
|
||||||
|
negation<is_map<T>>, // not a map
|
||||||
|
negation<std::is_same<T, std::string>>, // not a std::string
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
negation<std::is_same<T, std::string_view>>, // not a std::string_view
|
||||||
|
#endif
|
||||||
|
has_iterator<T>, // has T::iterator
|
||||||
|
has_value_type<T> // has T::value_type
|
||||||
|
>{};
|
||||||
|
template<typename T> struct is_container<T&> : is_container<T>{};
|
||||||
|
template<typename T> struct is_container<T const&> : is_container<T>{};
|
||||||
|
template<typename T> struct is_container<T volatile&> : is_container<T>{};
|
||||||
|
template<typename T> struct is_container<T const volatile&> : is_container<T>{};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// C++14 index_sequence
|
// C++14 index_sequence
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,6 @@
|
|||||||
#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
|
||||||
{
|
{
|
||||||
@@ -161,34 +156,6 @@ template<typename T> struct is_exact_toml_type<T const&> : is_exact_toml
|
|||||||
template<typename T> struct is_exact_toml_type<T volatile&> : is_exact_toml_type<T>{};
|
template<typename T> struct is_exact_toml_type<T volatile&> : is_exact_toml_type<T>{};
|
||||||
template<typename T> struct is_exact_toml_type<T const volatile&>: is_exact_toml_type<T>{};
|
template<typename T> struct is_exact_toml_type<T const volatile&>: is_exact_toml_type<T>{};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct is_map : conjunction<
|
|
||||||
has_iterator<T>,
|
|
||||||
has_value_type<T>,
|
|
||||||
has_key_type<T>,
|
|
||||||
has_mapped_type<T>
|
|
||||||
>{};
|
|
||||||
template<typename T> struct is_map<T&> : is_map<T>{};
|
|
||||||
template<typename T> struct is_map<T const&> : is_map<T>{};
|
|
||||||
template<typename T> struct is_map<T volatile&> : is_map<T>{};
|
|
||||||
template<typename T> struct is_map<T const volatile&> : is_map<T>{};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct is_container : conjunction<
|
|
||||||
negation<is_map<T>>,
|
|
||||||
negation<std::is_same<T, std::string>>,
|
|
||||||
#if __cplusplus >= 201703L
|
|
||||||
negation<std::is_same<T, std::string_view>>,
|
|
||||||
#endif
|
|
||||||
has_iterator<T>,
|
|
||||||
has_value_type<T>
|
|
||||||
>{};
|
|
||||||
template<typename T> struct is_container<T&> : is_container<T>{};
|
|
||||||
template<typename T> struct is_container<T const&> : is_container<T>{};
|
|
||||||
template<typename T> struct is_container<T volatile&> : is_container<T>{};
|
|
||||||
template<typename T> struct is_container<T const volatile&> : is_container<T>{};
|
|
||||||
|
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // toml
|
} // toml
|
||||||
#endif// TOML11_TYPES_H
|
#endif// TOML11_TYPES_H
|
||||||
|
|||||||
425
toml/value.hpp
425
toml/value.hpp
@@ -27,6 +27,16 @@ namespace detail
|
|||||||
region_base const& get_region(const value&);
|
region_base const& get_region(const value&);
|
||||||
template<typename Region>
|
template<typename Region>
|
||||||
void change_region(value&, Region&&);
|
void change_region(value&, Region&&);
|
||||||
|
|
||||||
|
template<value_t Expected>
|
||||||
|
[[noreturn]] inline void throw_bad_cast(value_t actual, const ::toml::value& v)
|
||||||
|
{
|
||||||
|
throw type_error(detail::format_underline(concat_to_string(
|
||||||
|
"[error] toml::value bad_cast to ", Expected), {
|
||||||
|
{std::addressof(get_region(v)),
|
||||||
|
concat_to_string("the actual type is ", actual)}
|
||||||
|
}));
|
||||||
|
}
|
||||||
}// detail
|
}// detail
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -616,7 +626,7 @@ class value
|
|||||||
bool is_uninitialized() const noexcept {return this->is(value_t::Empty );}
|
bool is_uninitialized() const noexcept {return this->is(value_t::Empty );}
|
||||||
bool is_boolean() const noexcept {return this->is(value_t::Boolean );}
|
bool is_boolean() const noexcept {return this->is(value_t::Boolean );}
|
||||||
bool is_integer() const noexcept {return this->is(value_t::Integer );}
|
bool is_integer() const noexcept {return this->is(value_t::Integer );}
|
||||||
bool is_float() const noexcept {return this->is(value_t::Float );}
|
bool is_floating() const noexcept {return this->is(value_t::Float );}
|
||||||
bool is_string() const noexcept {return this->is(value_t::String );}
|
bool is_string() const noexcept {return this->is(value_t::String );}
|
||||||
bool is_offset_datetime() const noexcept {return this->is(value_t::OffsetDatetime);}
|
bool is_offset_datetime() const noexcept {return this->is(value_t::OffsetDatetime);}
|
||||||
bool is_local_datetime() const noexcept {return this->is(value_t::LocalDatetime );}
|
bool is_local_datetime() const noexcept {return this->is(value_t::LocalDatetime );}
|
||||||
@@ -634,38 +644,353 @@ class value
|
|||||||
template<value_t T>
|
template<value_t T>
|
||||||
typename detail::toml_default_type<T>::type&& cast() &&;
|
typename detail::toml_default_type<T>::type&& cast() &&;
|
||||||
|
|
||||||
boolean const& as_boolean() const& noexcept {return this->boolean_;}
|
// ------------------------------------------------------------------------
|
||||||
integer const& as_integer() const& noexcept {return this->integer_;}
|
// nothrow version
|
||||||
floating const& as_float() const& noexcept {return this->floating_;}
|
|
||||||
string const& as_string() const& noexcept {return this->string_;}
|
|
||||||
offset_datetime const& as_offset_datetime() const& noexcept {return this->offset_datetime_;}
|
|
||||||
local_datetime const& as_local_datetime() const& noexcept {return this->local_datetime_;}
|
|
||||||
local_date const& as_local_date() const& noexcept {return this->local_date_;}
|
|
||||||
local_time const& as_local_time() const& noexcept {return this->local_time_;}
|
|
||||||
array const& as_array() const& noexcept {return this->array_.value();}
|
|
||||||
table const& as_table() const& noexcept {return this->table_.value();}
|
|
||||||
|
|
||||||
boolean & as_boolean() & noexcept {return this->boolean_;}
|
boolean const& as_boolean (const std::nothrow_t&) const& noexcept {return this->boolean_;}
|
||||||
integer & as_integer() & noexcept {return this->integer_;}
|
integer const& as_integer (const std::nothrow_t&) const& noexcept {return this->integer_;}
|
||||||
floating & as_float() & noexcept {return this->floating_;}
|
floating const& as_floating (const std::nothrow_t&) const& noexcept {return this->floating_;}
|
||||||
string & as_string() & noexcept {return this->string_;}
|
string const& as_string (const std::nothrow_t&) const& noexcept {return this->string_;}
|
||||||
offset_datetime& as_offset_datetime() & noexcept {return this->offset_datetime_;}
|
offset_datetime const& as_offset_datetime(const std::nothrow_t&) const& noexcept {return this->offset_datetime_;}
|
||||||
local_datetime & as_local_datetime() & noexcept {return this->local_datetime_;}
|
local_datetime const& as_local_datetime (const std::nothrow_t&) const& noexcept {return this->local_datetime_;}
|
||||||
local_date & as_local_date() & noexcept {return this->local_date_;}
|
local_date const& as_local_date (const std::nothrow_t&) const& noexcept {return this->local_date_;}
|
||||||
local_time & as_local_time() & noexcept {return this->local_time_;}
|
local_time const& as_local_time (const std::nothrow_t&) const& noexcept {return this->local_time_;}
|
||||||
array & as_array() & noexcept {return this->array_.value();}
|
array const& as_array (const std::nothrow_t&) const& noexcept {return this->array_.value();}
|
||||||
table & as_table() & noexcept {return this->table_.value();}
|
table const& as_table (const std::nothrow_t&) const& noexcept {return this->table_.value();}
|
||||||
|
|
||||||
boolean && as_boolean() && noexcept {return std::move(this->boolean_);}
|
boolean & as_boolean (const std::nothrow_t&) & noexcept {return this->boolean_;}
|
||||||
integer && as_integer() && noexcept {return std::move(this->integer_);}
|
integer & as_integer (const std::nothrow_t&) & noexcept {return this->integer_;}
|
||||||
floating && as_float() && noexcept {return std::move(this->floating_);}
|
floating & as_floating (const std::nothrow_t&) & noexcept {return this->floating_;}
|
||||||
string && as_string() && noexcept {return std::move(this->string_);}
|
string & as_string (const std::nothrow_t&) & noexcept {return this->string_;}
|
||||||
offset_datetime&& as_offset_datetime() && noexcept {return std::move(this->offset_datetime_);}
|
offset_datetime& as_offset_datetime(const std::nothrow_t&) & noexcept {return this->offset_datetime_;}
|
||||||
local_datetime && as_local_datetime() && noexcept {return std::move(this->local_datetime_);}
|
local_datetime & as_local_datetime (const std::nothrow_t&) & noexcept {return this->local_datetime_;}
|
||||||
local_date && as_local_date() && noexcept {return std::move(this->local_date_);}
|
local_date & as_local_date (const std::nothrow_t&) & noexcept {return this->local_date_;}
|
||||||
local_time && as_local_time() && noexcept {return std::move(this->local_time_);}
|
local_time & as_local_time (const std::nothrow_t&) & noexcept {return this->local_time_;}
|
||||||
array && as_array() && noexcept {return std::move(this->array_.value());}
|
array & as_array (const std::nothrow_t&) & noexcept {return this->array_.value();}
|
||||||
table && as_table() && noexcept {return std::move(this->table_.value());}
|
table & as_table (const std::nothrow_t&) & noexcept {return this->table_.value();}
|
||||||
|
|
||||||
|
boolean && as_boolean (const std::nothrow_t&) && noexcept {return std::move(this->boolean_);}
|
||||||
|
integer && as_integer (const std::nothrow_t&) && noexcept {return std::move(this->integer_);}
|
||||||
|
floating && as_floating (const std::nothrow_t&) && noexcept {return std::move(this->floating_);}
|
||||||
|
string && as_string (const std::nothrow_t&) && noexcept {return std::move(this->string_);}
|
||||||
|
offset_datetime&& as_offset_datetime(const std::nothrow_t&) && noexcept {return std::move(this->offset_datetime_);}
|
||||||
|
local_datetime && as_local_datetime (const std::nothrow_t&) && noexcept {return std::move(this->local_datetime_);}
|
||||||
|
local_date && as_local_date (const std::nothrow_t&) && noexcept {return std::move(this->local_date_);}
|
||||||
|
local_time && as_local_time (const std::nothrow_t&) && noexcept {return std::move(this->local_time_);}
|
||||||
|
array && as_array (const std::nothrow_t&) && noexcept {return std::move(this->array_.value());}
|
||||||
|
table && as_table (const std::nothrow_t&) && noexcept {return std::move(this->table_.value());}
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// throw version
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// const reference
|
||||||
|
|
||||||
|
boolean const& as_boolean() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Boolean)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Boolean>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->boolean_;
|
||||||
|
}
|
||||||
|
integer const& as_integer() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Integer)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Integer>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->integer_;
|
||||||
|
}
|
||||||
|
floating const& as_floating() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Float)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Float>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->floating_;
|
||||||
|
}
|
||||||
|
string const& as_string() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::String)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::String>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->string_;
|
||||||
|
}
|
||||||
|
offset_datetime const& as_offset_datetime() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::OffsetDatetime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::OffsetDatetime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->offset_datetime_;
|
||||||
|
}
|
||||||
|
local_datetime const& as_local_datetime() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalDatetime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalDatetime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->local_datetime_;
|
||||||
|
}
|
||||||
|
local_date const& as_local_date() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalDate)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalDate>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->local_date_;
|
||||||
|
}
|
||||||
|
local_time const& as_local_time() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalTime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalTime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->local_time_;
|
||||||
|
}
|
||||||
|
array const& as_array() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Array)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Array>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->array_.value();
|
||||||
|
}
|
||||||
|
table const& as_table() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Table)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Table>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->table_.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// nonconst reference
|
||||||
|
|
||||||
|
boolean & as_boolean() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Boolean)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Boolean>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->boolean_;
|
||||||
|
}
|
||||||
|
integer & as_integer() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Integer)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Integer>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->integer_;
|
||||||
|
}
|
||||||
|
floating & as_floating() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Float)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Float>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->floating_;
|
||||||
|
}
|
||||||
|
string & as_string() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::String)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::String>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->string_;
|
||||||
|
}
|
||||||
|
offset_datetime & as_offset_datetime() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::OffsetDatetime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::OffsetDatetime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->offset_datetime_;
|
||||||
|
}
|
||||||
|
local_datetime & as_local_datetime() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalDatetime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalDatetime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->local_datetime_;
|
||||||
|
}
|
||||||
|
local_date & as_local_date() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalDate)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalDate>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->local_date_;
|
||||||
|
}
|
||||||
|
local_time & as_local_time() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalTime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalTime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->local_time_;
|
||||||
|
}
|
||||||
|
array & as_array() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Array)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Array>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->array_.value();
|
||||||
|
}
|
||||||
|
table & as_table() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Table)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Table>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->table_.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// rvalue reference
|
||||||
|
|
||||||
|
boolean && as_boolean() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Boolean)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Boolean>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->boolean_);
|
||||||
|
}
|
||||||
|
integer && as_integer() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Integer)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Integer>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->integer_);
|
||||||
|
}
|
||||||
|
floating && as_floating() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Float)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Float>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->floating_);
|
||||||
|
}
|
||||||
|
string && as_string() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::String)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::String>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->string_);
|
||||||
|
}
|
||||||
|
offset_datetime && as_offset_datetime() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::OffsetDatetime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::OffsetDatetime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->offset_datetime_);
|
||||||
|
}
|
||||||
|
local_datetime && as_local_datetime() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalDatetime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalDatetime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->local_datetime_);
|
||||||
|
}
|
||||||
|
local_date && as_local_date() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalDate)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalDate>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->local_date_);
|
||||||
|
}
|
||||||
|
local_time && as_local_time() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::LocalTime)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::LocalTime>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->local_time_);
|
||||||
|
}
|
||||||
|
array && as_array() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Array)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Array>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->array_.value());
|
||||||
|
}
|
||||||
|
table && as_table() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Table)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Table>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->table_.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// as|is_float (deprecated)
|
||||||
|
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating() instead.")
|
||||||
|
bool is_float() const noexcept {return this->is(value_t::Float);}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// nothrow version
|
||||||
|
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating(std::nothrow) instead.")
|
||||||
|
floating& as_float(const std::nothrow_t&) & noexcept
|
||||||
|
{
|
||||||
|
return this->floating_;
|
||||||
|
}
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating(std::nothrow) instead.")
|
||||||
|
floating&& as_float(const std::nothrow_t&) && noexcept
|
||||||
|
{
|
||||||
|
return std::move(this->floating_);
|
||||||
|
}
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating(std::nothrow) instead.")
|
||||||
|
floating const& as_float(const std::nothrow_t&) const& noexcept
|
||||||
|
{
|
||||||
|
return this->floating_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// throw version
|
||||||
|
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating() instead.")
|
||||||
|
floating& as_float() &
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Float)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Float>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->floating_;
|
||||||
|
}
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating() instead.")
|
||||||
|
floating&& as_float() &&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Float)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Float>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return std::move(this->floating_);
|
||||||
|
}
|
||||||
|
TOML11_MARK_AS_DEPRECATED("use toml::value::is_floating() instead.")
|
||||||
|
floating const& as_float() const&
|
||||||
|
{
|
||||||
|
if(this->type_ != value_t::Float)
|
||||||
|
{
|
||||||
|
detail::throw_bad_cast<value_t::Float>(this->type_, *this);
|
||||||
|
}
|
||||||
|
return this->floating_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
std::string comment() const
|
std::string comment() const
|
||||||
{
|
{
|
||||||
@@ -744,16 +1069,6 @@ void change_region(value& v, Region&& reg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<value_t Expected>
|
|
||||||
[[noreturn]] inline void throw_bad_cast(value_t actual, const ::toml::value& v)
|
|
||||||
{
|
|
||||||
throw type_error(detail::format_underline(concat_to_string(
|
|
||||||
"[error] toml::value bad_cast to ", Expected), {
|
|
||||||
{std::addressof(get_region(v)),
|
|
||||||
concat_to_string("the actual type is ", actual)}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<value_t T>
|
template<value_t T>
|
||||||
struct switch_cast;
|
struct switch_cast;
|
||||||
template<>
|
template<>
|
||||||
@@ -773,9 +1088,9 @@ struct switch_cast<value_t::Integer>
|
|||||||
template<>
|
template<>
|
||||||
struct switch_cast<value_t::Float>
|
struct switch_cast<value_t::Float>
|
||||||
{
|
{
|
||||||
static ::toml::floating& invoke(value& v) {return v.as_float();}
|
static ::toml::floating& invoke(value& v) {return v.as_floating();}
|
||||||
static ::toml::floating const& invoke(value const& v) {return v.as_float();}
|
static ::toml::floating const& invoke(value const& v) {return v.as_floating();}
|
||||||
static ::toml::floating&& invoke(value&& v) {return std::move(v).as_float();}
|
static ::toml::floating&& invoke(value&& v) {return std::move(v).as_floating();}
|
||||||
};
|
};
|
||||||
template<>
|
template<>
|
||||||
struct switch_cast<value_t::String>
|
struct switch_cast<value_t::String>
|
||||||
@@ -856,6 +1171,9 @@ typename detail::toml_default_type<T>::type&& value::cast() &&
|
|||||||
return detail::switch_cast<T>::invoke(std::move(*this));
|
return detail::switch_cast<T>::invoke(std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(const toml::value& lhs, const toml::value& rhs);
|
||||||
|
bool operator< (const toml::value& lhs, const toml::value& rhs);
|
||||||
|
|
||||||
inline bool operator==(const toml::value& lhs, const toml::value& rhs)
|
inline bool operator==(const toml::value& lhs, const toml::value& rhs)
|
||||||
{
|
{
|
||||||
if(lhs.type() != rhs.type()){return false;}
|
if(lhs.type() != rhs.type()){return false;}
|
||||||
@@ -871,7 +1189,7 @@ inline bool operator==(const toml::value& lhs, const toml::value& rhs)
|
|||||||
}
|
}
|
||||||
case value_t::Float :
|
case value_t::Float :
|
||||||
{
|
{
|
||||||
return lhs.as_float() == rhs.as_float();
|
return lhs.as_floating() == rhs.as_floating();
|
||||||
}
|
}
|
||||||
case value_t::String :
|
case value_t::String :
|
||||||
{
|
{
|
||||||
@@ -921,7 +1239,7 @@ inline bool operator<(const toml::value& lhs, const toml::value& rhs)
|
|||||||
}
|
}
|
||||||
case value_t::Float :
|
case value_t::Float :
|
||||||
{
|
{
|
||||||
return lhs.as_float() < rhs.as_float();
|
return lhs.as_floating() < rhs.as_floating();
|
||||||
}
|
}
|
||||||
case value_t::String :
|
case value_t::String :
|
||||||
{
|
{
|
||||||
@@ -949,7 +1267,14 @@ inline bool operator<(const toml::value& lhs, const toml::value& rhs)
|
|||||||
}
|
}
|
||||||
case value_t::Table :
|
case value_t::Table :
|
||||||
{
|
{
|
||||||
return lhs.as_table() < rhs.as_table();
|
// since unordered_map does not have `operator<` ...
|
||||||
|
std::vector<std::pair<toml::key, toml::value>>
|
||||||
|
L(lhs.as_table().begin(), lhs.as_table().end()),
|
||||||
|
R(rhs.as_table().begin(), rhs.as_table().end());
|
||||||
|
std::sort(L.begin(), L.end());
|
||||||
|
std::sort(R.begin(), R.end());
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
L.begin(), L.end(), R.begin(), R.end());
|
||||||
}
|
}
|
||||||
case value_t::Empty : {return false;}
|
case value_t::Empty : {return false;}
|
||||||
case value_t::Unknown : {return false;}
|
case value_t::Unknown : {return false;}
|
||||||
@@ -1018,7 +1343,7 @@ visit(Visitor&& visitor, const toml::value& v)
|
|||||||
{
|
{
|
||||||
case value_t::Boolean : {return visitor(v.as_boolean ());}
|
case value_t::Boolean : {return visitor(v.as_boolean ());}
|
||||||
case value_t::Integer : {return visitor(v.as_integer ());}
|
case value_t::Integer : {return visitor(v.as_integer ());}
|
||||||
case value_t::Float : {return visitor(v.as_float ());}
|
case value_t::Float : {return visitor(v.as_floating ());}
|
||||||
case value_t::String : {return visitor(v.as_string ());}
|
case value_t::String : {return visitor(v.as_string ());}
|
||||||
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
|
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
|
||||||
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
|
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
|
||||||
@@ -1042,7 +1367,7 @@ visit(Visitor&& visitor, toml::value& v)
|
|||||||
{
|
{
|
||||||
case value_t::Boolean : {return visitor(v.as_boolean ());}
|
case value_t::Boolean : {return visitor(v.as_boolean ());}
|
||||||
case value_t::Integer : {return visitor(v.as_integer ());}
|
case value_t::Integer : {return visitor(v.as_integer ());}
|
||||||
case value_t::Float : {return visitor(v.as_float ());}
|
case value_t::Float : {return visitor(v.as_floating ());}
|
||||||
case value_t::String : {return visitor(v.as_string ());}
|
case value_t::String : {return visitor(v.as_string ());}
|
||||||
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
|
case value_t::OffsetDatetime: {return visitor(v.as_offset_datetime());}
|
||||||
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
|
case value_t::LocalDatetime : {return visitor(v.as_local_datetime ());}
|
||||||
@@ -1066,7 +1391,7 @@ visit(Visitor&& visitor, toml::value&& v)
|
|||||||
{
|
{
|
||||||
case value_t::Boolean : {return visitor(std::move(v.as_boolean ()));}
|
case value_t::Boolean : {return visitor(std::move(v.as_boolean ()));}
|
||||||
case value_t::Integer : {return visitor(std::move(v.as_integer ()));}
|
case value_t::Integer : {return visitor(std::move(v.as_integer ()));}
|
||||||
case value_t::Float : {return visitor(std::move(v.as_float ()));}
|
case value_t::Float : {return visitor(std::move(v.as_floating ()));}
|
||||||
case value_t::String : {return visitor(std::move(v.as_string ()));}
|
case value_t::String : {return visitor(std::move(v.as_string ()));}
|
||||||
case value_t::OffsetDatetime: {return visitor(std::move(v.as_offset_datetime()));}
|
case value_t::OffsetDatetime: {return visitor(std::move(v.as_offset_datetime()));}
|
||||||
case value_t::LocalDatetime : {return visitor(std::move(v.as_local_datetime ()));}
|
case value_t::LocalDatetime : {return visitor(std::move(v.as_local_datetime ()));}
|
||||||
|
|||||||
Reference in New Issue
Block a user