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)
|
||||
enable_testing()
|
||||
|
||||
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)
|
||||
if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
@@ -34,5 +44,62 @@ else()
|
||||
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)
|
||||
endif ()
|
||||
|
||||
183
README.md
183
README.md
@@ -144,6 +144,24 @@ terminate called after throwing an instance of 'toml::syntax_error'
|
||||
| ~~~~~~~ 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
|
||||
status is not ideal. If you encounter a weird error message, please let us know
|
||||
and contribute to improve the quality!
|
||||
@@ -425,6 +443,10 @@ toml::integer opt = 42;
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
toml11 provides utility function to find a value from `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.
|
||||
toml11 provides a utility function to find a value from `toml::value` and `toml::table`.
|
||||
|
||||
```cpp
|
||||
const auto data = toml::parse("example.toml");
|
||||
const auto num = toml::find<int>(data, "num", /*for err msg*/"example.toml");
|
||||
const toml::value data = /* ... */;
|
||||
|
||||
// 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
|
||||
terminate called after throwing an instance of 'std::out_of_range'
|
||||
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.
|
||||
When the value does not exist, it throws `std::out_of_range` with an error message.
|
||||
By passing a `toml::value`, it shows an informative error message like the following.
|
||||
|
||||
```console
|
||||
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
|
||||
```
|
||||
|
||||
If it's not a `toml::table`, the same error as "invalid type" would be thrown.
|
||||
|
||||
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`.
|
||||
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`.
|
||||
|
||||
```cpp
|
||||
const auto data = toml::parse("example.toml");
|
||||
const auto num = toml::find_or(data.at("table"), "num", 42);
|
||||
const toml::table data = /* ... */;
|
||||
|
||||
// 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
|
||||
|
||||
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.
|
||||
|
||||
```cpp
|
||||
const toml::value v(/*...*/);
|
||||
v.is_boolean();
|
||||
v.is_integer();
|
||||
v.is_float();
|
||||
v.is_string();
|
||||
v.is_offset_datetime();
|
||||
v.is_local_datetime();
|
||||
v.is_local_date();
|
||||
v.is_local_time();
|
||||
v.is_array();
|
||||
v.is_table();
|
||||
v.is_uninitialized();
|
||||
namespace toml {
|
||||
class value {
|
||||
// ...
|
||||
bool is_boolean() const noexcept;
|
||||
bool is_integer() const noexcept;
|
||||
bool is_floating() const noexcept;
|
||||
bool is_string() const noexcept;
|
||||
bool is_offset_datetime() const noexcept;
|
||||
bool is_local_datetime() const noexcept;
|
||||
bool is_local_date() const noexcept;
|
||||
bool is_local_time() const noexcept;
|
||||
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`.
|
||||
|
||||
```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
|
||||
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();
|
||||
toml::value v = /* ... */;
|
||||
if(v.is_integer() && v.as_integer(std::nothrow) == 42) // never fail
|
||||
{
|
||||
std::cout << "value is 42" << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
- Ivan Shynkarenka (@chronoxor)
|
||||
- Fixed Visual Studio 2019 warnings
|
||||
- @khoitd1997
|
||||
- Fixed warnings while type conversion
|
||||
- @KerstinKeller
|
||||
- Added installation script to CMake
|
||||
|
||||
## 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})
|
||||
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
||||
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
|
||||
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
|
||||
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
||||
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
|
||||
@@ -105,3 +105,4 @@ endforeach(TEST_NAME)
|
||||
add_executable(test_multiple_translation_unit
|
||||
test_multiple_translation_unit_1.cpp
|
||||
test_multiple_translation_unit_2.cpp)
|
||||
target_link_libraries(test_multiple_translation_unit toml11::toml11)
|
||||
|
||||
@@ -78,8 +78,8 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
|
||||
const toml::value v1 = u8"3.1415"_toml;
|
||||
const toml::value v2 = u8"6.02e+23"_toml;
|
||||
|
||||
BOOST_CHECK(v1.is_float());
|
||||
BOOST_CHECK(v2.is_float());
|
||||
BOOST_CHECK(v1.is_floating());
|
||||
BOOST_CHECK(v2.is_floating());
|
||||
BOOST_CHECK_CLOSE(toml::get<double>(v1), 3.1415, 0.00001);
|
||||
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(v1.as_boolean(), true);
|
||||
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;
|
||||
v2 = true;
|
||||
@@ -96,12 +98,12 @@ BOOST_AUTO_TEST_CASE(test_value_boolean)
|
||||
BOOST_CHECK(v1.is<toml::Integer>());
|
||||
BOOST_CHECK(v2.is<toml::Float>());
|
||||
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(v2.cast<toml::value_t::Float>(), 3.14);
|
||||
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)
|
||||
@@ -122,6 +124,8 @@ BOOST_AUTO_TEST_CASE(test_value_integer)
|
||||
BOOST_CHECK_EQUAL(v2.cast<toml::value_t::Integer>(), 42u);
|
||||
BOOST_CHECK_EQUAL(v1.as_integer(), -42);
|
||||
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;
|
||||
v2 = -54;
|
||||
@@ -205,13 +209,15 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
||||
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||
BOOST_CHECK(v1.is<toml::Float>());
|
||||
BOOST_CHECK(v2.is<toml::Float>());
|
||||
BOOST_CHECK(v1.is_float());
|
||||
BOOST_CHECK(v2.is_float());
|
||||
BOOST_CHECK(v1.is_floating());
|
||||
BOOST_CHECK(v2.is_floating());
|
||||
|
||||
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_EQUAL (v1.as_float(), 3.14);
|
||||
BOOST_CHECK_CLOSE_FRACTION(v2.as_float(), 3.14, 1e-2);
|
||||
BOOST_CHECK_EQUAL (v1.as_floating(), 3.14);
|
||||
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;
|
||||
v2 = 2.718;
|
||||
@@ -222,13 +228,13 @@ BOOST_AUTO_TEST_CASE(test_value_float)
|
||||
BOOST_CHECK(v2.is(toml::value_t::Float));
|
||||
BOOST_CHECK(v1.is<toml::Float>());
|
||||
BOOST_CHECK(v2.is<toml::Float>());
|
||||
BOOST_CHECK(v1.is_float());
|
||||
BOOST_CHECK(v2.is_float());
|
||||
BOOST_CHECK(v1.is_floating());
|
||||
BOOST_CHECK(v2.is_floating());
|
||||
|
||||
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_CLOSE_FRACTION(v1.as_float(), 2.718, 1e-3);
|
||||
BOOST_CHECK_EQUAL (v2.as_float(), 2.718);
|
||||
BOOST_CHECK_CLOSE_FRACTION(v1.as_floating(), 2.718, 1e-3);
|
||||
BOOST_CHECK_EQUAL (v2.as_floating(), 2.718);
|
||||
|
||||
toml::value v3(v1);
|
||||
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(v3.is<toml::Float>());
|
||||
BOOST_CHECK(v4.is<toml::Float>());
|
||||
BOOST_CHECK(v3.is_float());
|
||||
BOOST_CHECK(v4.is_float());
|
||||
BOOST_CHECK(v3.is_floating());
|
||||
BOOST_CHECK(v4.is_floating());
|
||||
|
||||
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_CLOSE_FRACTION(v3.as_float(), 2.718, 1e-3);
|
||||
BOOST_CHECK_EQUAL (v4.as_float(), 2.718);
|
||||
BOOST_CHECK_CLOSE_FRACTION(v3.as_floating(), 2.718, 1e-3);
|
||||
BOOST_CHECK_EQUAL (v4.as_floating(), 2.718);
|
||||
|
||||
toml::value v5(std::move(v1));
|
||||
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(v5.is<toml::Float>());
|
||||
BOOST_CHECK(v6.is<toml::Float>());
|
||||
BOOST_CHECK(v5.is_float());
|
||||
BOOST_CHECK(v6.is_float());
|
||||
BOOST_CHECK(v5.is_floating());
|
||||
BOOST_CHECK(v6.is_floating());
|
||||
|
||||
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_CLOSE_FRACTION(v5.as_float(), 2.718, 1e-3);
|
||||
BOOST_CHECK_EQUAL (v6.as_float(), 2.718);
|
||||
BOOST_CHECK_CLOSE_FRACTION(v5.as_floating(), 2.718, 1e-3);
|
||||
BOOST_CHECK_EQUAL (v6.as_floating(), 2.718);
|
||||
|
||||
v1 = true;
|
||||
v2 = false;
|
||||
@@ -309,7 +315,9 @@ BOOST_AUTO_TEST_CASE(test_value_string)
|
||||
BOOST_CHECK_EQUAL(v1.as_string(), "foo");
|
||||
BOOST_CHECK_EQUAL(v2.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";
|
||||
v2 = "bar";
|
||||
@@ -439,6 +447,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_date)
|
||||
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));
|
||||
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);
|
||||
|
||||
@@ -503,6 +513,8 @@ BOOST_AUTO_TEST_CASE(test_value_local_time)
|
||||
v2.cast<toml::value_t::LocalTime>());
|
||||
BOOST_CHECK_EQUAL(v1.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);
|
||||
|
||||
@@ -557,6 +569,11 @@ BOOST_AUTO_TEST_CASE(test_value_local_datetime)
|
||||
toml::local_datetime(
|
||||
toml::local_date(2018, toml::month_t::Jan, 31),
|
||||
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(
|
||||
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::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(
|
||||
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(3).as_integer(), 4);
|
||||
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(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("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("bar").as_floating(), 3.14);
|
||||
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"}};
|
||||
@@ -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("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.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("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("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.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("baz").as_string().str, "quux");
|
||||
|
||||
@@ -841,4 +872,15 @@ BOOST_AUTO_TEST_CASE(test_value_empty)
|
||||
toml::value v1;
|
||||
BOOST_CHECK(v1.is_uninitialized());
|
||||
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');
|
||||
const auto r = std::snprintf(
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
41
toml/get.hpp
41
toml/get.hpp
@@ -519,7 +519,7 @@ std::string get_or(toml::value&& v, T&& opt)
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return opt;
|
||||
return std::forward<T>(opt);
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>,
|
||||
detail::negation<std::is_same<T, std::string>>,
|
||||
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
||||
detail::negation<detail::is_exact_toml_type<
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::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>
|
||||
T get_or(const toml::value& v, T&& opt)
|
||||
{
|
||||
@@ -554,7 +557,7 @@ T get_or(const toml::value& v, T&& opt)
|
||||
}
|
||||
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::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));
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>,
|
||||
detail::negation<std::is_same<T, std::string>>,
|
||||
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
||||
detail::negation<detail::is_exact_toml_type<
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::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>
|
||||
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));
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// find_or(table, key, opt)
|
||||
// ---------------------------------------------------------------------------
|
||||
// toml::find(table)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 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::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));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>,
|
||||
detail::negation<std::is_same<T, std::string>>,
|
||||
detail::negation<detail::is_string_literal<typename std::remove_reference<T>::type>>
|
||||
detail::negation<detail::is_exact_toml_type<
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::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>
|
||||
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>
|
||||
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;
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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>
|
||||
value_t guess_value_type(const location<Container>& loc)
|
||||
result<value_t, std::string> 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.
|
||||
case '"' : {return ok(value_t::String); }
|
||||
case '\'': {return ok(value_t::String); }
|
||||
case 't' : {return ok(value_t::Boolean);}
|
||||
case 'f' : {return ok(value_t::Boolean);}
|
||||
case '[' : {return ok(value_t::Array); }
|
||||
case '{' : {return ok(value_t::Table); }
|
||||
case 'i' : {return ok(value_t::Float); } // inf.
|
||||
case 'n' : {return ok(value_t::Float); } // nan.
|
||||
default : {return guess_number_type(loc);}
|
||||
}
|
||||
}
|
||||
@@ -1459,7 +1574,12 @@ result<value, std::string> parse_value(location<Container>& 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::Integer : {return parse_integer(loc); }
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
#include <utility>
|
||||
#include <chrono>
|
||||
#include <tuple>
|
||||
#include <string>
|
||||
#if __cplusplus >= 201703L
|
||||
#if __has_include(<string_view>)
|
||||
#include <string_view>
|
||||
#endif // has_include(<string_view>)
|
||||
#endif // cplusplus >= C++17
|
||||
|
||||
namespace toml
|
||||
{
|
||||
@@ -81,7 +87,6 @@ struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
|
||||
template<typename T>
|
||||
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct has_from_toml_method
|
||||
: 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)>{};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// normal type checker
|
||||
// type checkers
|
||||
|
||||
template<typename T> struct is_std_pair : std::false_type{};
|
||||
template<typename T1, typename T2>
|
||||
@@ -128,6 +133,33 @@ template<typename T> struct is_chrono_duration: std::false_type{};
|
||||
template<typename Rep, typename Period>
|
||||
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
|
||||
|
||||
template<typename T>
|
||||
struct is_map : conjunction< // map satisfies all the following conditions
|
||||
has_iterator<T>, // has T::iterator
|
||||
has_value_type<T>, // has T::value_type
|
||||
has_key_type<T>, // has T::key_type
|
||||
has_mapped_type<T> // has T::mapped_type
|
||||
>{};
|
||||
template<typename T> struct is_map<T&> : is_map<T>{};
|
||||
template<typename T> struct is_map<T const&> : is_map<T>{};
|
||||
template<typename T> struct is_map<T volatile&> : is_map<T>{};
|
||||
template<typename T> struct is_map<T const volatile&> : is_map<T>{};
|
||||
|
||||
template<typename T>
|
||||
struct is_container : conjunction<
|
||||
negation<is_map<T>>, // not a map
|
||||
negation<std::is_same<T, std::string>>, // not a std::string
|
||||
#if __cplusplus >= 201703L
|
||||
negation<std::is_same<T, std::string_view>>, // not a std::string_view
|
||||
#endif
|
||||
has_iterator<T>, // has T::iterator
|
||||
has_value_type<T> // has T::value_type
|
||||
>{};
|
||||
template<typename T> struct is_container<T&> : is_container<T>{};
|
||||
template<typename T> struct is_container<T const&> : is_container<T>{};
|
||||
template<typename T> struct is_container<T volatile&> : is_container<T>{};
|
||||
template<typename T> struct is_container<T const volatile&> : is_container<T>{};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// C++14 index_sequence
|
||||
|
||||
|
||||
@@ -7,11 +7,6 @@
|
||||
#include "traits.hpp"
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#if __cplusplus >= 201703L
|
||||
#if __has_include(<string_view>)
|
||||
#include <string_view>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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 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
|
||||
} // toml
|
||||
#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&);
|
||||
template<typename 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
|
||||
|
||||
template<typename T>
|
||||
@@ -616,7 +626,7 @@ class value
|
||||
bool is_uninitialized() const noexcept {return this->is(value_t::Empty );}
|
||||
bool is_boolean() const noexcept {return this->is(value_t::Boolean );}
|
||||
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_offset_datetime() const noexcept {return this->is(value_t::OffsetDatetime);}
|
||||
bool is_local_datetime() const noexcept {return this->is(value_t::LocalDatetime );}
|
||||
@@ -634,38 +644,353 @@ class value
|
||||
template<value_t T>
|
||||
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_;}
|
||||
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();}
|
||||
// ------------------------------------------------------------------------
|
||||
// nothrow version
|
||||
|
||||
boolean & as_boolean() & noexcept {return this->boolean_;}
|
||||
integer & as_integer() & noexcept {return this->integer_;}
|
||||
floating & as_float() & noexcept {return this->floating_;}
|
||||
string & as_string() & noexcept {return this->string_;}
|
||||
offset_datetime& as_offset_datetime() & noexcept {return this->offset_datetime_;}
|
||||
local_datetime & as_local_datetime() & noexcept {return this->local_datetime_;}
|
||||
local_date & as_local_date() & noexcept {return this->local_date_;}
|
||||
local_time & as_local_time() & noexcept {return this->local_time_;}
|
||||
array & as_array() & noexcept {return this->array_.value();}
|
||||
table & as_table() & noexcept {return this->table_.value();}
|
||||
boolean const& as_boolean (const std::nothrow_t&) const& noexcept {return this->boolean_;}
|
||||
integer const& as_integer (const std::nothrow_t&) const& noexcept {return this->integer_;}
|
||||
floating const& as_floating (const std::nothrow_t&) const& noexcept {return this->floating_;}
|
||||
string const& as_string (const std::nothrow_t&) const& noexcept {return this->string_;}
|
||||
offset_datetime const& as_offset_datetime(const std::nothrow_t&) const& noexcept {return this->offset_datetime_;}
|
||||
local_datetime const& as_local_datetime (const std::nothrow_t&) const& noexcept {return this->local_datetime_;}
|
||||
local_date const& as_local_date (const std::nothrow_t&) const& noexcept {return this->local_date_;}
|
||||
local_time const& as_local_time (const std::nothrow_t&) const& noexcept {return this->local_time_;}
|
||||
array const& as_array (const std::nothrow_t&) const& noexcept {return this->array_.value();}
|
||||
table const& as_table (const std::nothrow_t&) const& noexcept {return this->table_.value();}
|
||||
|
||||
boolean && as_boolean() && noexcept {return std::move(this->boolean_);}
|
||||
integer && as_integer() && noexcept {return std::move(this->integer_);}
|
||||
floating && as_float() && noexcept {return std::move(this->floating_);}
|
||||
string && as_string() && noexcept {return std::move(this->string_);}
|
||||
offset_datetime&& as_offset_datetime() && noexcept {return std::move(this->offset_datetime_);}
|
||||
local_datetime && as_local_datetime() && noexcept {return std::move(this->local_datetime_);}
|
||||
local_date && as_local_date() && noexcept {return std::move(this->local_date_);}
|
||||
local_time && as_local_time() && noexcept {return std::move(this->local_time_);}
|
||||
array && as_array() && noexcept {return std::move(this->array_.value());}
|
||||
table && as_table() && noexcept {return std::move(this->table_.value());}
|
||||
boolean & as_boolean (const std::nothrow_t&) & noexcept {return this->boolean_;}
|
||||
integer & as_integer (const std::nothrow_t&) & noexcept {return this->integer_;}
|
||||
floating & as_floating (const std::nothrow_t&) & noexcept {return this->floating_;}
|
||||
string & as_string (const std::nothrow_t&) & noexcept {return this->string_;}
|
||||
offset_datetime& as_offset_datetime(const std::nothrow_t&) & noexcept {return this->offset_datetime_;}
|
||||
local_datetime & as_local_datetime (const std::nothrow_t&) & noexcept {return this->local_datetime_;}
|
||||
local_date & as_local_date (const std::nothrow_t&) & noexcept {return this->local_date_;}
|
||||
local_time & as_local_time (const std::nothrow_t&) & noexcept {return this->local_time_;}
|
||||
array & as_array (const std::nothrow_t&) & noexcept {return this->array_.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
|
||||
{
|
||||
@@ -744,16 +1069,6 @@ void change_region(value& v, Region&& reg)
|
||||
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>
|
||||
struct switch_cast;
|
||||
template<>
|
||||
@@ -773,9 +1088,9 @@ struct switch_cast<value_t::Integer>
|
||||
template<>
|
||||
struct switch_cast<value_t::Float>
|
||||
{
|
||||
static ::toml::floating& invoke(value& v) {return v.as_float();}
|
||||
static ::toml::floating const& invoke(value const& v) {return v.as_float();}
|
||||
static ::toml::floating&& invoke(value&& v) {return std::move(v).as_float();}
|
||||
static ::toml::floating& invoke(value& v) {return v.as_floating();}
|
||||
static ::toml::floating const& invoke(value const& v) {return v.as_floating();}
|
||||
static ::toml::floating&& invoke(value&& v) {return std::move(v).as_floating();}
|
||||
};
|
||||
template<>
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 :
|
||||
{
|
||||
return lhs.as_float() == rhs.as_float();
|
||||
return lhs.as_floating() == rhs.as_floating();
|
||||
}
|
||||
case value_t::String :
|
||||
{
|
||||
@@ -921,7 +1239,7 @@ inline bool operator<(const toml::value& lhs, const toml::value& rhs)
|
||||
}
|
||||
case value_t::Float :
|
||||
{
|
||||
return lhs.as_float() < rhs.as_float();
|
||||
return lhs.as_floating() < rhs.as_floating();
|
||||
}
|
||||
case value_t::String :
|
||||
{
|
||||
@@ -949,7 +1267,14 @@ inline bool operator<(const toml::value& lhs, const toml::value& rhs)
|
||||
}
|
||||
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::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::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::OffsetDatetime: {return visitor(v.as_offset_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::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::OffsetDatetime: {return visitor(v.as_offset_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::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::OffsetDatetime: {return visitor(std::move(v.as_offset_datetime()));}
|
||||
case value_t::LocalDatetime : {return visitor(std::move(v.as_local_datetime ()));}
|
||||
|
||||
Reference in New Issue
Block a user