mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc562ae5cb | ||
|
|
83f37a18b1 | ||
|
|
dc7e443be4 | ||
|
|
59921c1eb7 | ||
|
|
a4d0189df3 | ||
|
|
3320d25abb | ||
|
|
8efb305e8b | ||
|
|
2baa47ef3d | ||
|
|
a0ae1a6bfd | ||
|
|
044a66210d | ||
|
|
c4fb41b812 | ||
|
|
a610e75df0 | ||
|
|
0e84d0591b |
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
sudo apt-get install clang-${{ matrix.compiler }}
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -B build/ -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
cmake -B build/ -DCMAKE_VERBOSE_MAKEFILE=1 -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build/
|
||||
|
||||
@@ -14,13 +14,11 @@ string(REGEX REPLACE "#define TOML11_VERSION_PATCH ([0-9]+)" "\\1" TOML11_VERSIO
|
||||
|
||||
project(toml11 LANGUAGES CXX VERSION "${TOML11_VERSION_MAJOR}.${TOML11_VERSION_MINOR}.${TOML11_VERSION_PATCH}")
|
||||
|
||||
include(CTest) # to use ${BUILD_TESTING}
|
||||
include(CMakeDependentOption)
|
||||
include(CTest)
|
||||
|
||||
option(TOML11_PRECOMPILE "precompile toml11 library" OFF)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(SET CMP0127 OLD) # syntax of condition changed in 3.22
|
||||
cmake_dependent_option(TOML11_INSTALL "install toml11 library" ON
|
||||
"${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}" OFF)
|
||||
cmake_dependent_option(TOML11_BUILD_EXAMPLES "build toml11 examples" OFF
|
||||
@@ -29,8 +27,6 @@ cmake_dependent_option(TOML11_BUILD_TESTS "build toml11 unit tests" OFF
|
||||
"${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}; ${BUILD_TESTING}" OFF)
|
||||
cmake_dependent_option(TOML11_BUILD_TOML_TESTS "build toml11 toml-test encoder & decoder" OFF
|
||||
"${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}" OFF)
|
||||
cmake_policy(POP)
|
||||
|
||||
cmake_dependent_option(TOML11_TEST_WITH_ASAN "build toml11 unit tests with asan" OFF
|
||||
"${TOML11_BUILD_TESTS}" OFF)
|
||||
cmake_dependent_option(TOML11_TEST_WITH_UBSAN "build toml11 unit tests with ubsan" OFF
|
||||
@@ -40,22 +36,8 @@ if(${TOML11_TEST_WITH_ASAN} AND ${TOML11_TEST_WITH_UBSAN})
|
||||
message(FATAL_ERROR "trying to build tests with BOTH asan and ubsan")
|
||||
endif()
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag("-Wall" TOML11_COMPILER_SUPPORTS_WALL)
|
||||
check_cxx_compiler_flag("-Wextra" TOML11_COMPILER_SUPPORTS_WEXTRA)
|
||||
check_cxx_compiler_flag("-Wpedantic" TOML11_COMPILER_SUPPORTS_WPEDANTIC)
|
||||
check_cxx_compiler_flag("-Werror" TOML11_COMPILER_SUPPORTS_WERROR)
|
||||
check_cxx_compiler_flag("-Wsign-conversion" TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION)
|
||||
check_cxx_compiler_flag("-Wconversion" TOML11_COMPILER_SUPPORTS_WCONVERSION)
|
||||
check_cxx_compiler_flag("-Wduplicated-cond" TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND)
|
||||
check_cxx_compiler_flag("-Wduplicated-branches" TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
|
||||
check_cxx_compiler_flag("-Wlogical-op" TOML11_COMPILER_SUPPORTS_WLOGICAL_OP)
|
||||
check_cxx_compiler_flag("-Wdouble-promotion" TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
|
||||
check_cxx_compiler_flag("-Wrange-loop-analysis" TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS)
|
||||
check_cxx_compiler_flag("-Wundef" TOML11_COMPILER_SUPPORTS_WUNDEF)
|
||||
check_cxx_compiler_flag("-Wshadow" TOML11_COMPILER_SUPPORTS_WSHADOW)
|
||||
|
||||
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)
|
||||
|
||||
185
README.md
185
README.md
@@ -8,7 +8,7 @@
|
||||
|
||||
[日本語版](https://github.com/ToruNiina/toml11/blob/main/README_ja.md)
|
||||
|
||||
toml11 is a feature-rich TOML language library for C++11/14/17/20.
|
||||
toml11 is a feature-rich TOML language library for C++.
|
||||
|
||||
- It complies with [the latest TOML language specification](https://toml.io/en/v1.0.0).
|
||||
- It passes all the standard TOML language [test cases](https://github.com/toml-lang/toml-test).
|
||||
@@ -100,23 +100,6 @@ Copy `single_include/toml.hpp` to your preferred location and add it to your inc
|
||||
By adding toml11 as a subdirectory using `git submodule` (or any other way),
|
||||
you can either add `toml11/include` to your include path or use `add_subdirectory(toml11)` in your CMake project.
|
||||
|
||||
### CMake `FetchContent`
|
||||
|
||||
Using `FetchContent`, you can automatically download it.
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
toml11
|
||||
GIT_REPOSITORY https://github.com/ToruNiina/toml11.git
|
||||
GIT_TAG v4.0.3
|
||||
)
|
||||
FetchContent_MakeAvailable(toml11)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main PRIVATE toml11::toml11)
|
||||
```
|
||||
|
||||
### Install Using CMake
|
||||
|
||||
You can install toml11 using CMake with the following steps:
|
||||
@@ -141,14 +124,6 @@ $ cmake -B ./build/ -DTOML11_PRECOMPILE=ON -DCMAKE_CXX_STANDARD=11/14/17/20
|
||||
$ cmake --build ./build/
|
||||
```
|
||||
|
||||
When linking the library, use `target_link_libraries` in CMake
|
||||
|
||||
```cmake
|
||||
target_link_libraries(your_target PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
or pass `-DTOML11_COMPILE_SOURCES` to the compiler.
|
||||
|
||||
### Building Example
|
||||
|
||||
To compile the examples in the `examples/` directory, set `-DTOML11_BUILD_EXAMPLES=ON`.
|
||||
@@ -192,30 +167,8 @@ To parse a string directly, use `toml::parse_str`.
|
||||
const toml::value input = toml::parse_str("a = 42");
|
||||
```
|
||||
|
||||
When parsing string literals, you can use the `""_toml` literal.
|
||||
|
||||
```cpp
|
||||
using namespace toml::literals::toml_literals;
|
||||
const toml::value lit = "a = 42"_toml;
|
||||
```
|
||||
|
||||
`toml::parse`, `parse_str` and `_toml` literal throw a `toml::syntax_error` exception in case of a syntax error.
|
||||
|
||||
The error message obtained with `what()` will look like this:
|
||||
|
||||
```
|
||||
[error] bad integer: `_` must be surrounded by digits
|
||||
--> internal string at line 64 in file main.cpp
|
||||
|
|
||||
1 | a = 123__456
|
||||
| ^-- invalid underscore
|
||||
Hint: valid : -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755
|
||||
Hint: invalid: _42, 1__000, 0123
|
||||
```
|
||||
|
||||
Error messages can also be colorized by calling `toml::color::enable()`.
|
||||
|
||||
By using `toml::try_parse`, you can receive a `toml::result<toml::value, std::vector<toml::error_info>>` without throwing exceptions.
|
||||
`toml::parse` throws a `toml::syntax_error` exception on syntax errors.
|
||||
To avoid this, use `toml::try_parse`, which returns a `toml::result`.
|
||||
|
||||
```cpp
|
||||
const auto input = toml::try_parse("input.toml");
|
||||
@@ -266,40 +219,6 @@ const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find<int>(input, "a") << std::endl;
|
||||
```
|
||||
|
||||
If type conversion or value lookup fails, a `toml::type_error` is thrown. The error message will look like this:
|
||||
|
||||
```
|
||||
[error] toml::value::as_string(): bad_cast to string
|
||||
--> input.toml
|
||||
|
|
||||
1 | a = 123_456
|
||||
| ^^^^^^^-- the actual type is integer
|
||||
```
|
||||
|
||||
You can access nested tables or arrays of tables in the same way.
|
||||
|
||||
```cpp
|
||||
// [a]
|
||||
// b = [
|
||||
// {c = 42},
|
||||
// {c = 54}
|
||||
// ]
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find<int>(input, "a", "b", 1, "c") << std::endl;
|
||||
```
|
||||
|
||||
Most STL containers and those with similar interfaces can be converted.
|
||||
|
||||
```cpp
|
||||
// array = [3,1,4,1,5]
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
|
||||
const auto a1 = toml::find<std::vector<int>>(input, "array");
|
||||
const auto a2 = toml::find<std::array<int, 5>>(input, "array");
|
||||
const auto a3 = toml::find<std::deque<int>>(input, "array");
|
||||
const auto a4 = toml::find<boost::container::small_vector<int, 8>>(input, "array");
|
||||
```
|
||||
|
||||
You can perform advanced type conversions on complex TOML values.
|
||||
|
||||
```toml
|
||||
@@ -318,36 +237,6 @@ const auto mixed = toml::find<
|
||||
>(input, "mixed_array") << std::endl;
|
||||
```
|
||||
|
||||
User-defined types can also be converted by using macros or defining some specific functions.
|
||||
|
||||
```cpp
|
||||
namespace extlib
|
||||
{
|
||||
struct foo
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
} // extlib
|
||||
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib::foo, a, b)
|
||||
|
||||
// ...
|
||||
|
||||
const auto input = R"(
|
||||
[foo]
|
||||
a = 42
|
||||
b = "bar"
|
||||
)"_toml;
|
||||
const extlib::foo f = toml::find<extlib::foo>(input, "foo");
|
||||
```
|
||||
|
||||
Using `toml::find_or`, you can get a default value in case of failure.
|
||||
|
||||
```cpp
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find_or(input, "a", 6*9) << std::endl;
|
||||
```
|
||||
|
||||
For more details, please refer to the [documentation](https://toruniina.github.io/toml11/docs/features/value/).
|
||||
|
||||
### comments
|
||||
@@ -434,72 +323,19 @@ std::cout << toml::format(input) << std::endl;
|
||||
```cpp
|
||||
toml::value output(toml::table{ {"a", 0xDEADBEEF} });
|
||||
output.at("a").as_integer_fmt().fmt = toml::integer_format::hex;
|
||||
output.at("a").as_integer_fmt().spacer = 4; // position of `_`
|
||||
output.at("a").as_integer_fmt().spacer = 4;
|
||||
|
||||
std::cout << toml::format(input) << std::endl;
|
||||
// a = 0xdead_beef
|
||||
```
|
||||
|
||||
You can also specify the formatting for tables and arrays.
|
||||
|
||||
```cpp
|
||||
toml::value output(toml::table{
|
||||
{"array-of-tables", toml::array{}},
|
||||
{"subtable", toml::table{}},
|
||||
});
|
||||
|
||||
auto& aot = output.at("array-of-tables");
|
||||
aot.as_array_fmt().fmt = toml::array_format::multiline; // one element per line
|
||||
aot.as_array_fmt().body_indent = 4;
|
||||
aot.as_array_fmt().closing_indent = 2;
|
||||
|
||||
toml::value v1(toml::table{ {"a", 42}, {"b", 3.14} });
|
||||
v1.as_table_fmt().fmt = toml::table_format::oneline;
|
||||
aot.push_back(std::move(v1));
|
||||
|
||||
toml::value v2(toml::table{ {"a", 42}, {"b", 3.14} });
|
||||
v2.as_table_fmt().fmt = toml::table_format::oneline;
|
||||
aot.push_back(std::move(v2));
|
||||
|
||||
output.at("subtable").as_table_fmt().fmt = toml::table_format::dotted;
|
||||
output.at("subtable")["a"] = 42;
|
||||
output.at("subtable")["b"] = 3.14;
|
||||
|
||||
std::cout << toml::format(output) << std::endl;
|
||||
// subtable.b = 3.14
|
||||
// subtable.a = 42
|
||||
// array-of-tables = [
|
||||
// {b = 3.14, a = 42},
|
||||
// {b = 3.14, a = 42},
|
||||
// ]
|
||||
```
|
||||
|
||||
These settings are read during parsing and will be maintained as long as the value type does not change when modified.
|
||||
|
||||
For details on possible formatting specifications, please refer to the [documentation](https://toruniina.github.io/toml11/docs/features/serialize/).
|
||||
|
||||
### Configuring Types
|
||||
### configuring types
|
||||
|
||||
Many types held by `toml::value`, such as `integer_type` and `array_type`, can be modified by changing the `type_config` type.
|
||||
[The examples directory](https://github.com/ToruNiina/toml11/tree/main/examples) provides usage examples, such as using
|
||||
arbitrary-precision integers, normalizing Unicode, and integrating with an external reflection library.
|
||||
|
||||
Refer to the [`examples` directory](https://github.com/ToruNiina/toml11/tree/main/examples) for complex use cases such as using multi-precision integers, changing containers, and normalizing Unicode.
|
||||
|
||||
Use these examples as references for implementing such configurations.
|
||||
|
||||
## Examples
|
||||
|
||||
The [`examples`](https://github.com/ToruNiina/toml11/tree/main/examples) directory provides various implementation examples in addition to type configurations.
|
||||
|
||||
- [boost_container](https://github.com/ToruNiina/toml11/tree/main/examples/boost_container)
|
||||
- This example shows how to use `boost::container` containers for `array_type` and `table_type`.
|
||||
- [boost_multiprecision](https://github.com/ToruNiina/toml11/tree/main/examples/boost_multiprecision)
|
||||
- This example demonstrates the use of `boost::multiprecision` multi-precision numeric types for `integer_type` and `floating_type`.
|
||||
- [parse_file](https://github.com/ToruNiina/toml11/tree/main/examples/parse_file)
|
||||
- This example includes type conversion implementations, covering slightly more complex cases. The corresponding TOML file is included.
|
||||
- [reflect](https://github.com/ToruNiina/toml11/tree/main/examples/reflect)
|
||||
- This example shows self-type conversion using boost-ext/reflect for user-defined types.
|
||||
- [unicode](https://github.com/ToruNiina/toml11/tree/main/examples/unicode)
|
||||
- This example demonstrates normalizing Unicode strings when searching for keys using uni-algo.
|
||||
Please refer to these examples for implementation guidance in such scenarios.
|
||||
|
||||
## Changes from v3
|
||||
|
||||
@@ -623,11 +459,6 @@ I appreciate the help of the contributors who introduced the great feature to th
|
||||
- Add fuzzing test based on ClusterFuzzLite
|
||||
- Esonhugh Skyworship (@Esonhugh)
|
||||
- Fix function signature of `strerror_r` on macos
|
||||
- Alberto (@0X1A)
|
||||
- Fix issues with CMake package configuration when used with vcpkg
|
||||
- Egor Pugin (@egorpugin)
|
||||
- Fix incorrect operator<<() argument type that gives build error
|
||||
|
||||
|
||||
## Licensing terms
|
||||
|
||||
|
||||
189
README_ja.md
189
README_ja.md
@@ -5,7 +5,7 @@
|
||||
[](LICENSE)
|
||||
[](https://doi.org/10.5281/zenodo.1209136)
|
||||
|
||||
toml11は、C++11,14,17,20のための豊富な機能を持つTOML言語ライブラリです。
|
||||
toml11は、C++のための豊富な機能を持つTOML言語ライブラリです。
|
||||
|
||||
- [TOML言語の最新規格](https://toml.io/ja/v1.0.0)に準拠しています。
|
||||
- TOML言語標準のテストケースすべてにパスしています。
|
||||
@@ -97,23 +97,6 @@ toml11を使うには複数の方法があります。
|
||||
git submoduleなどでサブディレクトリにすれば、`toml11/include`にインクルードパスを通すか、
|
||||
`add_subdirectory(toml11)` とすることで使用できます。
|
||||
|
||||
### CMake `FetchContent`
|
||||
|
||||
CMakeの `FetchContent`を使用することで、`build`ディレクトリに自動でダウンロードすることができます。
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
toml11
|
||||
GIT_REPOSITORY https://github.com/ToruNiina/toml11.git
|
||||
GIT_TAG v4.0.3
|
||||
)
|
||||
FetchContent_MakeAvailable(toml11)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main PRIVATE toml11::toml11)
|
||||
```
|
||||
|
||||
### Install using CMake
|
||||
|
||||
以下の手順で、CMakeを使ってインストールすることができます。
|
||||
@@ -139,14 +122,6 @@ $ cmake -B ./build/ -DTOML11_PRECOMPILE=ON -DCMAKE_CXX_STANDARD=11/14/17/20
|
||||
$ cmake --build ./build/
|
||||
```
|
||||
|
||||
ライブラリをリンクする場合は、CMakeで
|
||||
|
||||
```cmake
|
||||
target_link_libraries(your_target PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
とするか、コンパイラに`-DTOML11_COMPILE_SOURCES`を渡してください。
|
||||
|
||||
### Building example
|
||||
|
||||
`-DTOML11_BUILD_EXAMPLES=ON`とすることで、`examples/`をコンパイルできます。
|
||||
@@ -156,7 +131,7 @@ $ cmake -B ./build/ -DTOML11_BUILD_EXAMPLES=ON
|
||||
$ cmake --build ./build/
|
||||
```
|
||||
|
||||
### Building Tests
|
||||
### Building example
|
||||
|
||||
`-DTOML11_BUILD_TESTS=ON`とすることで、ユニットテストをコンパイルできます。
|
||||
|
||||
@@ -191,30 +166,8 @@ const toml::value input = toml::parse("input.toml");
|
||||
const toml::value input = toml::parse_str("a = 42");
|
||||
```
|
||||
|
||||
文字列リテラルをパースする際は、`""_toml`リテラルを使うことができます。
|
||||
|
||||
```cpp
|
||||
using namespace toml::literals::toml_literals;
|
||||
const toml::value lit = "a = 42"_toml;
|
||||
```
|
||||
|
||||
`toml::parse`や`parse_str`は文法エラーの際に `toml::syntax_error` 例外を投げます。
|
||||
|
||||
`what()`で得られるエラーメッセージは以下のようになります。
|
||||
|
||||
```
|
||||
[error] bad integer: `_` must be surrounded by digits
|
||||
--> internal string at line 64 in file main.cpp
|
||||
|
|
||||
1 | a = 123__456
|
||||
| ^-- invalid underscore
|
||||
Hint: valid : -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755
|
||||
Hint: invalid: _42, 1__000, 0123
|
||||
```
|
||||
|
||||
エラーメッセージには`toml::color::enable()`を呼ぶことで色を付けることも可能です。
|
||||
|
||||
`toml::try_parse`を使うことで、例外を投げずに `toml::result<toml::value, std::vector<toml::error_info>>` を受け取ることができます。
|
||||
`toml::parse`は文法エラーの際に `toml::syntax_error` 例外を投げます。
|
||||
これを避けるには、 `toml::result` を返す `toml::try_parse` を使います。
|
||||
|
||||
```cpp
|
||||
const auto input = toml::try_parse("input.toml");
|
||||
@@ -258,46 +211,11 @@ if(input.contains("a") && input.at("a").is_integer())
|
||||
}
|
||||
```
|
||||
|
||||
`toml::find` を使うことで、型変換と検索を同時に行うことができます。
|
||||
`toml::find` を使うことで、型変換と検索が同時に行えます。
|
||||
|
||||
```cpp
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find<std::string>(input, "a") << std::endl;
|
||||
```
|
||||
|
||||
型変換や値の検索に失敗した場合は、`toml::type_error`が送出されます。
|
||||
その場合のエラーメッセージは以下のようになります。
|
||||
|
||||
```
|
||||
[error] toml::value::as_string(): bad_cast to string
|
||||
--> input.toml
|
||||
|
|
||||
1 | a = 123_456
|
||||
| ^^^^^^^-- the actual type is integer
|
||||
```
|
||||
|
||||
ネストされたテーブルやテーブルの配列にも同じ方法でアクセスできます。
|
||||
|
||||
```cpp
|
||||
// [a]
|
||||
// b = [
|
||||
// {c = 42},
|
||||
// {c = 54}
|
||||
// ]
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find<int>(input, "a", "b", 1, "c") << std::endl;
|
||||
```
|
||||
|
||||
ほとんどのSTLコンテナや、同様のインターフェースを持つコンテナへ変換が可能です。
|
||||
|
||||
```cpp
|
||||
// array = [3,1,4,1,5]
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
|
||||
const auto a1 = toml::find<std::vector<int> >(input, "array") << std::endl;
|
||||
const auto a2 = toml::find<std::array<int, 5>>(input, "array") << std::endl;
|
||||
const auto a3 = toml::find<std::deque<int> >(input, "array") << std::endl;
|
||||
const auto a4 = toml::find<boost::container::small_vector<int, 8>>(input, "array") << std::endl;
|
||||
std::cout << toml::find<int>(input, "a") << std::endl;
|
||||
```
|
||||
|
||||
また、複雑なTOML値に対して、高度な型変換を行うことができます。
|
||||
@@ -318,36 +236,6 @@ const auto mixed = toml::find<
|
||||
>(input, "mixed_array") << std::endl;
|
||||
```
|
||||
|
||||
マクロの使用または特定の関数を定義することで、ユーザー定義型にも変換が可能です。
|
||||
|
||||
```cpp
|
||||
namespace extlib
|
||||
{
|
||||
struct foo
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
} // extlib
|
||||
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib::foo, a, b)
|
||||
|
||||
// ...
|
||||
|
||||
const auto input = R"(
|
||||
[foo]
|
||||
a = 42
|
||||
b = "bar"
|
||||
)"_toml;
|
||||
const extlib::foo f = toml::find<extlib::foo>(input, "foo");
|
||||
```
|
||||
|
||||
`toml::find_or`を使うことで、失敗時にデフォルト値を得ることができます。
|
||||
|
||||
```cpp
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find_or(input, "a", 6*9) << std::endl;
|
||||
```
|
||||
|
||||
詳細については[ドキュメント](https://toruniina.github.io/toml11/ja/docs/features/value/)を参照してください。
|
||||
|
||||
### comments
|
||||
@@ -436,73 +324,18 @@ toml::value output(toml::table{ {"a", 0xDEADBEEF} });
|
||||
output.at("a").as_integer_fmt().fmt = toml::integer_format::hex;
|
||||
output.at("a").as_integer_fmt().spacer = 4;
|
||||
|
||||
std::cout << toml::format(output) << std::endl;
|
||||
// a = 0xdead_beef
|
||||
std::cout << toml::format(input) << std::endl;
|
||||
```
|
||||
|
||||
テーブルや配列のフォーマットも指定が可能です。
|
||||
|
||||
```cpp
|
||||
toml::value output(toml::table{
|
||||
{"array-of-tables", toml::array{}},
|
||||
{"subtable", toml::table{}},
|
||||
});
|
||||
|
||||
auto& aot = output.at("array-of-tables");
|
||||
aot.as_array_fmt().fmt = toml::array_format::multiline;
|
||||
aot.as_array_fmt().body_indent = 4;
|
||||
aot.as_array_fmt().closing_indent = 2;
|
||||
|
||||
toml::value v1(toml::table{ {"a", 42}, {"b", 3.14} });
|
||||
v1.as_table_fmt().fmt = toml::table_format::oneline;
|
||||
aot.push_back(std::move(v1));
|
||||
|
||||
toml::value v2(toml::table{ {"a", 42}, {"b", 3.14} });
|
||||
v2.as_table_fmt().fmt = toml::table_format::oneline;
|
||||
aot.push_back(std::move(v2));
|
||||
|
||||
output.at("subtable").as_table_fmt().fmt = toml::table_format::dotted;
|
||||
output.at("subtable")["a"] = 42;
|
||||
output.at("subtable")["b"] = 3.14;
|
||||
|
||||
std::cout << toml::format(output) << std::endl;
|
||||
// subtable.b = 3.14
|
||||
// subtable.a = 42
|
||||
// array-of-tables = [
|
||||
// {b = 3.14, a = 42},
|
||||
// {b = 2.71, a = 54},
|
||||
// ]
|
||||
```
|
||||
|
||||
これらの設定はパース時に読み取られ、値を変更した際も型が変わらない限り維持されます。
|
||||
|
||||
どのような指定が可能かなどの詳細は[ドキュメント](https://toruniina.github.io/toml11/ja/docs/features/serialize/)を参照してください。
|
||||
|
||||
### configuring types
|
||||
|
||||
`toml::value`が持つ型の多く、`integer_type`や`array_type`などは`type_config`型を変更することで変更可能です。
|
||||
|
||||
[`examples`ディレクトリ](https://github.com/ToruNiina/toml11/tree/main/examples)には、
|
||||
多倍長整数を使用する場合やコンテナを変更する場合、ユニコードを正規化する場合などの複雑な使用例を用意しています。
|
||||
[`examples`ディレクトリ](https://github.com/ToruNiina/toml11/tree/main/examples)には、多倍長整数を使用する場合やユニコードを正規化する場合、
|
||||
外部のリフレクションライブラリと連携する場合などの複雑な使用例を用意しています。
|
||||
|
||||
そのような状況での実装例として参照してください。
|
||||
|
||||
## Examples
|
||||
|
||||
[`examples`ディレクトリ](https://github.com/ToruNiina/toml11/tree/main/examples)では、
|
||||
型の設定の他にも実装例を紹介しています。
|
||||
|
||||
- [boost_container](https://github.com/ToruNiina/toml11/tree/main/examples/boost_container)
|
||||
- `array_type`や`table_type`に`boost::container`のコンテナを使う例です。
|
||||
- [boost_multiprecision](https://github.com/ToruNiina/toml11/tree/main/examples/boost_multiprecision)
|
||||
- `integer_type`や`floating_type`に`boost::multiprecision`の多倍長数値型を使う例です。
|
||||
- [parse_file](https://github.com/ToruNiina/toml11/tree/main/examples/parse_file)
|
||||
- 少し複雑な場合も含めた、型変換の実装例です。対応するTOMLファイルが同梱されています。
|
||||
- [reflect](https://github.com/ToruNiina/toml11/tree/main/examples/reflect)
|
||||
- boost-ext/reflectを用いたユーザー定義型との自型変換の例です。
|
||||
- [unicode](https://github.com/ToruNiina/toml11/tree/main/examples/unicode)
|
||||
- uni-algoを用いて、キーを検索する際にユニコード文字列を正規化する例です。
|
||||
|
||||
## Changes from v3
|
||||
|
||||
toml11 v3からは複数の破壊的変更が追加されています。
|
||||
@@ -625,10 +458,6 @@ toml11 v3からは複数の破壊的変更が追加されています。
|
||||
- Add fuzzing test based on ClusterFuzzLite
|
||||
- Esonhugh Skyworship (@Esonhugh)
|
||||
- Fix function signature of `strerror_r` on macos
|
||||
- Alberto (@0X1A)
|
||||
- Fix issues with CMake package configuration when used with vcpkg
|
||||
- Egor Pugin (@egorpugin)
|
||||
- Fix incorrect operator<<() argument type that gives build error
|
||||
|
||||
## Licensing terms
|
||||
|
||||
|
||||
@@ -4,10 +4,8 @@ environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
generator: Visual Studio 16 2019
|
||||
systemver: 10.0.18362.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
generator: Visual Studio 17 2022
|
||||
systemver: 10.0.22621.0
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
@@ -21,7 +19,7 @@ install:
|
||||
|
||||
build_script:
|
||||
- cd C:\toml11
|
||||
- cmake -B build -G"%generator%" -DCMAKE_SYSTEM_VERSION="%systemver%" -A x64 -DCMAKE_CXX_STANDARD=11 -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=ON
|
||||
- cmake -B build -G"%generator%" -A x64 -DCMAKE_CXX_STANDARD=11 -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=ON
|
||||
- cmake --build build --config "%configuration%"
|
||||
|
||||
test_script:
|
||||
|
||||
@@ -7,19 +7,19 @@ type = "docs"
|
||||
|
||||
日本語版は[こちら](/toml11/ja/)
|
||||
|
||||
## [Installation](docs/installation)
|
||||
## [Installation]({{< relref "/installation" >}})
|
||||
|
||||
This section describes how to build and install toml11.
|
||||
|
||||
## [Features](docs/features)
|
||||
## [Features]({{< relref "/features" >}})
|
||||
|
||||
This section describes how to use toml11's features with examples.
|
||||
|
||||
## [Reference](docs/reference)
|
||||
## [Reference]({{< relref "/reference" >}})
|
||||
|
||||
This section details toml11 functions and classes.
|
||||
|
||||
## [ChangeLog](docs/changelog)
|
||||
## [ChangeLog]({{< relref "/changelog" >}})
|
||||
|
||||
This section describes changes from release to release.
|
||||
|
||||
|
||||
@@ -42,18 +42,10 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
#### Specifying a File with `std::filesystem::path`
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}}) can accept a `std::filesystem::path`.
|
||||
|
||||
This requires C++17 or later, as it relies on the `<filesystem>` support.
|
||||
|
||||
#### Specifying an Input Stream with `std::istream`
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}}) can also accept an `std::istream`.
|
||||
|
||||
Open a stream in binary mode by passing `std::ios::binary` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
Without the filename information, error messages will display `"unknown file"`. To avoid this, you can pass the filename as a `std::string` in the second argument when using `std::istream`.
|
||||
|
||||
You can use streams other than `std::ifstream`, such as `std::istringstream`. Note that the entire content is readable at the time of the call.
|
||||
@@ -72,12 +64,16 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
#### Specifying a File with `std::filesystem::path`
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}}) can accept a `std::filesystem::path`.
|
||||
|
||||
This requires C++17 or later, as it relies on the `<filesystem>` support.
|
||||
|
||||
#### Specifying a File with `FILE*`
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}}) can also accept a `FILE*`.
|
||||
|
||||
Open a stream in binary mode by passing `"rb"` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
As with `std::istream`, you need to provide the filename as a string in the second argument.
|
||||
|
||||
When passing a `FILE*`, if the file read fails, `errno` will be reported.
|
||||
|
||||
@@ -92,6 +92,32 @@ std::cout << v.at(1);
|
||||
|
||||
If the stored type is not `array_type`, a `type_error` is thrown.
|
||||
|
||||
### `try_at(std::size_t i)`
|
||||
|
||||
Performs the same operation as `at(i)`, but instead of throwing an exception on failure, it always returns a [`toml::result<T&, error_info>`]({{<ref "docs/reference/result">}}). It does not throw an exception on failure.
|
||||
|
||||
```cpp
|
||||
toml::value v(toml::array{1,2,3});
|
||||
|
||||
auto res1 = v.try_at(1);
|
||||
assert(res1.is_ok());
|
||||
std::cout << res1.unwrap() << std::endl;
|
||||
|
||||
auto res5 = v.try_at(5);
|
||||
assert(res1.is_err());
|
||||
std::cout << toml::format_error(res1.unwrap_err()) << std::endl;
|
||||
```
|
||||
|
||||
Additionally, since this `toml::result` holds a reference, it is possible to update the value.
|
||||
|
||||
```cpp
|
||||
toml::value v(toml::array{1,2,3});
|
||||
|
||||
auto res1 = v.try_at(1);
|
||||
assert(res1.is_ok());
|
||||
res1.unwrap() = 42;
|
||||
```
|
||||
|
||||
#### `at(std::string key)`, `operator[](std::string key)`
|
||||
|
||||
These are equivalent to `as_table().at(key)` and `as_table()[key]`.
|
||||
@@ -105,6 +131,32 @@ v["a"] = 42;
|
||||
|
||||
If the stored type is not `table_type`, a `type_error` is thrown.
|
||||
|
||||
### `try_at(std::string key)`
|
||||
|
||||
Performs the same operation as `at(key)`, but instead of throwing an exception on failure, it always returns a [`toml::result<T&, error_info>`]({{<ref "docs/reference/result">}}). It does not throw an exception on failure.
|
||||
|
||||
```cpp
|
||||
toml::value v(toml::table{ {"a", 42}, {"b", "foo"} });
|
||||
|
||||
auto res_a = v.try_at("a");
|
||||
assert(res_a.is_ok());
|
||||
std::cout << res_a.unwrap() << std::endl;
|
||||
|
||||
auto res_c = v.try_at("c");
|
||||
assert(res_c.is_err());
|
||||
std::cout << toml::format_error(res_c.unwrap_err()) << std::endl;
|
||||
```
|
||||
|
||||
Additionally, since this `toml::result` holds a reference, it is possible to update the value.
|
||||
|
||||
```cpp
|
||||
toml::value v(toml::table{ {"a", 42}, {"b", "foo"} });
|
||||
|
||||
auto res_a = v.try_at("a");
|
||||
assert(res_a.is_ok());
|
||||
res_a.unwrap() = 6 * 9;
|
||||
```
|
||||
|
||||
#### `size()`
|
||||
|
||||
Returns the length.
|
||||
|
||||
@@ -54,14 +54,6 @@ By defining `-DTOML11_PRECOMPILE=ON` when running cmake, you can precompile some
|
||||
$ cmake -B ./build/ -DTOML11_PRECOMPILE=ON
|
||||
```
|
||||
|
||||
When linking the library, use `target_link_libraries` in CMake
|
||||
|
||||
```cmake
|
||||
target_link_libraries(your_target PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
or pass `-DTOML11_COMPILE_SOURCES` to the compiler to suppress header-only features.
|
||||
|
||||
However, since toml11 supports multiple C++ versions and may switch types based on the value of `__cplusplus`,
|
||||
there is a possibility of link failures if the version used during build differs from the version used during usage.
|
||||
If you encounter issues, set the required version using `CMAKE_CXX_STANDARD` during compilation.
|
||||
|
||||
@@ -17,6 +17,23 @@ In case of failure, `toml::syntax_error` is thrown.
|
||||
|
||||
The type information of `basic_value` is provided by a `template`, and the TOML language version is specified by `toml::spec`.
|
||||
|
||||
### `parse(std::istream&, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC = type_config>
|
||||
basic_value<TC>
|
||||
parse(std::istream& is,
|
||||
std::string fname = "unknown file",
|
||||
spec s = spec::default_version());
|
||||
}
|
||||
```
|
||||
|
||||
Parses the content of the given `std::istream&`.
|
||||
|
||||
The filename information is taken as the third argument. If the filename is not provided, it defaults to `"unknown file"`.
|
||||
|
||||
### `parse(std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@@ -73,25 +90,6 @@ If reading the file fails, `toml::file_io_error` is thrown.
|
||||
|
||||
If parsing fails, `toml::syntax_error` is thrown.
|
||||
|
||||
### `parse(std::istream&, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC = type_config>
|
||||
basic_value<TC>
|
||||
parse(std::istream& is,
|
||||
std::string fname = "unknown file",
|
||||
spec s = spec::default_version());
|
||||
}
|
||||
```
|
||||
|
||||
Parses the content of the given `std::istream&`.
|
||||
|
||||
Open a stream in binary mode by passing `std::ios::binary` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
The filename information is taken as the third argument. If the filename is not provided, it defaults to `"unknown file"`.
|
||||
|
||||
### `parse(FILE*, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@@ -107,8 +105,6 @@ parse(FILE* fp,
|
||||
|
||||
Parses the content of the file pointed to by `FILE*`.
|
||||
|
||||
Open a stream in binary mode by passing `"rb"` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
If reading the file fails, `file_io_error` containing `errno` is thrown.
|
||||
|
||||
If parsing fails, `syntax_error` is thrown.
|
||||
@@ -170,6 +166,27 @@ For instance, errors occurring internally within `std::ifstream` or memory exhau
|
||||
|
||||
{{< /hint >}}
|
||||
|
||||
### `try_parse(std::istream&, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC = type_config>
|
||||
result<basic_value<TC>, std::vector<error_info>>
|
||||
try_parse(std::istream& is,
|
||||
std::string fname = "unknown file",
|
||||
spec s = spec::default_version());
|
||||
}
|
||||
```
|
||||
|
||||
Takes a `std::istream&` and parses its content.
|
||||
|
||||
The file name information is taken as the second argument. If a file name is not provided, it defaults to `"unknown file"`.
|
||||
|
||||
If parsing fails, a `result` holding the error type `std::vector<error_info>` is returned.
|
||||
|
||||
If successful, a `result` holding a `basic_value` is returned.
|
||||
|
||||
### `try_parse(std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@@ -224,29 +241,6 @@ If parsing fails, a `result` holding the error type `std::vector<error_info>` is
|
||||
|
||||
If successful, a `result` holding a `basic_value` is returned.
|
||||
|
||||
### `try_parse(std::istream&, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC = type_config>
|
||||
result<basic_value<TC>, std::vector<error_info>>
|
||||
try_parse(std::istream& is,
|
||||
std::string fname = "unknown file",
|
||||
spec s = spec::default_version());
|
||||
}
|
||||
```
|
||||
|
||||
Takes a `std::istream&` and parses its content.
|
||||
|
||||
Open a stream in binary mode by passing `std::ios::binary` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
The file name information is taken as the second argument. If a file name is not provided, it defaults to `"unknown file"`.
|
||||
|
||||
If parsing fails, a `result` holding the error type `std::vector<error_info>` is returned.
|
||||
|
||||
If successful, a `result` holding a `basic_value` is returned.
|
||||
|
||||
### `try_parse(FILE*, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@@ -262,8 +256,6 @@ try_parse(FILE* fp,
|
||||
|
||||
Takes a `FILE*` and parses its content.
|
||||
|
||||
Open a stream in binary mode by passing `"rb"` to avoid inconsistency between the file size and the number of characters due to automatic conversion of newline characters by the standard library.
|
||||
|
||||
If parsing fails, a `result` holding the error type `std::vector<error_info>` is returned.
|
||||
|
||||
If successful, a `result` holding a `basic_value` is returned.
|
||||
|
||||
@@ -585,6 +585,27 @@ Throws `std::out_of_range` if the `table` does not contain the specified element
|
||||
|
||||
-----
|
||||
|
||||
### `try_at(key)`
|
||||
|
||||
```cpp
|
||||
result<std::reference_wrapper<value_type>, error_info> try_at(const key_type& key) noexcept;
|
||||
result<std::reference_wrapper<const value_type>, error_info> try_at(const key_type& key) const noexcept;
|
||||
```
|
||||
|
||||
#### Return Value
|
||||
|
||||
After casting the current `value` to a `table`, it returns the element specified by the `key`.
|
||||
|
||||
If successful, it returns a `reference_wrapper` holding a reference to that element.
|
||||
|
||||
If unsuccessful, it returns an `error_info` corresponding to `type_error` or `out_of_range`.
|
||||
|
||||
#### Exceptions
|
||||
|
||||
Does not throw.
|
||||
|
||||
-----
|
||||
|
||||
#### `operator[](key)`
|
||||
|
||||
```cpp
|
||||
@@ -652,6 +673,26 @@ Throws `toml::type_error` if the stored value is not an `array`.
|
||||
|
||||
Throws `std::out_of_range` if the specified element does not exist in the `array`.
|
||||
|
||||
-----
|
||||
|
||||
### `try_at(idx)`
|
||||
|
||||
```cpp
|
||||
result<std::reference_wrapper<value_type>, error_info> try_at(const std::size_t idx) noexcept;
|
||||
result<std::reference_wrapper<const value_type>, error_info> try_at(const std::size_t idx) const noexcept;
|
||||
```
|
||||
|
||||
#### Return Value
|
||||
|
||||
After casting the current `value` to an `array`, it returns the element specified by the `idx`.
|
||||
|
||||
If successful, it returns a `reference_wrapper` holding a reference to that element.
|
||||
|
||||
If unsuccessful, it returns an `error_info` corresponding to `type_error` or `out_of_range`.
|
||||
|
||||
#### Exceptions
|
||||
|
||||
Does not throw.
|
||||
|
||||
-----
|
||||
|
||||
|
||||
@@ -7,19 +7,19 @@ type = "docs"
|
||||
|
||||
English version is [here](../en/)
|
||||
|
||||
## [Installation](docs/installation)
|
||||
## [Installation]({{< relref "/installation" >}})
|
||||
|
||||
toml11のインストール方法について説明します。
|
||||
|
||||
## [Features](docs/features)
|
||||
## [Features]({{< relref "/features" >}})
|
||||
|
||||
toml11の機能と使い方を例に沿って説明します。
|
||||
|
||||
## [Reference](docs/reference)
|
||||
## [Reference]({{< relref "/reference" >}})
|
||||
|
||||
toml11が持つ関数・クラスの詳細を説明します。
|
||||
|
||||
## [ChangeLog](docs/changelog)
|
||||
## [ChangeLog]({{< relref "/changelog" >}})
|
||||
|
||||
v3系から、そしてリリースごとの変化を説明します。
|
||||
|
||||
|
||||
@@ -44,21 +44,11 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
#### `std::filesystem::path`でファイルを指定する
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
|
||||
には、`std::filesystem::path`を渡すことも可能です。
|
||||
|
||||
当然ですが、`<filesystem>`がサポートされるC++17以降でなければ使用できません。
|
||||
|
||||
#### `std::istream`で入力ストリームを指定する
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
|
||||
には、`std::istream`を渡すことも可能です。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`std::ios::binary`を使ってバイナリモードで開いてください。
|
||||
|
||||
その際、ファイル名の情報がなくなるため、エラーメッセージ中では `"unknown file"` となります。
|
||||
|
||||
これを避けるため、 `std::istream` を取る場合は第二引数に `std::string` でファイル名を取ることもできます。
|
||||
@@ -80,14 +70,18 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
#### `std::filesystem::path`でファイルを指定する
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
|
||||
には、`std::filesystem::path`を渡すことも可能です。
|
||||
|
||||
当然ですが、`<filesystem>`がサポートされるC++17以降でなければ使用できません。
|
||||
|
||||
#### `FILE*`でファイルを指定する
|
||||
|
||||
[`toml::parse`]({{< ref "docs/reference/parser#parse" >}})
|
||||
には、`FILE*`を渡すことも可能です。
|
||||
|
||||
標準ライブラリによる改行文字の自動変換によるファイルサイズと文字数との不整合を避けるため、
|
||||
`fopen("example.toml", "rb")`のようにしてバイナリモードで開いてください。
|
||||
|
||||
この場合も、`std::istream`のときと同様に、第二引数に文字列でファイル名を与える必要があります。
|
||||
|
||||
`FILE*`を渡した場合、ファイルの読み込みに失敗した際には`errno`が報告されます。
|
||||
|
||||
@@ -96,6 +96,32 @@ std::cout << v.at(1);
|
||||
|
||||
格納している型が `array_type` ではなかった場合、 `type_error` を送出します。
|
||||
|
||||
#### `try_at(std::size_t i)`
|
||||
|
||||
`at(i)`と同様の操作をしますが、失敗時に例外を投げる代わりに、常に[`toml::result<T&, error_info>`]({{<ref "docs/reference/result">}})を返します。失敗時に例外は投げません。
|
||||
|
||||
```cpp
|
||||
toml::value v(toml::array{1,2,3});
|
||||
|
||||
auto res1 = v.try_at(1);
|
||||
assert(res1.is_ok());
|
||||
std::cout << res1.unwrap() << std::endl;
|
||||
|
||||
auto res5 = v.try_at(5);
|
||||
assert(res1.is_err());
|
||||
std::cout << toml::format_error(res1.unwrap_err()) << std::endl;
|
||||
```
|
||||
|
||||
また、この`toml::result`は成功値として参照を持つので、値を更新することも可能です。
|
||||
|
||||
```cpp
|
||||
toml::value v(toml::array{1,2,3});
|
||||
|
||||
auto res1 = v.try_at(1);
|
||||
assert(res1.is_ok());
|
||||
res1.unwrap() = 42;
|
||||
```
|
||||
|
||||
#### `at(std::string key)`, `operator[](std::string key)`
|
||||
|
||||
`as_table().at(key)`, `as_table()[key]` と同等です。
|
||||
@@ -111,6 +137,32 @@ v["a"] = 42;
|
||||
|
||||
格納している型が `table_type` ではなかった場合、 `type_error` を送出します。
|
||||
|
||||
#### `try_at(std::string key)`
|
||||
|
||||
`at(key)`と同様の操作をしますが、失敗時に例外を投げる代わりに、常に[`toml::result<T&, error_info>`]({{<ref "docs/reference/result">}})を返します。失敗時に例外は投げません。
|
||||
|
||||
```cpp
|
||||
toml::value v(toml::table{ {"a", 42}, {"b", "foo"} });
|
||||
|
||||
auto res_a = v.try_at("a");
|
||||
assert(res_a.is_ok());
|
||||
std::cout << res_a.unwrap() << std::endl;
|
||||
|
||||
auto res_c = v.try_at("c");
|
||||
assert(res_c.is_err());
|
||||
std::cout << toml::format_error(res_c.unwrap_err()) << std::endl;
|
||||
```
|
||||
|
||||
また、この`toml::result`は成功値として参照を持つので、値を更新することも可能です。
|
||||
|
||||
```cpp
|
||||
toml::value v(toml::table{ {"a", 42}, {"b", "foo"} });
|
||||
|
||||
auto res_a = v.try_at("a");
|
||||
assert(res_a.is_ok());
|
||||
res_a.unwrap() = 6 * 9;
|
||||
```
|
||||
|
||||
#### `size()`
|
||||
|
||||
長さを返します。
|
||||
|
||||
@@ -54,14 +54,6 @@ target_link_libraries(main PRIVATE toml11::toml11)
|
||||
$ cmake -B ./build/ -DTOML11_PRECOMPILE=ON
|
||||
```
|
||||
|
||||
ライブラリをリンクする場合は、CMakeで
|
||||
|
||||
```cmake
|
||||
target_link_libraries(your_target PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
とするか、ヘッダ内の関数の`inline`化を避けるためにコンパイラに`-DTOML11_COMPILE_SOURCES`を渡してください。
|
||||
|
||||
ただし、toml11は複数のC++バージョンに対応するため、`__cplusplus`の値などによって型を切り替えることがあります。
|
||||
そのため、ビルドした際のバージョンと使用時のバージョンが異なる場合、リンクに失敗する可能性があります。
|
||||
問題が生じた場合は`CMAKE_CXX_STANDARD`によって必要なバージョンを設定してコンパイルしてください。
|
||||
|
||||
@@ -17,6 +17,23 @@ type = "docs"
|
||||
|
||||
`basic_value`の持つ型情報は`template`で、TOML言語のバージョンは`toml::spec`で指定します。
|
||||
|
||||
### `parse(std::istream&, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC = type_config>
|
||||
basic_value<TC>
|
||||
parse(std::istream& is,
|
||||
std::string fname = "unknown file",
|
||||
spec s = spec::default_version());
|
||||
}
|
||||
```
|
||||
|
||||
`std::istream&`を受け取ってその内容をパースします。
|
||||
|
||||
ファイル名の情報は第三引数で受け取ります。ファイル名が渡されなかった場合、`"unknown file"`になります。
|
||||
|
||||
### `parse(std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@@ -73,25 +90,6 @@ parse(const std::filesystem::path& fpath,
|
||||
|
||||
パースに失敗した場合、`syntax_error`が送出されます。
|
||||
|
||||
### `parse(std::istream&, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC = type_config>
|
||||
basic_value<TC>
|
||||
parse(std::istream& is,
|
||||
std::string fname = "unknown file",
|
||||
spec s = spec::default_version());
|
||||
}
|
||||
```
|
||||
|
||||
`std::istream&`を受け取ってその内容をパースします。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`std::ios::binary`を使ってバイナリモードで開いてください。
|
||||
|
||||
ファイル名の情報は第三引数で受け取ります。ファイル名が渡されなかった場合、`"unknown file"`になります。
|
||||
|
||||
### `parse(FILE*, std::string filename, toml::spec)`
|
||||
|
||||
@@ -108,9 +106,6 @@ parse(FILE* fp,
|
||||
|
||||
`FILE*`が指すファイルを読み込んでパースします。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`fopen`には`"rb"`などを渡してバイナリモードで開いてください。
|
||||
|
||||
ファイルの読み込みに失敗した場合、`errno`が含まれた`file_io_error`が送出されます。
|
||||
|
||||
パースに失敗した場合、`syntax_error`が送出されます。
|
||||
@@ -172,6 +167,28 @@ parse_str(std::string content,
|
||||
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
### `try_parse(std::istream&, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC = type_config>
|
||||
result<basic_value<TC>, std::vector<error_info>>
|
||||
try_parse(std::istream& is,
|
||||
std::string fname = "unknown file",
|
||||
spec s = spec::default_version());
|
||||
}
|
||||
```
|
||||
|
||||
`std::istream&`を受け取ってその内容をパースします。
|
||||
|
||||
ファイル名の情報は第二引数で受け取ります。ファイル名が渡されなかった場合、`"unknown file"`になります。
|
||||
|
||||
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
|
||||
|
||||
成功した場合、`basic_value`を持つ`result`が返されます。
|
||||
|
||||
### `try_parse(std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@@ -227,30 +244,6 @@ try_parse(const std::filesystem::path& fpath,
|
||||
|
||||
成功した場合、`basic_value`を持つ`result`が返されます。
|
||||
|
||||
### `try_parse(std::istream&, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC = type_config>
|
||||
result<basic_value<TC>, std::vector<error_info>>
|
||||
try_parse(std::istream& is,
|
||||
std::string fname = "unknown file",
|
||||
spec s = spec::default_version());
|
||||
}
|
||||
```
|
||||
|
||||
`std::istream&`を受け取ってその内容をパースします。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`std::ios::binary`を使ってバイナリモードで開いてください。
|
||||
|
||||
ファイル名の情報は第二引数で受け取ります。ファイル名が渡されなかった場合、`"unknown file"`になります。
|
||||
|
||||
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
|
||||
|
||||
成功した場合、`basic_value`を持つ`result`が返されます。
|
||||
|
||||
### `try_parse(FILE*, std::string filename, toml::spec)`
|
||||
|
||||
```cpp
|
||||
@@ -266,9 +259,6 @@ try_parse(FILE* fp,
|
||||
|
||||
`FILE*`を受け取って、そのファイルの内容をパースします。
|
||||
|
||||
標準ライブラリが改行文字を自動変換することによるファイルサイズと文字数との不整合を避けるため、
|
||||
`fopen`には`"rb"`などを渡してバイナリモードで開いてください。
|
||||
|
||||
パースに失敗した場合、エラー型である`std::vector<error_info>`を持つ`result`が返されます。
|
||||
|
||||
成功した場合、`basic_value`を持つ`result`が返されます。
|
||||
|
||||
@@ -583,6 +583,27 @@ value_type const& at(const key_type& key) const;
|
||||
|
||||
-----
|
||||
|
||||
### `try_at(key)`
|
||||
|
||||
```cpp
|
||||
result<std::reference_wrapper<value_type>, error_info> try_at(const key_type& key) noexcept;
|
||||
result<std::reference_wrapper<const value_type>, error_info> try_at(const key_type& key) const noexcept;
|
||||
```
|
||||
|
||||
#### 戻り値
|
||||
|
||||
今の`value`を`table`にキャストしたあと、`key`によって指定される要素を返します。
|
||||
|
||||
成功した場合、その要素への参照を持つ`reference_wrapper`を返します。
|
||||
|
||||
失敗した場合、 `type_error` または `out_of_range` に対応する `error_info` を返します。
|
||||
|
||||
#### 例外
|
||||
|
||||
投げません。
|
||||
|
||||
-----
|
||||
|
||||
#### `operator[](key)`
|
||||
|
||||
```cpp
|
||||
@@ -652,6 +673,27 @@ value_type const& at(const std::size_t idx) const;
|
||||
|
||||
-----
|
||||
|
||||
### `try_at(idx)`
|
||||
|
||||
```cpp
|
||||
result<std::reference_wrapper<value_type>, error_info> try_at(const std::size_t idx) noexcept;
|
||||
result<std::reference_wrapper<const value_type>, error_info> try_at(const std::size_t idx) const noexcept;
|
||||
```
|
||||
|
||||
#### 戻り値
|
||||
|
||||
今の`value`を`array`にキャストしたあと、`idx`によって指定される要素を返します。
|
||||
|
||||
成功した場合、その要素への参照を持つ`reference_wrapper`を返します。
|
||||
|
||||
失敗した場合、 `type_error` または `out_of_range` に対応する `error_info` を返します。
|
||||
|
||||
#### 例外
|
||||
|
||||
投げません。
|
||||
|
||||
-----
|
||||
|
||||
### `operator[](idx)`
|
||||
|
||||
```cpp
|
||||
|
||||
@@ -498,7 +498,7 @@ struct source_location
|
||||
static source_location current() { return source_location{}; }
|
||||
};
|
||||
|
||||
inline std::string to_string(const source_location&)
|
||||
inline std::string to_string(const source_location& loc)
|
||||
{
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "get.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "value.hpp"
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
@@ -101,54 +102,7 @@ find(basic_value<TC>&& v, const std::size_t idx)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// toml::find(toml::value, toml::key, Ts&& ... keys)
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// It suppresses warnings by -Wsign-conversion when we pass integer literal
|
||||
// to toml::find. integer literal `0` is deduced as an int, and will be
|
||||
// converted to std::size_t. This causes sign-conversion.
|
||||
|
||||
template<typename TC>
|
||||
std::size_t key_cast(const std::size_t& v) noexcept
|
||||
{
|
||||
return v;
|
||||
}
|
||||
template<typename TC, typename T>
|
||||
cxx::enable_if_t<std::is_integral<cxx::remove_cvref_t<T>>::value, std::size_t>
|
||||
key_cast(const T& v) noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(v);
|
||||
}
|
||||
|
||||
// for string-like (string, string literal, string_view)
|
||||
|
||||
template<typename TC>
|
||||
typename basic_value<TC>::key_type const&
|
||||
key_cast(const typename basic_value<TC>::key_type& v) noexcept
|
||||
{
|
||||
return v;
|
||||
}
|
||||
template<typename TC>
|
||||
typename basic_value<TC>::key_type
|
||||
key_cast(const typename basic_value<TC>::key_type::value_type* v)
|
||||
{
|
||||
return typename basic_value<TC>::key_type(v);
|
||||
}
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
template<typename TC>
|
||||
typename basic_value<TC>::key_type
|
||||
key_cast(const std::string_view v)
|
||||
{
|
||||
return typename basic_value<TC>::key_type(v);
|
||||
}
|
||||
#endif // string_view
|
||||
|
||||
} // detail
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// find(v, keys...)
|
||||
// toml::find(toml::value, toml::key, Ts&& ... keys) w/o conversion
|
||||
|
||||
template<typename TC, typename K1, typename K2, typename ... Ks>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value, basic_value<TC>> const&
|
||||
|
||||
@@ -7,7 +7,18 @@ namespace toml
|
||||
template<typename T>
|
||||
struct from;
|
||||
// {
|
||||
// static T from_toml(const toml::value& v)
|
||||
// template<typename TC>
|
||||
// static T from_toml(const toml::basic_value<TC>& v)
|
||||
// {
|
||||
// // User-defined conversions ...
|
||||
// }
|
||||
// };
|
||||
|
||||
template<typename T>
|
||||
struct try_from;
|
||||
// {
|
||||
// template<typename TC>
|
||||
// static result<T, error_info> try_from_toml(const toml::basic_value<TC>& v) noexcept
|
||||
// {
|
||||
// // User-defined conversions ...
|
||||
// }
|
||||
|
||||
@@ -41,10 +41,6 @@ struct error_info
|
||||
std::string suffix_; // hint or something like that
|
||||
};
|
||||
|
||||
// forward decl
|
||||
template<typename TypeConfig>
|
||||
class basic_value;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline error_info make_error_info_rec(error_info e)
|
||||
@@ -57,10 +53,6 @@ inline error_info make_error_info_rec(error_info e, std::string s)
|
||||
return e;
|
||||
}
|
||||
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
const basic_value<TC>& v, std::string msg, Ts&& ... tail);
|
||||
|
||||
template<typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
source_location loc, std::string msg, Ts&& ... tail)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "../location.hpp"
|
||||
#include "../types.hpp"
|
||||
#include "../version.hpp" // IWYU pragma: keep for TOML11_HAS_CHAR8_T
|
||||
#include "../value.hpp"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
@@ -21,6 +21,12 @@ inline namespace toml_literals
|
||||
|
||||
::toml::value operator"" _toml(const char* str, std::size_t len);
|
||||
|
||||
#if defined(__cpp_char8_t)
|
||||
# if __cpp_char8_t >= 201811L
|
||||
# define TOML11_HAS_CHAR8_T 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(TOML11_HAS_CHAR8_T)
|
||||
// value of u8"" literal has been changed from char to char8_t and char8_t is
|
||||
// NOT compatible to char
|
||||
|
||||
@@ -552,7 +552,6 @@ TOML11_INLINE either string(const spec& s)
|
||||
TOML11_INLINE non_ascii_key_char::non_ascii_key_char(const spec& s) noexcept
|
||||
{
|
||||
assert(s.v1_1_0_allow_non_english_in_bare_keys);
|
||||
(void)s; // for NDEBUG
|
||||
}
|
||||
|
||||
TOML11_INLINE std::uint32_t non_ascii_key_char::read_utf8(location& loc) const
|
||||
|
||||
@@ -3524,7 +3524,7 @@ try_parse(std::istream& is, std::string fname = "unknown file", spec s = spec::d
|
||||
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize), '\0');
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
is.read(reinterpret_cast<char*>(letters.data()), fsize);
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(fname), std::move(s));
|
||||
@@ -3714,15 +3714,7 @@ try_parse(FILE* fp, std::string filename, spec s = spec::default_version())
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
const auto actual = std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
if(actual != static_cast<std::size_t>(fsize))
|
||||
{
|
||||
return err(std::vector<error_info>{error_info(
|
||||
std::string("File size changed: \"") + filename +
|
||||
std::string("\" make sure that FILE* is in binary mode "
|
||||
"to avoid LF <-> CRLF conversion"), {}
|
||||
)});
|
||||
}
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(filename), std::move(s));
|
||||
}
|
||||
@@ -3760,12 +3752,7 @@ parse(FILE* fp, std::string filename, spec s = spec::default_version())
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
const auto actual = std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
if(actual != static_cast<std::size_t>(fsize))
|
||||
{
|
||||
throw file_io_error(errno, "File size changed; make sure that "
|
||||
"FILE* is in binary mode to avoid LF <-> CRLF conversion", filename);
|
||||
}
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
|
||||
auto res = detail::parse_impl<TC>(std::move(letters), std::move(filename), std::move(s));
|
||||
if(res.is_ok())
|
||||
|
||||
@@ -90,6 +90,13 @@ struct has_specialized_from_impl
|
||||
template<typename T, std::size_t S = sizeof(::toml::from<T>)>
|
||||
static std::true_type check(::toml::from<T>*);
|
||||
};
|
||||
struct has_specialized_try_from_impl
|
||||
{
|
||||
template<typename T>
|
||||
static std::false_type check(...);
|
||||
template<typename T, std::size_t S = sizeof(::toml::try_from<T>)>
|
||||
static std::true_type check(::toml::try_from<T>*);
|
||||
};
|
||||
struct has_specialized_into_impl
|
||||
{
|
||||
template<typename T>
|
||||
@@ -130,6 +137,8 @@ template<typename T>
|
||||
struct has_specialized_from: decltype(has_specialized_from_impl::check<T>(nullptr)){};
|
||||
template<typename T>
|
||||
struct has_specialized_into: decltype(has_specialized_into_impl::check<T>(nullptr)){};
|
||||
template<typename T>
|
||||
struct has_specialized_try_from: decltype(has_specialized_try_from_impl::check<T>(nullptr)){};
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
#undef decltype
|
||||
|
||||
228
include/toml11/try_find.hpp
Normal file
228
include/toml11/try_find.hpp
Normal file
@@ -0,0 +1,228 @@
|
||||
#ifndef TOML11_TRY_FIND_HPP
|
||||
#define TOML11_TRY_FIND_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "try_get.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "value.hpp"
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// find<T>(value, key);
|
||||
|
||||
template<typename T, typename TC>
|
||||
decltype(try_get<T>(std::declval<basic_value<TC> const&>()))
|
||||
try_find(const basic_value<TC>& v, const typename basic_value<TC>::key_type& ky) noexcept
|
||||
{
|
||||
const auto res = v.try_at(ky);
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_get<T>(res.as_ok());
|
||||
}
|
||||
|
||||
template<typename T, typename TC>
|
||||
decltype(try_get<T>(std::declval<basic_value<TC>&>()))
|
||||
try_find(basic_value<TC>& v, const typename basic_value<TC>::key_type& ky) noexcept
|
||||
{
|
||||
auto res = v.try_at(ky);
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_get<T>(res.as_ok());
|
||||
}
|
||||
|
||||
template<typename T, typename TC>
|
||||
decltype(try_get<T>(std::declval<basic_value<TC>&&>()))
|
||||
try_find(basic_value<TC>&& v, const typename basic_value<TC>::key_type& ky) noexcept
|
||||
{
|
||||
auto res = v.try_at(ky);
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_get<T>(std::move(res.as_ok()));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// find<T>(value, idx)
|
||||
|
||||
template<typename T, typename TC>
|
||||
decltype(try_get<T>(std::declval<basic_value<TC> const&>()))
|
||||
try_find(const basic_value<TC>& v, const std::size_t idx) noexcept
|
||||
{
|
||||
const auto res = v.try_at(idx);
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_get<T>(res.as_ok());
|
||||
}
|
||||
template<typename T, typename TC>
|
||||
decltype(try_get<T>(std::declval<basic_value<TC>&>()))
|
||||
try_find(basic_value<TC>& v, const std::size_t idx) noexcept
|
||||
{
|
||||
auto res = v.try_at(idx);
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_get<T>(res.as_ok());
|
||||
}
|
||||
template<typename T, typename TC>
|
||||
decltype(try_get<T>(std::declval<basic_value<TC>&&>()))
|
||||
try_find(basic_value<TC>&& v, const std::size_t idx) noexcept
|
||||
{
|
||||
auto res = v.try_at(idx);
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_get<T>(std::move(res.as_ok()));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// find(value, key/idx), w/o conversion
|
||||
|
||||
template<typename TC>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<std::reference_wrapper<basic_value<TC>>, error_info>>
|
||||
try_find(basic_value<TC>& v, const typename basic_value<TC>::key_type& ky) noexcept
|
||||
{
|
||||
return v.try_at(ky);
|
||||
}
|
||||
template<typename TC>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<std::reference_wrapper<const basic_value<TC>>, error_info>>
|
||||
try_find(basic_value<TC> const& v, const typename basic_value<TC>::key_type& ky) noexcept
|
||||
{
|
||||
return v.try_at(ky);
|
||||
}
|
||||
template<typename TC>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<basic_value<TC>, error_info>>
|
||||
try_find(basic_value<TC>&& v, const typename basic_value<TC>::key_type& ky) noexcept
|
||||
{
|
||||
auto res = v.try_at(ky);
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return ok(basic_value<TC>(std::move(res.as_ok())));
|
||||
}
|
||||
|
||||
template<typename TC>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<std::reference_wrapper<basic_value<TC>>, error_info>>
|
||||
try_find(basic_value<TC>& v, const std::size_t idx) noexcept
|
||||
{
|
||||
return v.try_at(idx);
|
||||
}
|
||||
template<typename TC>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<std::reference_wrapper<const basic_value<TC>>, error_info>>
|
||||
try_find(basic_value<TC> const& v, const std::size_t idx) noexcept
|
||||
{
|
||||
return v.try_at(idx);
|
||||
}
|
||||
template<typename TC>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<basic_value<TC>, error_info>>
|
||||
try_find(basic_value<TC>&& v, const std::size_t idx) noexcept
|
||||
{
|
||||
auto res = v.try_at(idx);
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(std::move(res.as_err()));
|
||||
}
|
||||
return ok(basic_value<TC>(std::move(res.as_ok())));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// toml::find(toml::value, toml::key, Ts&& ... keys) w/o conversion
|
||||
|
||||
template<typename TC, typename K1, typename K2, typename ... Ks>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<std::reference_wrapper<const basic_value<TC>>, error_info>>
|
||||
try_find(const basic_value<TC>& v, const K1& k1, const K2& k2, const Ks& ... ks) noexcept
|
||||
{
|
||||
auto res = v.try_at(detail::key_cast<TC>(k1));
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_find(res.as_ok(), detail::key_cast<TC>(k2), ks...);
|
||||
}
|
||||
template<typename TC, typename K1, typename K2, typename ... Ks>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<std::reference_wrapper<basic_value<TC>>, error_info>>
|
||||
try_find(basic_value<TC>& v, const K1& k1, const K2& k2, const Ks& ... ks) noexcept
|
||||
{
|
||||
auto res = v.try_at(detail::key_cast<TC>(k1));
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_find(res.as_ok(), detail::key_cast<TC>(k2), ks...);
|
||||
}
|
||||
template<typename TC, typename K1, typename K2, typename ... Ks>
|
||||
cxx::enable_if_t<detail::is_type_config<TC>::value,
|
||||
result<basic_value<TC>, error_info>>
|
||||
try_find(basic_value<TC>&& v, const K1& k1, const K2& k2, const Ks& ... ks) noexcept
|
||||
{
|
||||
auto res = v.try_at(detail::key_cast<TC>(k1));
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_find(std::move(res.as_ok()), detail::key_cast<TC>(k2), ks...);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// find<T>(v, keys...)
|
||||
|
||||
template<typename T, typename TC, typename K1, typename K2, typename ... Ks>
|
||||
decltype(::toml::try_get<T>(std::declval<const basic_value<TC>&>()))
|
||||
try_find(const basic_value<TC>& v, const K1& k1, const K2& k2, const Ks& ... ks) noexcept
|
||||
{
|
||||
auto res = v.try_at(detail::key_cast<TC>(k1));
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_find<T>(res.as_ok(), detail::key_cast<TC>(k2), ks...);
|
||||
}
|
||||
template<typename T, typename TC, typename K1, typename K2, typename ... Ks>
|
||||
decltype(::toml::try_get<T>(std::declval<basic_value<TC>&>()))
|
||||
try_find(basic_value<TC>& v, const K1& k1, const K2& k2, const Ks& ... ks) noexcept
|
||||
{
|
||||
auto res = v.try_at(detail::key_cast<TC>(k1));
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_find<T>(res.as_ok(), detail::key_cast<TC>(k2), ks...);
|
||||
}
|
||||
template<typename T, typename TC, typename K1, typename K2, typename ... Ks>
|
||||
decltype(::toml::try_get<T>(std::declval<basic_value<TC>&&>()))
|
||||
try_find(basic_value<TC>&& v, const K1& k1, const K2& k2, const Ks& ... ks) noexcept
|
||||
{
|
||||
auto res = v.try_at(detail::key_cast<TC>(k1));
|
||||
if(res.is_err())
|
||||
{
|
||||
return err(res.as_err());
|
||||
}
|
||||
return try_find<T>(std::move(res.as_ok()), detail::key_cast<TC>(k2), ks...);
|
||||
}
|
||||
|
||||
} // toml
|
||||
#endif // TOML11_FIND_HPP
|
||||
472
include/toml11/try_get.hpp
Normal file
472
include/toml11/try_get.hpp
Normal file
@@ -0,0 +1,472 @@
|
||||
#ifndef TOML11_TRY_GET_HPP
|
||||
#define TOML11_TRY_GET_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "error_info.hpp"
|
||||
#include "from.hpp"
|
||||
#include "types.hpp"
|
||||
#include "value.hpp"
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
#include <string_view>
|
||||
#endif // string_view
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
// ============================================================================
|
||||
// T is toml::value; identity transformation.
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<std::is_same<T, basic_value<TC>>::value,
|
||||
result<std::reference_wrapper<T>, error_info>>
|
||||
try_get(basic_value<TC>& v) noexcept
|
||||
{
|
||||
return ok(std::ref(v));
|
||||
}
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<std::is_same<T, basic_value<TC>>::value,
|
||||
result<std::reference_wrapper<const T>, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
return ok(std::cref(v));
|
||||
}
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<std::is_same<T, basic_value<TC>>::value,
|
||||
result<T, error_info>>
|
||||
try_get(basic_value<TC>&& v) noexcept
|
||||
{
|
||||
return ok(basic_value<TC>(std::move(v)));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// exact toml::* type
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_exact_toml_type<T, basic_value<TC>>::value,
|
||||
result<std::reference_wrapper<T>, error_info>>
|
||||
try_get(basic_value<TC>& v) noexcept
|
||||
{
|
||||
constexpr auto ty = detail::type_to_enum<T, basic_value<TC>>::value;
|
||||
if(v.type() == ty)
|
||||
{
|
||||
return ok(std::ref(detail::getter<TC, ty>::get_nothrow(v)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return err(detail::make_type_error(v, "toml::try_get()", ty));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_exact_toml_type<T, basic_value<TC>>::value,
|
||||
result<std::reference_wrapper<const T>, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
constexpr auto ty = detail::type_to_enum<T, basic_value<TC>>::value;
|
||||
if(v.type() == ty)
|
||||
{
|
||||
return ok(std::cref(detail::getter<TC, ty>::get_nothrow(v)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return err(detail::make_type_error(v, "toml::try_get()", ty));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_exact_toml_type<T, basic_value<TC>>::value,
|
||||
result<T, error_info>>
|
||||
try_get(basic_value<TC>&& v) noexcept
|
||||
{
|
||||
constexpr auto ty = detail::type_to_enum<T, basic_value<TC>>::value;
|
||||
if(v.type() == ty)
|
||||
{
|
||||
return ok(detail::getter<TC, ty>::get_nothrow(std::move(v)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return err(detail::make_type_error(v, "toml::try_get()", ty));
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// T is toml::basic_value<U>
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_basic_value<T>,
|
||||
cxx::negation<std::is_same<T, basic_value<TC>>>
|
||||
>::value, result<T, error_info>>
|
||||
try_get(basic_value<TC> v) noexcept
|
||||
{
|
||||
return ok(T(std::move(v)));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// integer convertible from toml::value::integer_type
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
std::is_integral<T>,
|
||||
cxx::negation<std::is_same<T, bool>>,
|
||||
detail::is_not_toml_type<T, basic_value<TC>>,
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>,
|
||||
cxx::negation<detail::has_specialized_from<T>>
|
||||
>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.is_integer())
|
||||
{
|
||||
return ok(static_cast<T>(v.as_integer(std::nothrow)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::integer));
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// floating point convertible from toml::value::floating_type
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
std::is_floating_point<T>,
|
||||
detail::is_not_toml_type<T, basic_value<TC>>,
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>,
|
||||
cxx::negation<detail::has_specialized_from<T>>
|
||||
>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.is_floating())
|
||||
{
|
||||
return ok(static_cast<T>(v.as_floating(std::nothrow)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::floating));
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::string_view
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<std::is_same<T, std::string_view>::value,
|
||||
result<std::string_view, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.is_string())
|
||||
{
|
||||
return ok(std::string_view(v.as_string(std::nothrow)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::string));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // string_view
|
||||
|
||||
// ============================================================================
|
||||
// std::chrono::duration from toml::local_time
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_chrono_duration<T>::value,
|
||||
result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.is_local_time())
|
||||
{
|
||||
return ok(std::chrono::duration_cast<T>(
|
||||
std::chrono::nanoseconds(v.as_local_time(std::nothrow))));
|
||||
}
|
||||
else
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::local_time));
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::chrono::system_clock::time_point from toml::datetime variants
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<std::is_same<std::chrono::system_clock::time_point, T>::value,
|
||||
result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
switch(v.type())
|
||||
{
|
||||
case value_t::local_date:
|
||||
{
|
||||
return ok(std::chrono::system_clock::time_point(v.as_local_date(std::nothrow)));
|
||||
}
|
||||
case value_t::local_datetime:
|
||||
{
|
||||
return ok(std::chrono::system_clock::time_point(v.as_local_datetime(std::nothrow)));
|
||||
}
|
||||
case value_t::offset_datetime:
|
||||
{
|
||||
return ok(std::chrono::system_clock::time_point(v.as_offset_datetime(std::nothrow)));
|
||||
}
|
||||
default:
|
||||
{
|
||||
const auto loc = v.location();
|
||||
return err(make_error_info("toml::try_get(): bad_cast to "
|
||||
"std::chrono::system_clock::time_point", loc,
|
||||
"the actual type is " + to_string(v.type())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// array-like types; most likely STL container, like std::vector, etc.
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::has_push_back_method<T>, // .push_back() works
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::array
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.type() != toml::value_t::array)
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::array));
|
||||
}
|
||||
|
||||
using value_type = typename T::value_type;
|
||||
const auto& a = v.as_array(std::nothrow);
|
||||
|
||||
T container;
|
||||
detail::try_reserve(container, a.size()); // if T has .reserve(), call it
|
||||
|
||||
for(const auto& elem : a)
|
||||
{
|
||||
auto converted = try_get<value_type>(elem);
|
||||
if(converted.is_err())
|
||||
{
|
||||
return err(converted.as_err());
|
||||
}
|
||||
container.push_back(std::move(converted.as_ok()));
|
||||
}
|
||||
return ok(container);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::array
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_std_array<T>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.type() != toml::value_t::array)
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::array));
|
||||
}
|
||||
|
||||
using value_type = typename T::value_type;
|
||||
const auto& a = v.as_array(std::nothrow);
|
||||
|
||||
T container;
|
||||
if(a.size() != container.size())
|
||||
{
|
||||
const auto loc = v.location();
|
||||
return err(make_error_info("toml::try_get: while converting to an array: "
|
||||
" array size is " + std::to_string(container.size()) +
|
||||
" but there are " + std::to_string(a.size()) + " elements in toml array.",
|
||||
loc, "here"));
|
||||
}
|
||||
for(std::size_t i=0; i<a.size(); ++i)
|
||||
{
|
||||
auto converted = try_get<value_type>(a[i]);
|
||||
if(converted.is_err())
|
||||
{
|
||||
return err(converted.as_err());
|
||||
}
|
||||
container[i] = std::move(converted.as_ok());
|
||||
}
|
||||
return ok(container);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::forward_list
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_std_forward_list<T>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.type() != toml::value_t::array)
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::array));
|
||||
}
|
||||
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
T container;
|
||||
for(const auto& elem : v.as_array(std::nothrow))
|
||||
{
|
||||
auto converted = try_get<value_type>(elem);
|
||||
if(converted.is_err())
|
||||
{
|
||||
return err(converted.as_err());
|
||||
}
|
||||
container.push_front(std::move(converted.as_ok()));
|
||||
}
|
||||
container.reverse();
|
||||
return ok(container);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::pair
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_std_pair<T>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.type() != toml::value_t::array)
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::array));
|
||||
}
|
||||
|
||||
using first_type = typename T::first_type;
|
||||
using second_type = typename T::second_type;
|
||||
|
||||
const auto& ar = v.as_array(std::nothrow);
|
||||
if(ar.size() != 2)
|
||||
{
|
||||
const auto loc = v.location();
|
||||
return err(make_error_info("toml::try_get: while converting std::pair: "
|
||||
" but there are " + std::to_string(ar.size()) +
|
||||
" > 2 elements in toml array.",
|
||||
loc, "here"));
|
||||
}
|
||||
|
||||
auto first_result = try_get<first_type>(ar[0]);
|
||||
if(first_result.is_err())
|
||||
{
|
||||
return err(first_result.as_err());
|
||||
}
|
||||
auto second_result = try_get<second_type>(ar[1]);
|
||||
if(second_result.is_err())
|
||||
{
|
||||
return err(second_result.as_err());
|
||||
}
|
||||
return ok(std::make_pair(std::move(first_result.as_ok()),
|
||||
std::move(second_result.as_ok())));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::tuple.
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename T, std::size_t I, std::size_t N>
|
||||
struct try_get_tuple_impl
|
||||
{
|
||||
template<typename Array, typename U>
|
||||
static result<T, error_info> invoke(const Array& a, U curr) noexcept
|
||||
{
|
||||
assert(I < a.size());
|
||||
using value_type = typename std::tuple_element<I, T>::type;
|
||||
|
||||
auto converted = try_get<value_type>(a[I]);
|
||||
if(converted.is_err())
|
||||
{
|
||||
return err(converted.as_err());
|
||||
}
|
||||
return try_get_tuple_impl<T, I+1, N>::invoke(a, std::tuple_cat(
|
||||
std::move(curr), std::make_tuple(std::move(converted.as_ok()))));
|
||||
}
|
||||
};
|
||||
template<typename T, std::size_t I>
|
||||
struct try_get_tuple_impl<T, I, I>
|
||||
{
|
||||
template<typename Array>
|
||||
static result<T, error_info> invoke(const Array&, T x) noexcept
|
||||
{
|
||||
return ok(std::move(x));
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_std_tuple<T>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
if(v.type() != toml::value_t::array)
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::array));
|
||||
}
|
||||
|
||||
const auto& ar = v.as_array(std::nothrow);
|
||||
if(ar.size() != std::tuple_size<T>::value)
|
||||
{
|
||||
const auto loc = v.location();
|
||||
return err(make_error_info("toml::try_get: while converting std::tuple: "
|
||||
" there are " + std::to_string(ar.size()) + " > " +
|
||||
std::to_string(std::tuple_size<T>::value) + " elements in toml array.",
|
||||
loc, "here"));
|
||||
}
|
||||
return detail::try_get_tuple_impl<T, 0, std::tuple_size<T>::value>::invoke(
|
||||
ar, std::make_tuple());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// map-like types; most likely STL map, like std::map or std::unordered_map.
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_map<T>, // T is map
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
using key_type = typename T::key_type;
|
||||
using mapped_type = typename T::mapped_type;
|
||||
static_assert(
|
||||
std::is_convertible<typename basic_value<TC>::key_type, key_type>::value,
|
||||
"toml::get only supports map type of which key_type is "
|
||||
"convertible from toml::basic_value::key_type.");
|
||||
|
||||
if(v.type() != toml::value_t::table)
|
||||
{
|
||||
return err(detail::make_type_error(v, "try_get()", toml::value_t::table));
|
||||
}
|
||||
|
||||
T m;
|
||||
for(const auto& kv : v.as_table(std::nothrow))
|
||||
{
|
||||
auto converted = try_get<mapped_type>(kv.second);
|
||||
if(converted.is_err())
|
||||
{
|
||||
return err(converted.as_err());
|
||||
}
|
||||
m.emplace(key_type(kv.first), std::move(converted.as_ok()));
|
||||
}
|
||||
return ok(m);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// user-defined type that defines `try_from<T>`.
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::has_specialized_try_from<T>::value, result<T, error_info>>
|
||||
try_get(const basic_value<TC>& v) noexcept
|
||||
{
|
||||
return ::toml::try_from<T>::try_from_toml(v);
|
||||
}
|
||||
|
||||
} // toml
|
||||
#endif // TOML11_TRY_GET_HPP
|
||||
@@ -99,6 +99,47 @@ inline std::string make_string(std::size_t len, char c)
|
||||
return std::string(len, c);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// It suppresses warnings by -Wsign-conversion when we pass integer literal
|
||||
// to toml::find. integer literal `0` is deduced as an int, and will be
|
||||
// converted to std::size_t. This causes sign-conversion.
|
||||
|
||||
template<typename TC>
|
||||
std::size_t key_cast(const std::size_t& v) noexcept
|
||||
{
|
||||
return v;
|
||||
}
|
||||
template<typename TC, typename T>
|
||||
cxx::enable_if_t<std::is_integral<cxx::remove_cvref_t<T>>::value, std::size_t>
|
||||
key_cast(const T& v) noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(v);
|
||||
}
|
||||
|
||||
// for string-like (string, string literal, string_view)
|
||||
|
||||
template<typename TC>
|
||||
typename basic_value<TC>::key_type const&
|
||||
key_cast(const typename basic_value<TC>::key_type& v) noexcept
|
||||
{
|
||||
return v;
|
||||
}
|
||||
template<typename TC>
|
||||
typename basic_value<TC>::key_type
|
||||
key_cast(const typename basic_value<TC>::key_type::value_type* v)
|
||||
{
|
||||
return typename basic_value<TC>::key_type(v);
|
||||
}
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
template<typename TC>
|
||||
typename basic_value<TC>::key_type
|
||||
key_cast(const std::string_view v)
|
||||
{
|
||||
return typename basic_value<TC>::key_type(v);
|
||||
}
|
||||
#endif // string_view
|
||||
|
||||
} // namespace detail
|
||||
} // namespace toml
|
||||
#endif // TOML11_UTILITY_HPP
|
||||
|
||||
@@ -50,6 +50,9 @@ error_info make_type_error(const basic_value<TC>&, const std::string&, const val
|
||||
template<typename TC>
|
||||
error_info make_not_found_error(const basic_value<TC>&, const std::string&, const std::string&);
|
||||
|
||||
template<typename TC>
|
||||
error_info make_not_found_error(const basic_value<TC>&, const std::string&, const std::size_t);
|
||||
|
||||
template<typename TC>
|
||||
void change_region_of_value(basic_value<TC>&, const basic_value<TC>&);
|
||||
|
||||
@@ -1613,6 +1616,44 @@ class basic_value
|
||||
assert(found->first == k);
|
||||
return found->second;
|
||||
}
|
||||
|
||||
result<std::reference_wrapper<value_type>, error_info>
|
||||
try_at(const key_type& k) noexcept
|
||||
{
|
||||
if(!this->is_table())
|
||||
{
|
||||
return err(detail::make_type_error(*this,
|
||||
"toml::value::try_at(key_type)", value_t::table));
|
||||
}
|
||||
auto& table = this->as_table(std::nothrow);
|
||||
const auto found = table.find(k);
|
||||
if(found == table.end())
|
||||
{
|
||||
return err(detail::make_not_found_error(*this,
|
||||
"toml::value::try_at(key_type)", k));
|
||||
}
|
||||
assert(found->first == k);
|
||||
return ok(std::ref(found->second));
|
||||
}
|
||||
result<std::reference_wrapper<const value_type>, error_info>
|
||||
try_at(const key_type& k) const noexcept
|
||||
{
|
||||
if(!this->is_table())
|
||||
{
|
||||
return err(detail::make_type_error(*this,
|
||||
"toml::value::try_at(key_type)", value_t::table));
|
||||
}
|
||||
const auto& table = this->as_table(std::nothrow);
|
||||
const auto found = table.find(k);
|
||||
if(found == table.end())
|
||||
{
|
||||
return err(detail::make_not_found_error(*this,
|
||||
"toml::value::try_at(key_type)", k));
|
||||
}
|
||||
assert(found->first == k);
|
||||
return ok(std::cref(found->second));
|
||||
}
|
||||
|
||||
value_type& operator[](const key_type& k)
|
||||
{
|
||||
if(this->is_empty())
|
||||
@@ -1688,6 +1729,41 @@ class basic_value
|
||||
return ar.at(idx);
|
||||
}
|
||||
|
||||
result<std::reference_wrapper<value_type>, error_info>
|
||||
try_at(const std::size_t& idx) noexcept
|
||||
{
|
||||
if(!this->is_array())
|
||||
{
|
||||
return err(detail::make_type_error(*this,
|
||||
"toml::value::try_at(key_type)", value_t::array));
|
||||
}
|
||||
auto& ar = this->as_array(std::nothrow);
|
||||
|
||||
if(ar.size() <= idx)
|
||||
{
|
||||
return err(detail::make_not_found_error(*this,
|
||||
"toml::value::try_at(idx)", idx));
|
||||
}
|
||||
return ok(std::ref(ar[idx]));
|
||||
}
|
||||
result<std::reference_wrapper<const value_type>, error_info>
|
||||
try_at(const std::size_t idx) const noexcept
|
||||
{
|
||||
if(!this->is_array())
|
||||
{
|
||||
return err(detail::make_type_error(*this,
|
||||
"toml::value::try_at(key_type)", value_t::array));
|
||||
}
|
||||
const auto& ar = this->as_array(std::nothrow);
|
||||
|
||||
if(ar.size() <= idx)
|
||||
{
|
||||
return err(detail::make_not_found_error(*this,
|
||||
"toml::value::try_at(idx)", idx));
|
||||
}
|
||||
return ok(std::cref(ar[idx]));
|
||||
}
|
||||
|
||||
value_type& operator[](const std::size_t idx) noexcept
|
||||
{
|
||||
// no check...
|
||||
@@ -1775,20 +1851,19 @@ class basic_value
|
||||
{
|
||||
switch(this->type_)
|
||||
{
|
||||
case value_t::boolean : { boolean_ .~boolean_storage (); break; }
|
||||
case value_t::integer : { integer_ .~integer_storage (); break; }
|
||||
case value_t::floating : { floating_ .~floating_storage (); break; }
|
||||
case value_t::string : { string_ .~string_storage (); break; }
|
||||
case value_t::offset_datetime : { offset_datetime_.~offset_datetime_storage (); break; }
|
||||
case value_t::local_datetime : { local_datetime_ .~local_datetime_storage (); break; }
|
||||
case value_t::local_date : { local_date_ .~local_date_storage (); break; }
|
||||
case value_t::local_time : { local_time_ .~local_time_storage (); break; }
|
||||
case value_t::array : { array_ .~array_storage (); break; }
|
||||
case value_t::table : { table_ .~table_storage (); break; }
|
||||
default : { break; }
|
||||
case value_t::boolean : { boolean_ .~boolean_storage (); return; }
|
||||
case value_t::integer : { integer_ .~integer_storage (); return; }
|
||||
case value_t::floating : { floating_ .~floating_storage (); return; }
|
||||
case value_t::string : { string_ .~string_storage (); return; }
|
||||
case value_t::offset_datetime : { offset_datetime_.~offset_datetime_storage (); return; }
|
||||
case value_t::local_datetime : { local_datetime_ .~local_datetime_storage (); return; }
|
||||
case value_t::local_date : { local_date_ .~local_date_storage (); return; }
|
||||
case value_t::local_time : { local_time_ .~local_time_storage (); return; }
|
||||
case value_t::array : { array_ .~array_storage (); return; }
|
||||
case value_t::table : { table_ .~table_storage (); return; }
|
||||
default : { return; }
|
||||
}
|
||||
this->type_ = value_t::empty;
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
@@ -2027,16 +2102,12 @@ operator>=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
||||
}
|
||||
|
||||
// error_info helper
|
||||
namespace detail
|
||||
{
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
||||
{
|
||||
return make_error_info_rec(std::move(e), v.location(), std::move(msg), std::forward<Ts>(tail)...);
|
||||
}
|
||||
} // detail
|
||||
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info(
|
||||
std::string title, const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
||||
@@ -2097,6 +2168,19 @@ error_info make_not_found_error(const basic_value<TC>& v, const std::string& fna
|
||||
}
|
||||
return error_info(title, locs);
|
||||
}
|
||||
template<typename TC>
|
||||
error_info make_not_found_error(const basic_value<TC>& v, const std::string& fname, const std::size_t idx)
|
||||
{
|
||||
if( ! v.is_array())
|
||||
{
|
||||
return make_type_error(v, fname, toml::value_t::array);
|
||||
}
|
||||
std::ostringstream oss;
|
||||
oss << "actual length (" << v.as_array(std::nothrow).size()
|
||||
<< ") is shorter than the specified index (" << idx << ").";
|
||||
return make_error_info(fname + ": no element corresponding to the index",
|
||||
v, oss.str());
|
||||
}
|
||||
|
||||
#define TOML11_DETAIL_GENERATE_COMPTIME_GETTER(ty) \
|
||||
template<typename TC> \
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#define TOML11_VERSION_MAJOR 4
|
||||
#define TOML11_VERSION_MINOR 0
|
||||
#define TOML11_VERSION_PATCH 3
|
||||
#define TOML11_VERSION_PATCH 1
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error "__cplusplus is not defined"
|
||||
@@ -57,11 +57,6 @@
|
||||
#define TOML11_CXX20_VALUE 202002L
|
||||
#endif//TOML11_CXX20_VALUE
|
||||
|
||||
#if defined(__cpp_char8_t)
|
||||
# if __cpp_char8_t >= 201811L
|
||||
# define TOML11_HAS_CHAR8_T 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= TOML11_CXX17_VALUE
|
||||
# if __has_include(<string_view>)
|
||||
|
||||
@@ -52,7 +52,8 @@ struct local_time_format_info;
|
||||
struct array_format_info;
|
||||
struct table_format_info;
|
||||
|
||||
template<typename Key, typename Val, typename Cmp, typename Allocator>
|
||||
template<typename Key, typename Val, typename Cmp = std::equal_to<Key>,
|
||||
typename Allocator = std::allocator<std::pair<Key, Val>>>
|
||||
class ordered_map;
|
||||
|
||||
struct syntax_error;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#define TOML11_VERSION_MAJOR 4
|
||||
#define TOML11_VERSION_MINOR 0
|
||||
#define TOML11_VERSION_PATCH 3
|
||||
#define TOML11_VERSION_PATCH 1
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error "__cplusplus is not defined"
|
||||
@@ -57,11 +57,6 @@
|
||||
#define TOML11_CXX20_VALUE 202002L
|
||||
#endif//TOML11_CXX20_VALUE
|
||||
|
||||
#if defined(__cpp_char8_t)
|
||||
# if __cpp_char8_t >= 201811L
|
||||
# define TOML11_HAS_CHAR8_T 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= TOML11_CXX17_VALUE
|
||||
# if __has_include(<string_view>)
|
||||
@@ -1948,7 +1943,7 @@ struct source_location
|
||||
static source_location current() { return source_location{}; }
|
||||
};
|
||||
|
||||
inline std::string to_string(const source_location&)
|
||||
inline std::string to_string(const source_location& loc)
|
||||
{
|
||||
return std::string("");
|
||||
}
|
||||
@@ -3589,7 +3584,7 @@ struct has_specialized_into_impl
|
||||
template<typename T>
|
||||
static std::false_type check(...);
|
||||
template<typename T, std::size_t S = sizeof(::toml::into<T>)>
|
||||
static std::true_type check(::toml::into<T>*);
|
||||
static std::true_type check(::toml::from<T>*);
|
||||
};
|
||||
|
||||
|
||||
@@ -4078,13 +4073,13 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.succ_);
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.as_ok());
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.fail_);
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.as_err());
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
@@ -4093,13 +4088,13 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.succ_));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.as_ok()));
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.fail_));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.as_err()));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
@@ -4110,13 +4105,13 @@ struct result
|
||||
this->cleanup();
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.succ_);
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.as_ok());
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.fail_);
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.as_err());
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
@@ -4128,13 +4123,13 @@ struct result
|
||||
this->cleanup();
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.succ_));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.as_ok()));
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.fail_));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.as_err()));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
@@ -5452,10 +5447,6 @@ struct error_info
|
||||
std::string suffix_; // hint or something like that
|
||||
};
|
||||
|
||||
// forward decl
|
||||
template<typename TypeConfig>
|
||||
class basic_value;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline error_info make_error_info_rec(error_info e)
|
||||
@@ -5468,10 +5459,6 @@ inline error_info make_error_info_rec(error_info e, std::string s)
|
||||
return e;
|
||||
}
|
||||
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
const basic_value<TC>& v, std::string msg, Ts&& ... tail);
|
||||
|
||||
template<typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
source_location loc, std::string msg, Ts&& ... tail)
|
||||
@@ -7350,20 +7337,19 @@ class basic_value
|
||||
{
|
||||
switch(this->type_)
|
||||
{
|
||||
case value_t::boolean : { boolean_ .~boolean_storage (); break; }
|
||||
case value_t::integer : { integer_ .~integer_storage (); break; }
|
||||
case value_t::floating : { floating_ .~floating_storage (); break; }
|
||||
case value_t::string : { string_ .~string_storage (); break; }
|
||||
case value_t::offset_datetime : { offset_datetime_.~offset_datetime_storage (); break; }
|
||||
case value_t::local_datetime : { local_datetime_ .~local_datetime_storage (); break; }
|
||||
case value_t::local_date : { local_date_ .~local_date_storage (); break; }
|
||||
case value_t::local_time : { local_time_ .~local_time_storage (); break; }
|
||||
case value_t::array : { array_ .~array_storage (); break; }
|
||||
case value_t::table : { table_ .~table_storage (); break; }
|
||||
default : { break; }
|
||||
case value_t::boolean : { boolean_ .~boolean_storage (); return; }
|
||||
case value_t::integer : { integer_ .~integer_storage (); return; }
|
||||
case value_t::floating : { floating_ .~floating_storage (); return; }
|
||||
case value_t::string : { string_ .~string_storage (); return; }
|
||||
case value_t::offset_datetime : { offset_datetime_.~offset_datetime_storage (); return; }
|
||||
case value_t::local_datetime : { local_datetime_ .~local_datetime_storage (); return; }
|
||||
case value_t::local_date : { local_date_ .~local_date_storage (); return; }
|
||||
case value_t::local_time : { local_time_ .~local_time_storage (); return; }
|
||||
case value_t::array : { array_ .~array_storage (); return; }
|
||||
case value_t::table : { table_ .~table_storage (); return; }
|
||||
default : { return; }
|
||||
}
|
||||
this->type_ = value_t::empty;
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
@@ -7602,16 +7588,12 @@ operator>=(const basic_value<TC>& lhs, const basic_value<TC>& rhs)
|
||||
}
|
||||
|
||||
// error_info helper
|
||||
namespace detail
|
||||
{
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info_rec(error_info e,
|
||||
const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
||||
{
|
||||
return make_error_info_rec(std::move(e), v.location(), std::move(msg), std::forward<Ts>(tail)...);
|
||||
}
|
||||
} // detail
|
||||
|
||||
template<typename TC, typename ... Ts>
|
||||
error_info make_error_info(
|
||||
std::string title, const basic_value<TC>& v, std::string msg, Ts&& ... tail)
|
||||
@@ -10997,7 +10979,6 @@ TOML11_INLINE either string(const spec& s)
|
||||
TOML11_INLINE non_ascii_key_char::non_ascii_key_char(const spec& s) noexcept
|
||||
{
|
||||
assert(s.v1_1_0_allow_non_english_in_bare_keys);
|
||||
(void)s; // for NDEBUG
|
||||
}
|
||||
|
||||
TOML11_INLINE std::uint32_t non_ascii_key_char::read_utf8(location& loc) const
|
||||
@@ -15082,7 +15063,7 @@ try_parse(std::istream& is, std::string fname = "unknown file", spec s = spec::d
|
||||
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize), '\0');
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
is.read(reinterpret_cast<char*>(letters.data()), fsize);
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(fname), std::move(s));
|
||||
@@ -15272,15 +15253,7 @@ try_parse(FILE* fp, std::string filename, spec s = spec::default_version())
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
const auto actual = std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
if(actual != static_cast<std::size_t>(fsize))
|
||||
{
|
||||
return err(std::vector<error_info>{error_info(
|
||||
std::string("File size changed: \"") + filename +
|
||||
std::string("\" make sure that FILE* is in binary mode "
|
||||
"to avoid LF <-> CRLF conversion"), {}
|
||||
)});
|
||||
}
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(filename), std::move(s));
|
||||
}
|
||||
@@ -15318,12 +15291,7 @@ parse(FILE* fp, std::string filename, spec s = spec::default_version())
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize));
|
||||
const auto actual = std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
if(actual != static_cast<std::size_t>(fsize))
|
||||
{
|
||||
throw file_io_error(errno, "File size changed; make sure that "
|
||||
"FILE* is in binary mode to avoid LF <-> CRLF conversion", filename);
|
||||
}
|
||||
std::fread(letters.data(), sizeof(char), static_cast<std::size_t>(fsize), fp);
|
||||
|
||||
auto res = detail::parse_impl<TC>(std::move(letters), std::move(filename), std::move(s));
|
||||
if(res.is_ok())
|
||||
@@ -15407,6 +15375,12 @@ inline namespace toml_literals
|
||||
|
||||
::toml::value operator"" _toml(const char* str, std::size_t len);
|
||||
|
||||
#if defined(__cpp_char8_t)
|
||||
# if __cpp_char8_t >= 201811L
|
||||
# define TOML11_HAS_CHAR8_T 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(TOML11_HAS_CHAR8_T)
|
||||
// value of u8"" literal has been changed from char to char8_t and char8_t is
|
||||
// NOT compatible to char
|
||||
|
||||
@@ -99,7 +99,6 @@ if(TOML11_PRECOMPILE)
|
||||
# required options to use toml11 with MSVC
|
||||
if(MSVC)
|
||||
target_compile_options(toml11 PUBLIC "/utf-8")
|
||||
target_compile_options(toml11 PRIVATE "/W4" "/WX")
|
||||
if(MSVC_VERSION LESS 1910)
|
||||
message(STATUS "MSVC < 1910. DEFINE_CONVERSION_NON_INTRUSIVE is disabled")
|
||||
target_compile_definitions(toml11 PUBLIC -DTOML11_WITHOUT_DEFINE_NON_INTRUSIVE)
|
||||
@@ -108,22 +107,6 @@ if(TOML11_PRECOMPILE)
|
||||
else() # MSVC 2019
|
||||
target_compile_options(toml11 PUBLIC "/Zc:preprocessor")
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(toml11 PRIVATE
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WERROR}>: -Werror >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
add_library(toml11 INTERFACE)
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
set(TOML11_TEST_NAMES
|
||||
test_comments
|
||||
test_datetime
|
||||
test_error_message
|
||||
test_find
|
||||
test_try_find
|
||||
test_find_or
|
||||
test_format_integer
|
||||
test_format_floating
|
||||
test_format_table
|
||||
test_get
|
||||
test_try_get
|
||||
test_get_or
|
||||
test_location
|
||||
test_literal
|
||||
@@ -23,7 +24,6 @@ set(TOML11_TEST_NAMES
|
||||
test_parse_table
|
||||
test_result
|
||||
test_scanner
|
||||
test_serialize
|
||||
test_syntax_boolean
|
||||
test_syntax_integer
|
||||
test_syntax_floating
|
||||
@@ -41,6 +41,23 @@ set(TOML11_TEST_NAMES
|
||||
test_visit
|
||||
)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
check_cxx_compiler_flag("-Wall" COMPILER_SUPPORTS_WALL)
|
||||
check_cxx_compiler_flag("-Wextra" COMPILER_SUPPORTS_WEXTRA)
|
||||
check_cxx_compiler_flag("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
|
||||
check_cxx_compiler_flag("-Werror" COMPILER_SUPPORTS_WERROR)
|
||||
|
||||
check_cxx_compiler_flag("-Wsign-conversion" COMPILER_SUPPORTS_WSIGN_CONVERSION)
|
||||
check_cxx_compiler_flag("-Wconversion" COMPILER_SUPPORTS_WCONVERSION)
|
||||
check_cxx_compiler_flag("-Wduplicated-cond" COMPILER_SUPPORTS_WDUPLICATED_COND)
|
||||
check_cxx_compiler_flag("-Wduplicated-branches" COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
|
||||
check_cxx_compiler_flag("-Wlogical-op" COMPILER_SUPPORTS_WLOGICAL_OP)
|
||||
check_cxx_compiler_flag("-Wdouble-promotion" COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
|
||||
check_cxx_compiler_flag("-Wrange-loop-analysis" COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS)
|
||||
check_cxx_compiler_flag("-Wundef" COMPILER_SUPPORTS_WUNDEF)
|
||||
check_cxx_compiler_flag("-Wshadow" COMPILER_SUPPORTS_WSHADOW)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_library(toml11_test_utility STATIC utility.cpp)
|
||||
target_include_directories(toml11_test_utility
|
||||
@@ -55,28 +72,27 @@ if(BUILD_TESTING)
|
||||
)
|
||||
target_link_libraries(${TEST_NAME} PUBLIC toml11 toml11_test_utility)
|
||||
if(MSVC)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W4 /WX)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W3)
|
||||
else()
|
||||
target_compile_options(${TEST_NAME} PRIVATE
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WERROR}>: -Werror >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
target_link_options(${TEST_NAME} PRIVATE
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
endif()
|
||||
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
|
||||
@@ -95,27 +111,27 @@ if(TOML11_BUILD_TOML_TESTS)
|
||||
)
|
||||
target_link_libraries(toml11_decoder PRIVATE toml11)
|
||||
if(MSVC)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W4 /WX)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W3)
|
||||
else()
|
||||
target_compile_options(toml11_decoder PRIVATE
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
target_link_options(toml11_decoder PRIVATE
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -127,7 +143,7 @@ if(TOML11_BUILD_TOML_TESTS)
|
||||
target_compile_definitions(toml11_decoder_v1_1_0 PRIVATE -DTOML11_TO_JSON_USE_V1_1_0)
|
||||
target_link_libraries(toml11_decoder_v1_1_0 PRIVATE toml11)
|
||||
if(MSVC)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W4 /WX)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W3)
|
||||
else()
|
||||
target_compile_options(toml11_decoder_v1_1_0 PRIVATE
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
@@ -158,27 +174,27 @@ if(TOML11_BUILD_TOML_TESTS)
|
||||
)
|
||||
target_link_libraries(toml11_encoder PRIVATE toml11)
|
||||
if(MSVC)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W4 /WX)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W3)
|
||||
else()
|
||||
target_compile_options(toml11_encoder PRIVATE
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
target_link_options(toml11_encoder PRIVATE
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
endif()
|
||||
endif(TOML11_BUILD_TOML_TESTS)
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include "doctest.h"
|
||||
|
||||
#include <toml.hpp>
|
||||
|
||||
TEST_CASE("testing custom error message using source_location")
|
||||
{
|
||||
const toml::value root = toml::parse_str(R"(
|
||||
range = [0, 42]
|
||||
val = 54
|
||||
)");
|
||||
|
||||
const auto& lower = root.at("range").at(0);
|
||||
const auto& upper = root.at("range").at(1);
|
||||
const auto& val = root.at("val");
|
||||
|
||||
const auto err = toml::make_error_info("val not in range",
|
||||
lower.location(), "lower limit is defined here",
|
||||
upper.location(), "upper limit is defined here",
|
||||
val.location(), "this is not in the range",
|
||||
"Hint: upper limit is inclusive"
|
||||
);
|
||||
|
||||
CHECK_EQ(err.title(), "val not in range");
|
||||
CHECK_EQ(err.locations().size(), 3);
|
||||
CHECK_EQ(err.locations().at(0).second, "lower limit is defined here");
|
||||
CHECK_EQ(err.locations().at(1).second, "upper limit is defined here");
|
||||
CHECK_EQ(err.locations().at(2).second, "this is not in the range" );
|
||||
}
|
||||
|
||||
TEST_CASE("testing custom error message using value")
|
||||
{
|
||||
const toml::value root = toml::parse_str(R"(
|
||||
range = [0, 42]
|
||||
val = 54
|
||||
)");
|
||||
|
||||
const auto& lower = root.at("range").at(0);
|
||||
const auto& upper = root.at("range").at(1);
|
||||
const auto& val = root.at("val");
|
||||
|
||||
const auto err = toml::make_error_info("val not in range",
|
||||
lower, "lower limit is defined here",
|
||||
upper, "upper limit is defined here",
|
||||
val, "this is not in the range",
|
||||
"Hint: upper limit is inclusive"
|
||||
);
|
||||
|
||||
CHECK_EQ(err.title(), "val not in range");
|
||||
CHECK_EQ(err.locations().size(), 3);
|
||||
CHECK_EQ(err.locations().at(0).second, "lower limit is defined here");
|
||||
CHECK_EQ(err.locations().at(1).second, "upper limit is defined here");
|
||||
CHECK_EQ(err.locations().at(2).second, "this is not in the range" );
|
||||
}
|
||||
|
||||
TEST_CASE("testing custom error message using source_location and value")
|
||||
{
|
||||
const toml::value root = toml::parse_str(R"(
|
||||
range = [0, 42]
|
||||
val = 54
|
||||
)");
|
||||
|
||||
const auto& lower = root.at("range").at(0);
|
||||
const auto& upper = root.at("range").at(1);
|
||||
const auto& val = root.at("val");
|
||||
|
||||
const auto err = toml::make_error_info("val not in range",
|
||||
lower, "lower limit is defined here",
|
||||
upper, "upper limit is defined here",
|
||||
val.location(), "this is not in the range",
|
||||
"Hint: upper limit is inclusive"
|
||||
);
|
||||
|
||||
CHECK_EQ(err.title(), "val not in range");
|
||||
CHECK_EQ(err.locations().size(), 3);
|
||||
CHECK_EQ(err.locations().at(0).second, "lower limit is defined here");
|
||||
CHECK_EQ(err.locations().at(1).second, "upper limit is defined here");
|
||||
CHECK_EQ(err.locations().at(2).second, "this is not in the range" );
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include "doctest.h"
|
||||
|
||||
#include <toml.hpp>
|
||||
|
||||
#include <clocale>
|
||||
|
||||
TEST_CASE("testing serialization")
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
|
||||
const auto spec_example = R"(# This is a TOML document
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob = 1979-05-27T07:32:00-08:00
|
||||
|
||||
[database]
|
||||
enabled = true
|
||||
ports = [ 8000, 8001, 8002 ]
|
||||
data = [ ["delta", "phi"], [3.14] ]
|
||||
temp_targets = { cpu = 79.5, case = 72.0 }
|
||||
|
||||
[servers]
|
||||
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
role = "frontend"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
role = "backend")"_toml;
|
||||
|
||||
// format and parse
|
||||
const auto v = toml::parse_str(toml::format(spec_example));
|
||||
|
||||
CHECK_EQ(v, spec_example);
|
||||
}
|
||||
|
||||
TEST_CASE("testing serialization with complicated keys")
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
|
||||
const auto spec_example = R"(
|
||||
[keys]
|
||||
|
||||
key = "value"
|
||||
bare_key = "value"
|
||||
bare-key = "value"
|
||||
1234 = "value"
|
||||
|
||||
"127.0.0.1" = "value"
|
||||
"character encoding" = "value"
|
||||
"ʎǝʞ" = "value"
|
||||
'key2' = "value"
|
||||
'quoted "value"' = "value"
|
||||
|
||||
"" = "blank"
|
||||
|
||||
fruits.apple.skin = "thin"
|
||||
fruits.apple.color = "red"
|
||||
|
||||
fruits.orange.skin = "thick"
|
||||
fruits.orange.color = "orange"
|
||||
|
||||
site."google.com" = true
|
||||
3.14159 = "pi"
|
||||
)"_toml;
|
||||
|
||||
// format and parse
|
||||
const auto v = toml::parse_str(toml::format(spec_example));
|
||||
|
||||
CHECK_EQ(v, spec_example);
|
||||
}
|
||||
|
||||
TEST_CASE("testing serialization with array of tables")
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
|
||||
const auto spec_example = R"(
|
||||
points = [ { x = 1, y = 2, z = 3 },
|
||||
{ x = 7, y = 8, z = 9 },
|
||||
{ x = 2, y = 4, z = 8 } ]
|
||||
|
||||
[[products]]
|
||||
name = "Hammer"
|
||||
sku = 738594937
|
||||
|
||||
[[products]] # empty table within the array
|
||||
|
||||
[[products]]
|
||||
name = "Nail"
|
||||
sku = 284758393
|
||||
|
||||
color = "gray"
|
||||
|
||||
[[fruits]]
|
||||
name = "apple"
|
||||
|
||||
[fruits.physical] # subtable
|
||||
color = "red"
|
||||
shape = "round"
|
||||
|
||||
[[fruits.varieties]] # nested array of tables
|
||||
name = "red delicious"
|
||||
|
||||
[[fruits.varieties]]
|
||||
name = "granny smith"
|
||||
|
||||
[[fruits]]
|
||||
name = "banana"
|
||||
|
||||
[[fruits.varieties]]
|
||||
name = "plantain"
|
||||
)"_toml;
|
||||
|
||||
// format and parse
|
||||
const auto v = toml::parse_str(toml::format(spec_example));
|
||||
|
||||
CHECK_EQ(v, spec_example);
|
||||
}
|
||||
|
||||
TEST_CASE("testing serialization with locale")
|
||||
{
|
||||
std::string current_locale = std::setlocale(LC_ALL, nullptr);
|
||||
|
||||
// fr_FR is a one of locales that uses `,` as a decimal separator.
|
||||
if(const char* try_hyphen = std::setlocale(LC_ALL, "fr_FR.UTF-8"))
|
||||
{
|
||||
current_locale = std::string(try_hyphen);
|
||||
}
|
||||
else if(const char* try_nohyphen = std::setlocale(LC_ALL, "fr_FR.utf8"))
|
||||
{
|
||||
current_locale = std::string(try_nohyphen);
|
||||
}
|
||||
|
||||
MESSAGE("current_locale = ", current_locale);
|
||||
|
||||
const auto v1 = toml::parse_str(R"(
|
||||
pi = 3.1415_9265
|
||||
large_int = 123_456_789
|
||||
)");
|
||||
const auto v2 = toml::parse_str(toml::format(v1));
|
||||
|
||||
// actually, it checkl if v1 is serialized correctly under FR locale
|
||||
// where 3.1415 -> 3,1415
|
||||
CHECK_EQ(v1, v2);
|
||||
}
|
||||
829
tests/test_try_find.cpp
Normal file
829
tests/test_try_find.cpp
Normal file
@@ -0,0 +1,829 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include "doctest.h"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <toml11/value.hpp>
|
||||
#include <toml11/try_find.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
namespace toml
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
std::tm localtime_s(const std::time_t* src);
|
||||
std::tm gmtime_s(const std::time_t* src);
|
||||
} // detail
|
||||
} // toml
|
||||
|
||||
TEST_CASE("testing toml::try_find with toml type")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
using boolean_type = typename value_type::boolean_type ;
|
||||
using integer_type = typename value_type::integer_type ;
|
||||
using floating_type = typename value_type::floating_type ;
|
||||
using string_type = typename value_type::string_type ;
|
||||
using local_time_type = typename value_type::local_time_type ;
|
||||
using local_date_type = typename value_type::local_date_type ;
|
||||
using local_datetime_type = typename value_type::local_datetime_type ;
|
||||
using offset_datetime_type = typename value_type::offset_datetime_type;
|
||||
using array_type = typename value_type::array_type ;
|
||||
using table_type = typename value_type::table_type ;
|
||||
|
||||
{
|
||||
value_type v(toml::table{{"a", true}});
|
||||
CHECK_EQ(true, toml::try_find<boolean_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<boolean_type>(v, "a").unwrap() = false;
|
||||
CHECK_EQ(false, toml::try_find<boolean_type>(v, "a").unwrap());
|
||||
|
||||
boolean_type x = toml::try_find<boolean_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(false, x);
|
||||
}
|
||||
{
|
||||
value_type v(toml::table{{"a", 42}});
|
||||
CHECK_EQ(integer_type(42), toml::try_find<integer_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<integer_type>(v, "a").unwrap() = 54;
|
||||
CHECK_EQ(integer_type(54), toml::try_find<integer_type>(v, "a").unwrap());
|
||||
|
||||
integer_type x = toml::try_find<integer_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(integer_type(54), x);
|
||||
}
|
||||
{
|
||||
value_type v(toml::table{{"a", 3.14}});
|
||||
CHECK_EQ(floating_type(3.14), toml::try_find<floating_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<floating_type>(v, "a").unwrap() = 2.71;
|
||||
CHECK_EQ(floating_type(2.71), toml::try_find<floating_type>(v, "a").unwrap());
|
||||
|
||||
floating_type x = toml::try_find<floating_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(floating_type(2.71), x);
|
||||
}
|
||||
{
|
||||
value_type v(toml::table{{"a", "foo"}});
|
||||
CHECK_EQ("foo", toml::try_find<string_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<string_type>(v, "a").unwrap() += "bar";
|
||||
CHECK_EQ("foobar", toml::try_find<string_type>(v, "a").unwrap());
|
||||
|
||||
string_type x = toml::try_find<string_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ("foobar", x);
|
||||
}
|
||||
{
|
||||
local_date_type d(2018, toml::month_t::Apr, 22);
|
||||
value_type v(toml::table{{"a", d}});
|
||||
CHECK_EQ(d, toml::try_find<local_date_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<local_date_type>(v, "a").unwrap().year = 2017;
|
||||
d.year = 2017;
|
||||
CHECK_EQ(d, toml::try_find<local_date_type>(v, "a").unwrap());
|
||||
|
||||
local_date_type x = toml::try_find<local_date_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(d, x);
|
||||
}
|
||||
{
|
||||
local_time_type t(12, 30, 45);
|
||||
value_type v(toml::table{{"a", t}});
|
||||
CHECK_EQ(t, toml::try_find<local_time_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<local_time_type>(v, "a").unwrap().hour = 9;
|
||||
t.hour = 9;
|
||||
CHECK_EQ(t, toml::try_find<local_time_type>(v, "a").unwrap());
|
||||
|
||||
local_time_type x = toml::try_find<local_time_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(t, x);
|
||||
}
|
||||
{
|
||||
local_datetime_type dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
||||
toml::local_time(12, 30, 45));
|
||||
value_type v(toml::table{{"a", dt}});
|
||||
CHECK_EQ(dt, toml::try_find<local_datetime_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<local_datetime_type>(v, "a").unwrap().date.year = 2017;
|
||||
dt.date.year = 2017;
|
||||
CHECK_EQ(dt, toml::try_find<local_datetime_type>(v, "a").unwrap());
|
||||
|
||||
toml::local_datetime x = toml::try_find<local_datetime_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(dt, x);
|
||||
}
|
||||
{
|
||||
offset_datetime_type dt(toml::local_datetime(
|
||||
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||
toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
|
||||
value_type v(toml::table{{"a", dt}});
|
||||
CHECK_EQ(dt, toml::try_find<offset_datetime_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<toml::offset_datetime>(v, "a").unwrap().date.year = 2017;
|
||||
dt.date.year = 2017;
|
||||
CHECK_EQ(dt, toml::try_find<offset_datetime_type>(v, "a").unwrap());
|
||||
|
||||
offset_datetime_type x = toml::try_find<offset_datetime_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(dt, x);
|
||||
}
|
||||
{
|
||||
array_type vec;
|
||||
vec.push_back(value_type(42));
|
||||
vec.push_back(value_type(54));
|
||||
value_type v(toml::table{{"a", vec}});
|
||||
CHECK_EQ(vec, toml::try_find<array_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<array_type>(v, "a").unwrap().push_back(value_type(123));
|
||||
vec.push_back(value_type(123));
|
||||
CHECK_EQ(vec, toml::try_find<array_type>(v, "a").unwrap());
|
||||
|
||||
array_type x = toml::try_find<array_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(vec, x);
|
||||
}
|
||||
{
|
||||
table_type tab;
|
||||
tab["key1"] = value_type(42);
|
||||
tab["key2"] = value_type(3.14);
|
||||
value_type v(toml::table{{"a", tab}});
|
||||
CHECK_EQ(tab, toml::try_find<table_type>(v, "a").unwrap());
|
||||
|
||||
toml::try_find<table_type>(v, "a").unwrap()["key3"] = value_type(123);
|
||||
tab["key3"] = value_type(123);
|
||||
CHECK_EQ(tab, toml::try_find<table_type>(v, "a").unwrap());
|
||||
|
||||
table_type x = toml::try_find<table_type>(std::move(v), "a").unwrap();
|
||||
CHECK_EQ(tab, x);
|
||||
}
|
||||
{
|
||||
value_type v1(toml::table{{"a", 42}});
|
||||
CHECK_EQ(toml::value(42), toml::try_find(v1, "a").unwrap());
|
||||
|
||||
value_type v2(54);
|
||||
toml::try_find(v1, "a").unwrap() = v2;
|
||||
CHECK_EQ(v2, toml::try_find(v1, "a").unwrap());
|
||||
|
||||
value_type x = toml::try_find(std::move(v1), "a").unwrap();
|
||||
CHECK_EQ(v2, x);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing try_find fails")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
using boolean_type = typename value_type::boolean_type ;
|
||||
using integer_type = typename value_type::integer_type ;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// const-reference version
|
||||
{
|
||||
// value is not a table
|
||||
const toml::value v(true);
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(v, "key").is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not the expected type
|
||||
const toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(v, "key").is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not found
|
||||
const toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<integer_type>(v, "different_key").is_err());
|
||||
}
|
||||
{
|
||||
// the positive control.
|
||||
const toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<int>(v, "key").is_ok());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// reference version
|
||||
{
|
||||
// value is not a table
|
||||
toml::value v(true);
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(v, "key").is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not the expected type
|
||||
toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(v, "key").is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not found
|
||||
toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<integer_type>(v, "different_key").is_err());
|
||||
}
|
||||
{
|
||||
// the positive control.
|
||||
toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<int>(v, "key").is_ok());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// move version
|
||||
|
||||
{
|
||||
// value is not a table
|
||||
toml::value v(true);
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(std::move(v), "key").is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not the expected type
|
||||
toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(std::move(v), "key").is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not found
|
||||
toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<integer_type>(std::move(v), "different_key").is_err());
|
||||
}
|
||||
{
|
||||
// the positive control.
|
||||
toml::value v = toml::table{{"key", 42}};
|
||||
CHECK_UNARY(toml::try_find<int>(std::move(v), "key").is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find(v, idx) throws")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
using boolean_type = typename value_type::boolean_type ;
|
||||
using integer_type = typename value_type::integer_type ;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// const-reference version
|
||||
{
|
||||
// value is not an array
|
||||
const toml::value v(true);
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(v, 0).is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not the expected type
|
||||
const toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(v, 0).is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not found
|
||||
const toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<integer_type>(v, 6).is_err());
|
||||
}
|
||||
{
|
||||
// the positive control.
|
||||
const toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<int>(v, 2).is_ok());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// non-const reference version
|
||||
{
|
||||
// value is not an array
|
||||
toml::value v(true);
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(v, 0).is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not the expected type
|
||||
toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(v, 0).is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not found
|
||||
toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<integer_type>(v, 6).is_err());
|
||||
}
|
||||
{
|
||||
// the positive control.
|
||||
toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<int>(v, 2).is_ok());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// move version
|
||||
{
|
||||
// value is not an array
|
||||
toml::value v(true);
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(std::move(v), 0).is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not the expected type
|
||||
toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<boolean_type>(std::move(v), 0).is_err());
|
||||
}
|
||||
{
|
||||
// the value corresponding to the key is not found
|
||||
toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<integer_type>(std::move(v), 6).is_err());
|
||||
}
|
||||
{
|
||||
// the positive control.
|
||||
toml::value v = toml::array{1, 2, 3, 4, 5};
|
||||
CHECK_UNARY(toml::try_find<int>(std::move(v), 2).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find with recursive table/array")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
using integer_type = typename value_type::integer_type ;
|
||||
|
||||
// recursively search tables
|
||||
{
|
||||
toml::value v = toml::table{
|
||||
{"a", toml::table{
|
||||
{"b", toml::table{
|
||||
{"c", toml::table{
|
||||
{"d", 42}
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
};
|
||||
CHECK_EQ(42, toml::try_find<int>(v, "a", "b", "c", "d").unwrap());
|
||||
|
||||
// reference that can be used to modify the content
|
||||
auto num = toml::try_find<integer_type>(v, "a", "b", "c", "d");
|
||||
CHECK_UNARY(num.is_ok());
|
||||
num.unwrap() = 54;
|
||||
CHECK_EQ(54, toml::try_find<int>(v, "a", "b", "c", "d").unwrap());
|
||||
|
||||
const std::string a("a"), b("b"), c("c"), d("d");
|
||||
auto num2 = toml::try_find<integer_type>(v, a, b, c, d);
|
||||
CHECK_UNARY(num2.is_ok());
|
||||
num2.unwrap() = 42;
|
||||
CHECK_EQ(42, toml::try_find<int>(v, a, b, c, d).unwrap());
|
||||
|
||||
auto num3 = toml::try_find<integer_type>(v, a, "b", c, "d");
|
||||
CHECK_EQ(42, num3.unwrap());
|
||||
|
||||
auto num4 = toml::try_find<integer_type>(std::move(v), a, b, c, d);
|
||||
CHECK_EQ(42, num4.unwrap());
|
||||
}
|
||||
// recursively search arrays
|
||||
{
|
||||
toml::value v = toml::array{
|
||||
toml::array{"array", "of", "string"},
|
||||
toml::array{toml::array{1, 2, 3}, toml::array{3.14, 2.71}}
|
||||
};
|
||||
CHECK_EQ("array" , toml::try_find<std::string>(v, 0, 0).unwrap());
|
||||
CHECK_EQ("of" , toml::try_find<std::string>(v, 0, 1).unwrap());
|
||||
CHECK_EQ("string", toml::try_find<std::string>(v, 0, 2).unwrap());
|
||||
|
||||
CHECK_EQ(1, toml::try_find<int>(v, 1, 0, 0).unwrap());
|
||||
CHECK_EQ(2, toml::try_find<int>(v, 1, 0, 1).unwrap());
|
||||
CHECK_EQ(3, toml::try_find<int>(v, 1, 0, 2).unwrap());
|
||||
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, 1, 1, 0).unwrap());
|
||||
CHECK_EQ(2.71, toml::try_find<double>(v, 1, 1, 1).unwrap());
|
||||
|
||||
// reference that can be used to modify the content
|
||||
auto num = toml::try_find<integer_type>(v, 1, 0, 2);
|
||||
num.unwrap() = 42;
|
||||
CHECK_EQ( 1, toml::try_find<int>(v, 1, 0, 0).unwrap());
|
||||
CHECK_EQ( 2, toml::try_find<int>(v, 1, 0, 1).unwrap());
|
||||
CHECK_EQ(42, toml::try_find<int>(v, 1, 0, 2).unwrap());
|
||||
|
||||
// move value
|
||||
auto num2 = toml::try_find<integer_type>(std::move(v), 1, 0, 2);
|
||||
CHECK_EQ(42, num2.unwrap());
|
||||
}
|
||||
// recursively search mixtures
|
||||
{
|
||||
toml::value v = toml::table{{"array", toml::array{
|
||||
toml::array{1, 2, 3},
|
||||
toml::array{
|
||||
toml::table{{"foo", "bar"}, {"baz", "qux"}},
|
||||
toml::table{{"pi", 3.14}, {"e", 2.71}}
|
||||
}}
|
||||
}};
|
||||
|
||||
CHECK_EQ(1, toml::try_find<int>(v, "array", 0, 0).unwrap());
|
||||
CHECK_EQ(2, toml::try_find<int>(v, "array", 0, 1).unwrap());
|
||||
CHECK_EQ(3, toml::try_find<int>(v, "array", 0, 2).unwrap());
|
||||
|
||||
CHECK_EQ("bar", toml::try_find<std::string>(v, "array", 1, 0, "foo").unwrap());
|
||||
CHECK_EQ("qux", toml::try_find<std::string>(v, "array", 1, 0, "baz").unwrap());
|
||||
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, "array", 1, 1, "pi").unwrap());
|
||||
CHECK_EQ(2.71, toml::try_find<double>(v, "array", 1, 1, "e" ).unwrap());
|
||||
|
||||
const std::string ar("array");
|
||||
const auto ar_c = "array";
|
||||
|
||||
const std::string pi("pi");
|
||||
const auto pi_c = "pi";
|
||||
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, ar, 1, 1, "pi").unwrap());
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, ar, 1, 1, pi) .unwrap());
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, ar, 1, 1, pi_c).unwrap());
|
||||
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, ar_c, 1, 1, "pi").unwrap());
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, ar_c, 1, 1, pi) .unwrap());
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, ar_c, 1, 1, pi_c).unwrap());
|
||||
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, "array", 1, 1, pi) .unwrap());
|
||||
CHECK_EQ(3.14, toml::try_find<double>(v, "array", 1, 1, pi_c).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find integer conversion")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
{
|
||||
value_type v = toml::table{{"key", 42}};
|
||||
CHECK_EQ(int(42) , toml::try_find<int >(v, "key").unwrap());
|
||||
CHECK_EQ(short(42) , toml::try_find<short >(v, "key").unwrap());
|
||||
CHECK_EQ(char(42) , toml::try_find<char >(v, "key").unwrap());
|
||||
CHECK_EQ(unsigned(42) , toml::try_find<unsigned >(v, "key").unwrap());
|
||||
CHECK_EQ(long(42) , toml::try_find<long >(v, "key").unwrap());
|
||||
CHECK_EQ(std::int64_t(42) , toml::try_find<std::int64_t >(v, "key").unwrap());
|
||||
CHECK_EQ(std::uint64_t(42), toml::try_find<std::uint64_t>(v, "key").unwrap());
|
||||
CHECK_EQ(std::int16_t(42) , toml::try_find<std::int16_t >(v, "key").unwrap());
|
||||
CHECK_EQ(std::uint16_t(42), toml::try_find<std::uint16_t>(v, "key").unwrap());
|
||||
CHECK_EQ(std::uint16_t(42), toml::try_find<std::uint16_t>(std::move(v), "key").unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find floating conversion")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
{
|
||||
value_type v = toml::table{{"key", 3.14}};
|
||||
const double ref(3.14);
|
||||
CHECK_EQ(static_cast<float >(ref), toml::try_find<float >(v, "key").unwrap());
|
||||
CHECK_EQ( ref , toml::try_find<double >(v, "key").unwrap());
|
||||
CHECK_EQ(static_cast<long double>(ref), toml::try_find<long double>(v, "key").unwrap());
|
||||
CHECK_EQ(static_cast<float >(ref), toml::try_find<float >(std::move(v), "key").unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find string conversion")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
{
|
||||
value_type v = toml::table{{"key", "foo"}};
|
||||
CHECK_EQ("foo", toml::try_find<std::string>(v, "key").unwrap());
|
||||
toml::try_find<std::string>(v, "key").unwrap() += "bar";
|
||||
CHECK_EQ("foobar", toml::try_find<std::string>(v, "key").unwrap());
|
||||
}
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
{
|
||||
value_type v = toml::table{{"key", "foo"}};
|
||||
CHECK_EQ("foo", toml::try_find<std::string_view>(v, "key").unwrap());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find array conversion")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
value_type v = toml::table{{"key", toml::array{42, 54, 69, 72}}};
|
||||
|
||||
const std::vector<int> vec = toml::try_find<std::vector<int>>(v, "key").unwrap();
|
||||
const std::list<short> lst = toml::try_find<std::list<short>>(v, "key").unwrap();
|
||||
const std::deque<std::int64_t> deq = toml::try_find<std::deque<std::int64_t>>(v, "key").unwrap();
|
||||
|
||||
CHECK_EQ(42, vec.at(0));
|
||||
CHECK_EQ(54, vec.at(1));
|
||||
CHECK_EQ(69, vec.at(2));
|
||||
CHECK_EQ(72, vec.at(3));
|
||||
|
||||
std::list<short>::const_iterator iter = lst.begin();
|
||||
CHECK_EQ(static_cast<short>(42), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(54), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(69), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(72), *(iter++));
|
||||
|
||||
CHECK_EQ(static_cast<std::int64_t>(42), deq.at(0));
|
||||
CHECK_EQ(static_cast<std::int64_t>(54), deq.at(1));
|
||||
CHECK_EQ(static_cast<std::int64_t>(69), deq.at(2));
|
||||
CHECK_EQ(static_cast<std::int64_t>(72), deq.at(3));
|
||||
|
||||
std::array<int, 4> ary = toml::try_find<std::array<int, 4>>(v, "key").unwrap();
|
||||
CHECK_EQ(42, ary.at(0));
|
||||
CHECK_EQ(54, ary.at(1));
|
||||
CHECK_EQ(69, ary.at(2));
|
||||
CHECK_EQ(72, ary.at(3));
|
||||
|
||||
std::tuple<int, short, unsigned, long> tpl =
|
||||
toml::try_find<std::tuple<int, short, unsigned, long>>(v, "key").unwrap();
|
||||
CHECK_EQ( 42 , std::get<0>(tpl));
|
||||
CHECK_EQ(static_cast<short >(54), std::get<1>(tpl));
|
||||
CHECK_EQ(static_cast<unsigned>(69), std::get<2>(tpl));
|
||||
CHECK_EQ(static_cast<long >(72), std::get<3>(tpl));
|
||||
|
||||
value_type p = toml::table{{"key", toml::array{3.14, 2.71}}};
|
||||
std::pair<double, double> pr = toml::try_find<std::pair<double, double> >(p, "key").unwrap();
|
||||
CHECK_EQ(3.14, pr.first);
|
||||
CHECK_EQ(2.71, pr.second);
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find array move conversion")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
value_type v1 = toml::table{{"key", toml::array{42, 54, 69, 72}}};
|
||||
value_type v2 = toml::table{{"key", toml::array{42, 54, 69, 72}}};
|
||||
value_type v3 = toml::table{{"key", toml::array{42, 54, 69, 72}}};
|
||||
value_type v4 = toml::table{{"key", toml::array{42, 54, 69, 72}}};
|
||||
value_type v5 = toml::table{{"key", toml::array{42, 54, 69, 72}}};
|
||||
|
||||
const std::vector<int> vec = toml::try_find<std::vector<int>>(std::move(v1), "key").unwrap();
|
||||
const std::list<short> lst = toml::try_find<std::list<short>>(std::move(v2), "key").unwrap();
|
||||
const std::deque<std::int64_t> deq = toml::try_find<std::deque<std::int64_t>>(std::move(v3), "key").unwrap();
|
||||
|
||||
CHECK_EQ(42, vec.at(0));
|
||||
CHECK_EQ(54, vec.at(1));
|
||||
CHECK_EQ(69, vec.at(2));
|
||||
CHECK_EQ(72, vec.at(3));
|
||||
|
||||
std::list<short>::const_iterator iter = lst.begin();
|
||||
CHECK_EQ(static_cast<short>(42), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(54), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(69), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(72), *(iter++));
|
||||
|
||||
CHECK_EQ(static_cast<std::int64_t>(42), deq.at(0));
|
||||
CHECK_EQ(static_cast<std::int64_t>(54), deq.at(1));
|
||||
CHECK_EQ(static_cast<std::int64_t>(69), deq.at(2));
|
||||
CHECK_EQ(static_cast<std::int64_t>(72), deq.at(3));
|
||||
|
||||
std::array<int, 4> ary = toml::try_find<std::array<int, 4>>(std::move(v4), "key").unwrap();
|
||||
CHECK_EQ(42, ary.at(0));
|
||||
CHECK_EQ(54, ary.at(1));
|
||||
CHECK_EQ(69, ary.at(2));
|
||||
CHECK_EQ(72, ary.at(3));
|
||||
|
||||
std::tuple<int, short, unsigned, long> tpl =
|
||||
toml::try_find<std::tuple<int, short, unsigned, long>>(std::move(v5), "key").unwrap();
|
||||
CHECK_EQ( 42 , std::get<0>(tpl));
|
||||
CHECK_EQ(static_cast<short >(54), std::get<1>(tpl));
|
||||
CHECK_EQ(static_cast<unsigned>(69), std::get<2>(tpl));
|
||||
CHECK_EQ(static_cast<long >(72), std::get<3>(tpl));
|
||||
|
||||
value_type p = toml::table{{"key", toml::array{3.14, 2.71}}};
|
||||
std::pair<double, double> pr = toml::try_find<std::pair<double, double> >(std::move(p), "key").unwrap();
|
||||
CHECK_EQ(3.14, pr.first);
|
||||
CHECK_EQ(2.71, pr.second);
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find array of array conversion")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
value_type v1 = toml::array{42, 54, 69, 72};
|
||||
value_type v2 = toml::array{"foo", "bar", "baz"};
|
||||
value_type v = toml::table{{"key", toml::array{v1, v2}}};
|
||||
|
||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||
toml::try_find<std::pair<std::vector<int>, std::vector<std::string>>>(v, "key").unwrap();
|
||||
|
||||
CHECK_EQ(p.first.at(0), 42);
|
||||
CHECK_EQ(p.first.at(1), 54);
|
||||
CHECK_EQ(p.first.at(2), 69);
|
||||
CHECK_EQ(p.first.at(3), 72);
|
||||
|
||||
CHECK_EQ(p.second.at(0), "foo");
|
||||
CHECK_EQ(p.second.at(1), "bar");
|
||||
CHECK_EQ(p.second.at(2), "baz");
|
||||
|
||||
std::tuple<std::vector<int>, std::vector<std::string>> t =
|
||||
toml::try_find<std::tuple<std::vector<int>, std::vector<std::string>>>(v, "key").unwrap();
|
||||
|
||||
CHECK_EQ(std::get<0>(t).at(0), 42);
|
||||
CHECK_EQ(std::get<0>(t).at(1), 54);
|
||||
CHECK_EQ(std::get<0>(t).at(2), 69);
|
||||
CHECK_EQ(std::get<0>(t).at(3), 72);
|
||||
|
||||
CHECK_EQ(std::get<1>(t).at(0), "foo");
|
||||
CHECK_EQ(std::get<1>(t).at(1), "bar");
|
||||
CHECK_EQ(std::get<1>(t).at(2), "baz");
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find array of array move conversion")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
value_type a1 = toml::array{42, 54, 69, 72};
|
||||
value_type a2 = toml::array{"foo", "bar", "baz"};
|
||||
value_type v1 = toml::table{{"key", toml::array{a1, a2}}};
|
||||
value_type v2 = toml::table{{"key", toml::array{a1, a2}}};
|
||||
|
||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||
toml::try_find<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v1), "key").unwrap();
|
||||
|
||||
CHECK_EQ(p.first.at(0), 42);
|
||||
CHECK_EQ(p.first.at(1), 54);
|
||||
CHECK_EQ(p.first.at(2), 69);
|
||||
CHECK_EQ(p.first.at(3), 72);
|
||||
|
||||
CHECK_EQ(p.second.at(0), "foo");
|
||||
CHECK_EQ(p.second.at(1), "bar");
|
||||
CHECK_EQ(p.second.at(2), "baz");
|
||||
|
||||
std::tuple<std::vector<int>, std::vector<std::string>> t =
|
||||
toml::try_find<std::tuple<std::vector<int>, std::vector<std::string>>>(std::move(v2), "key").unwrap();
|
||||
|
||||
CHECK_EQ(std::get<0>(t).at(0), 42);
|
||||
CHECK_EQ(std::get<0>(t).at(1), 54);
|
||||
CHECK_EQ(std::get<0>(t).at(2), 69);
|
||||
CHECK_EQ(std::get<0>(t).at(3), 72);
|
||||
|
||||
CHECK_EQ(std::get<1>(t).at(0), "foo");
|
||||
CHECK_EQ(std::get<1>(t).at(1), "bar");
|
||||
CHECK_EQ(std::get<1>(t).at(2), "baz");
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find table conversion")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::table{
|
||||
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
|
||||
}}};
|
||||
const auto v = toml::try_find<std::map<std::string, int>>(v1, "key").unwrap();
|
||||
CHECK_EQ(v.at("key1"), 1);
|
||||
CHECK_EQ(v.at("key2"), 2);
|
||||
CHECK_EQ(v.at("key3"), 3);
|
||||
CHECK_EQ(v.at("key4"), 4);
|
||||
}
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::table{
|
||||
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
|
||||
}}};
|
||||
const auto v = toml::try_find<std::map<std::string, int>>(std::move(v1), "key").unwrap();
|
||||
CHECK_EQ(v.at("key1"), 1);
|
||||
CHECK_EQ(v.at("key2"), 2);
|
||||
CHECK_EQ(v.at("key3"), 3);
|
||||
CHECK_EQ(v.at("key4"), 4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find local_date")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::try_find<std::chrono::system_clock::time_point>(v1, "key").unwrap());
|
||||
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 0;
|
||||
t.tm_min = 0;
|
||||
t.tm_sec = 0;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
CHECK_EQ(c, date);
|
||||
}
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::try_find<std::chrono::system_clock::time_point>(std::move(v1), "key").unwrap());
|
||||
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 0;
|
||||
t.tm_min = 0;
|
||||
t.tm_sec = 0;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
CHECK_EQ(c, date);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find local_time")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::local_time{12, 30, 45}}};
|
||||
const auto time = toml::try_find<std::chrono::seconds>(v1, "key").unwrap();
|
||||
CHECK_EQ(time, std::chrono::hours(12) +
|
||||
std::chrono::minutes(30) + std::chrono::seconds(45));
|
||||
}
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::local_time{12, 30, 45}}};
|
||||
const auto time = toml::try_find<std::chrono::seconds>(std::move(v1), "key").unwrap();
|
||||
CHECK_EQ(time, std::chrono::hours(12) +
|
||||
std::chrono::minutes(30) + std::chrono::seconds(45));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find local_datetime")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::local_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 45})}};
|
||||
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::try_find<std::chrono::system_clock::time_point>(v1, "key").unwrap());
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 12;
|
||||
t.tm_min = 30;
|
||||
t.tm_sec = 45;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
CHECK_EQ(c, date);
|
||||
}
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::local_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 45})}};
|
||||
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::try_find<std::chrono::system_clock::time_point>(std::move(v1), "key").unwrap());
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 12;
|
||||
t.tm_min = 30;
|
||||
t.tm_sec = 45;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
CHECK_EQ(c, date);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_find offset_datetime")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::offset_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 0},
|
||||
toml::time_offset{9, 0})}};
|
||||
// 2018-04-01T12:30:00+09:00
|
||||
//, 2018-04-01T03:30:00Z
|
||||
|
||||
const auto date = toml::try_find<std::chrono::system_clock::time_point>(v1, "key").unwrap();
|
||||
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||
|
||||
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||
const auto tm = toml::detail::gmtime_s(std::addressof(timet));
|
||||
CHECK_EQ(tm.tm_year + 1900, 2018);
|
||||
CHECK_EQ(tm.tm_mon + 1, 4);
|
||||
CHECK_EQ(tm.tm_mday, 1);
|
||||
CHECK_EQ(tm.tm_hour, 3);
|
||||
CHECK_EQ(tm.tm_min, 30);
|
||||
CHECK_EQ(tm.tm_sec, 0);
|
||||
}
|
||||
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::offset_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 0},
|
||||
toml::time_offset{-8, 0})}};
|
||||
// 2018-04-01T12:30:00-08:00
|
||||
//, 2018-04-01T20:30:00Z
|
||||
|
||||
const auto date = toml::try_find<std::chrono::system_clock::time_point>(v1, "key").unwrap();
|
||||
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||
|
||||
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||
const auto tm = toml::detail::gmtime_s(std::addressof(timet));
|
||||
CHECK_EQ(tm.tm_year + 1900, 2018);
|
||||
CHECK_EQ(tm.tm_mon + 1, 4);
|
||||
CHECK_EQ(tm.tm_mday, 1);
|
||||
CHECK_EQ(tm.tm_hour, 20);
|
||||
CHECK_EQ(tm.tm_min, 30);
|
||||
CHECK_EQ(tm.tm_sec, 0);
|
||||
}
|
||||
|
||||
{
|
||||
value_type v1 = toml::table{{"key", toml::offset_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 0},
|
||||
toml::time_offset{-8, 0})}};
|
||||
// 2018-04-01T12:30:00-08:00
|
||||
//, 2018-04-01T20:30:00Z
|
||||
|
||||
const auto date = toml::try_find<std::chrono::system_clock::time_point>(std::move(v1), "key").unwrap();
|
||||
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||
|
||||
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||
const auto tm = toml::detail::gmtime_s(std::addressof(timet));
|
||||
CHECK_EQ(tm.tm_year + 1900, 2018);
|
||||
CHECK_EQ(tm.tm_mon + 1, 4);
|
||||
CHECK_EQ(tm.tm_mday, 1);
|
||||
CHECK_EQ(tm.tm_hour, 20);
|
||||
CHECK_EQ(tm.tm_min, 30);
|
||||
CHECK_EQ(tm.tm_sec, 0);
|
||||
}
|
||||
}
|
||||
529
tests/test_try_get.cpp
Normal file
529
tests/test_try_get.cpp
Normal file
@@ -0,0 +1,529 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include "doctest.h"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <toml11/value.hpp>
|
||||
#include <toml11/try_get.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
namespace toml
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
std::tm localtime_s(const std::time_t* src);
|
||||
std::tm gmtime_s(const std::time_t* src);
|
||||
} // detail
|
||||
} // toml
|
||||
|
||||
TEST_CASE("testing toml::try_get with toml types")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
using boolean_type = typename value_type::boolean_type ;
|
||||
using integer_type = typename value_type::integer_type ;
|
||||
using floating_type = typename value_type::floating_type ;
|
||||
using string_type = typename value_type::string_type ;
|
||||
using local_time_type = typename value_type::local_time_type ;
|
||||
using local_date_type = typename value_type::local_date_type ;
|
||||
using local_datetime_type = typename value_type::local_datetime_type ;
|
||||
using offset_datetime_type = typename value_type::offset_datetime_type;
|
||||
using array_type = typename value_type::array_type ;
|
||||
using table_type = typename value_type::table_type ;
|
||||
|
||||
{
|
||||
value_type v(true);
|
||||
CHECK_EQ(true, toml::try_get<boolean_type>(v).unwrap());
|
||||
|
||||
toml::try_get<boolean_type>(v).unwrap() = false;
|
||||
CHECK_EQ(false, toml::try_get<boolean_type>(v).unwrap());
|
||||
|
||||
boolean_type x = toml::try_get<boolean_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(false, x);
|
||||
}
|
||||
{
|
||||
value_type v(42);
|
||||
CHECK_EQ(integer_type(42), toml::try_get<integer_type>(v).unwrap());
|
||||
|
||||
toml::try_get<integer_type>(v).unwrap() = 54;
|
||||
CHECK_EQ(integer_type(54), toml::try_get<integer_type>(v).unwrap());
|
||||
|
||||
integer_type x = toml::try_get<integer_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(integer_type(54), x);
|
||||
}
|
||||
{
|
||||
value_type v(3.14);
|
||||
CHECK_EQ(floating_type(3.14), toml::try_get<floating_type>(v).unwrap());
|
||||
|
||||
toml::try_get<floating_type>(v).unwrap() = 2.71;
|
||||
CHECK_EQ(floating_type(2.71), toml::try_get<floating_type>(v).unwrap());
|
||||
|
||||
floating_type x = toml::try_get<floating_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(floating_type(2.71), x);
|
||||
}
|
||||
{
|
||||
value_type v("foo");
|
||||
CHECK_EQ("foo", toml::try_get<string_type>(v).unwrap());
|
||||
|
||||
toml::try_get<string_type>(v).unwrap() += "bar";
|
||||
CHECK_EQ("foobar", toml::try_get<string_type>(v).unwrap());
|
||||
|
||||
string_type x = toml::try_get<string_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ("foobar", x);
|
||||
}
|
||||
{
|
||||
local_date_type d(2018, toml::month_t::Apr, 22);
|
||||
value_type v(d);
|
||||
CHECK_EQ(d, toml::try_get<local_date_type>(v).unwrap());
|
||||
|
||||
toml::try_get<local_date_type>(v).unwrap().year = 2017;
|
||||
d.year = 2017;
|
||||
CHECK_EQ(d, toml::try_get<local_date_type>(v).unwrap());
|
||||
|
||||
local_date_type x = toml::try_get<local_date_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(d, x);
|
||||
}
|
||||
{
|
||||
local_time_type t(12, 30, 45);
|
||||
value_type v(t);
|
||||
CHECK_EQ(t, toml::try_get<local_time_type>(v).unwrap());
|
||||
|
||||
toml::try_get<local_time_type>(v).unwrap().hour = 9;
|
||||
t.hour = 9;
|
||||
CHECK_EQ(t, toml::try_get<local_time_type>(v).unwrap());
|
||||
|
||||
local_time_type x = toml::try_get<local_time_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(t, x);
|
||||
}
|
||||
{
|
||||
local_datetime_type dt(toml::local_date(2018, toml::month_t::Apr, 22),
|
||||
toml::local_time(12, 30, 45));
|
||||
value_type v(dt);
|
||||
CHECK_EQ(dt, toml::try_get<local_datetime_type>(v).unwrap());
|
||||
|
||||
toml::try_get<local_datetime_type>(v).unwrap().date.year = 2017;
|
||||
dt.date.year = 2017;
|
||||
CHECK_EQ(dt, toml::try_get<local_datetime_type>(v).unwrap());
|
||||
|
||||
toml::local_datetime x = toml::try_get<local_datetime_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(dt, x);
|
||||
}
|
||||
{
|
||||
offset_datetime_type dt(toml::local_datetime(
|
||||
toml::local_date(2018, toml::month_t::Apr, 22),
|
||||
toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
|
||||
value_type v(dt);
|
||||
CHECK_EQ(dt, toml::try_get<offset_datetime_type>(v).unwrap());
|
||||
|
||||
toml::try_get<toml::offset_datetime>(v).unwrap().date.year = 2017;
|
||||
dt.date.year = 2017;
|
||||
CHECK_EQ(dt, toml::try_get<offset_datetime_type>(v).unwrap());
|
||||
|
||||
offset_datetime_type x = toml::try_get<offset_datetime_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(dt, x);
|
||||
}
|
||||
{
|
||||
array_type vec;
|
||||
vec.push_back(value_type(42));
|
||||
vec.push_back(value_type(54));
|
||||
value_type v(vec);
|
||||
CHECK_EQ(vec, toml::try_get<array_type>(v).unwrap());
|
||||
|
||||
toml::try_get<array_type>(v).unwrap().push_back(value_type(123));
|
||||
vec.push_back(value_type(123));
|
||||
CHECK_EQ(vec, toml::try_get<array_type>(v).unwrap());
|
||||
|
||||
array_type x = toml::try_get<array_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(vec, x);
|
||||
}
|
||||
{
|
||||
table_type tab;
|
||||
tab["key1"] = value_type(42);
|
||||
tab["key2"] = value_type(3.14);
|
||||
value_type v(tab);
|
||||
CHECK_EQ(tab, toml::try_get<table_type>(v).unwrap());
|
||||
|
||||
toml::try_get<table_type>(v).unwrap()["key3"] = value_type(123);
|
||||
tab["key3"] = value_type(123);
|
||||
CHECK_EQ(tab, toml::try_get<table_type>(v).unwrap());
|
||||
|
||||
table_type x = toml::try_get<table_type>(std::move(v)).unwrap();
|
||||
CHECK_EQ(tab, x);
|
||||
}
|
||||
{
|
||||
value_type v1(42);
|
||||
CHECK_EQ(v1, toml::try_get<value_type>(v1).unwrap());
|
||||
|
||||
value_type v2(54);
|
||||
toml::try_get<value_type>(v1).unwrap() = v2;
|
||||
CHECK_EQ(v2, toml::try_get<value_type>(v1).unwrap());
|
||||
|
||||
value_type x = toml::try_get<value_type>(std::move(v1)).unwrap();
|
||||
CHECK_EQ(v2, x);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_get<integer-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v(42);
|
||||
|
||||
CHECK_EQ(int(42), toml::try_get<int >(v).unwrap());
|
||||
CHECK_EQ(short(42), toml::try_get<short >(v).unwrap());
|
||||
CHECK_EQ(char(42), toml::try_get<char >(v).unwrap());
|
||||
CHECK_EQ(unsigned(42), toml::try_get<unsigned >(v).unwrap());
|
||||
CHECK_EQ(long(42), toml::try_get<long >(v).unwrap());
|
||||
CHECK_EQ(std::int64_t(42), toml::try_get<std::int64_t >(v).unwrap());
|
||||
CHECK_EQ(std::uint64_t(42), toml::try_get<std::uint64_t>(v).unwrap());
|
||||
CHECK_EQ(std::int16_t(42), toml::try_get<std::int16_t >(v).unwrap());
|
||||
CHECK_EQ(std::uint16_t(42), toml::try_get<std::uint16_t>(v).unwrap());
|
||||
|
||||
CHECK_EQ(int(42), toml::try_get<int >(as_const(v)).unwrap());
|
||||
CHECK_EQ(short(42), toml::try_get<short >(as_const(v)).unwrap());
|
||||
CHECK_EQ(char(42), toml::try_get<char >(as_const(v)).unwrap());
|
||||
CHECK_EQ(unsigned(42), toml::try_get<unsigned >(as_const(v)).unwrap());
|
||||
CHECK_EQ(long(42), toml::try_get<long >(as_const(v)).unwrap());
|
||||
CHECK_EQ(std::int64_t(42), toml::try_get<std::int64_t >(as_const(v)).unwrap());
|
||||
CHECK_EQ(std::uint64_t(42), toml::try_get<std::uint64_t>(as_const(v)).unwrap());
|
||||
CHECK_EQ(std::int16_t(42), toml::try_get<std::int16_t >(as_const(v)).unwrap());
|
||||
CHECK_EQ(std::uint16_t(42), toml::try_get<std::uint16_t>(as_const(v)).unwrap());
|
||||
|
||||
value_type v1(v);
|
||||
value_type v2(v);
|
||||
value_type v3(v);
|
||||
value_type v4(v);
|
||||
value_type v5(v);
|
||||
value_type v6(v);
|
||||
value_type v7(v);
|
||||
value_type v8(v);
|
||||
value_type v9(v);
|
||||
|
||||
CHECK_EQ(int(42), toml::try_get<int >(v1).unwrap());
|
||||
CHECK_EQ(short(42), toml::try_get<short >(v2).unwrap());
|
||||
CHECK_EQ(char(42), toml::try_get<char >(v3).unwrap());
|
||||
CHECK_EQ(unsigned(42), toml::try_get<unsigned >(v4).unwrap());
|
||||
CHECK_EQ(long(42), toml::try_get<long >(v5).unwrap());
|
||||
CHECK_EQ(std::int64_t(42), toml::try_get<std::int64_t >(v6).unwrap());
|
||||
CHECK_EQ(std::uint64_t(42), toml::try_get<std::uint64_t>(v7).unwrap());
|
||||
CHECK_EQ(std::int16_t(42), toml::try_get<std::int16_t >(v8).unwrap());
|
||||
CHECK_EQ(std::uint16_t(42), toml::try_get<std::uint16_t>(v9).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_get<floating-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
const double ref(3.14);
|
||||
|
||||
value_type v(ref);
|
||||
CHECK_EQ(static_cast<float >(ref), toml::try_get<float >(v).unwrap());
|
||||
CHECK_EQ( ref , toml::try_get<double >(v).unwrap());
|
||||
CHECK_EQ(static_cast<long double>(ref), toml::try_get<long double>(v).unwrap());
|
||||
|
||||
value_type v1(ref);
|
||||
value_type v2(ref);
|
||||
value_type v3(ref);
|
||||
CHECK_EQ(static_cast<float >(ref), toml::try_get<float >(std::move(v1)).unwrap());
|
||||
CHECK_EQ( ref , toml::try_get<double >(std::move(v2)).unwrap());
|
||||
CHECK_EQ(static_cast<long double>(ref), toml::try_get<long double>(std::move(v3)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
TEST_CASE("testing toml::try_get<string-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v("foo");
|
||||
CHECK_EQ("foo", toml::try_get<std::string_view>(v).unwrap());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("testing toml::try_get<array-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
const value_type v(toml::array{42, 54, 69, 72});
|
||||
|
||||
const std::vector<int> vec = toml::try_get<std::vector<int>>(v).unwrap();
|
||||
const std::list<short> lst = toml::try_get<std::list<short>>(v).unwrap();
|
||||
const std::deque<std::int64_t> deq = toml::try_get<std::deque<std::int64_t>>(v).unwrap();
|
||||
|
||||
CHECK_EQ(42, vec.at(0));
|
||||
CHECK_EQ(54, vec.at(1));
|
||||
CHECK_EQ(69, vec.at(2));
|
||||
CHECK_EQ(72, vec.at(3));
|
||||
|
||||
std::list<short>::const_iterator iter = lst.begin();
|
||||
CHECK_EQ(static_cast<short>(42), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(54), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(69), *(iter++));
|
||||
CHECK_EQ(static_cast<short>(72), *(iter++));
|
||||
|
||||
CHECK_EQ(static_cast<std::int64_t>(42), deq.at(0));
|
||||
CHECK_EQ(static_cast<std::int64_t>(54), deq.at(1));
|
||||
CHECK_EQ(static_cast<std::int64_t>(69), deq.at(2));
|
||||
CHECK_EQ(static_cast<std::int64_t>(72), deq.at(3));
|
||||
|
||||
std::array<int, 4> ary = toml::try_get<std::array<int, 4>>(v).unwrap();
|
||||
CHECK_EQ(42, ary.at(0));
|
||||
CHECK_EQ(54, ary.at(1));
|
||||
CHECK_EQ(69, ary.at(2));
|
||||
CHECK_EQ(72, ary.at(3));
|
||||
|
||||
std::tuple<int, short, unsigned, long> tpl =
|
||||
toml::try_get<std::tuple<int, short, unsigned, long>>(v).unwrap();
|
||||
CHECK_EQ( 42 , std::get<0>(tpl));
|
||||
CHECK_EQ(static_cast<short >(54), std::get<1>(tpl));
|
||||
CHECK_EQ(static_cast<unsigned>(69), std::get<2>(tpl));
|
||||
CHECK_EQ(static_cast<long >(72), std::get<3>(tpl));
|
||||
|
||||
const value_type p(toml::array{3.14, 2.71});
|
||||
std::pair<double, double> pr = toml::try_get<std::pair<double, double> >(p).unwrap();
|
||||
CHECK_EQ(3.14, pr.first);
|
||||
CHECK_EQ(2.71, pr.second);
|
||||
}
|
||||
|
||||
{
|
||||
value_type v(toml::array{42, 54, 69, 72});
|
||||
const std::vector<int> vec = toml::try_get<std::vector<int>>(std::move(v)).unwrap();
|
||||
CHECK_EQ(42, vec.at(0));
|
||||
CHECK_EQ(54, vec.at(1));
|
||||
CHECK_EQ(69, vec.at(2));
|
||||
CHECK_EQ(72, vec.at(3));
|
||||
}
|
||||
{
|
||||
value_type v(toml::array{42, 54, 69, 72});
|
||||
const std::deque<int> deq = toml::try_get<std::deque<int>>(std::move(v)).unwrap();
|
||||
CHECK_EQ(42, deq.at(0));
|
||||
CHECK_EQ(54, deq.at(1));
|
||||
CHECK_EQ(69, deq.at(2));
|
||||
CHECK_EQ(72, deq.at(3));
|
||||
}
|
||||
{
|
||||
value_type v(toml::array{42, 54, 69, 72});
|
||||
const std::list<int> lst = toml::try_get<std::list<int>>(std::move(v)).unwrap();
|
||||
std::list<int>::const_iterator iter = lst.begin();
|
||||
CHECK_EQ(42, *(iter++));
|
||||
CHECK_EQ(54, *(iter++));
|
||||
CHECK_EQ(69, *(iter++));
|
||||
CHECK_EQ(72, *(iter++));
|
||||
}
|
||||
{
|
||||
value_type v(toml::array{42, 54, 69, 72});
|
||||
std::array<int, 4> ary = toml::try_get<std::array<int, 4>>(std::move(v)).unwrap();
|
||||
CHECK_EQ(42, ary.at(0));
|
||||
CHECK_EQ(54, ary.at(1));
|
||||
CHECK_EQ(69, ary.at(2));
|
||||
CHECK_EQ(72, ary.at(3));
|
||||
}
|
||||
{
|
||||
value_type v(toml::array{42, 54, 69, 72});
|
||||
std::tuple<int, short, unsigned, long> tpl =
|
||||
toml::try_get<std::tuple<int, short, unsigned, long>>(std::move(v)).unwrap();
|
||||
CHECK_EQ( 42 , std::get<0>(tpl));
|
||||
CHECK_EQ(static_cast<short >(54), std::get<1>(tpl));
|
||||
CHECK_EQ(static_cast<unsigned>(69), std::get<2>(tpl));
|
||||
CHECK_EQ(static_cast<long >(72), std::get<3>(tpl));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_get<array-of-arrays>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
const value_type v1(toml::array{42, 54, 69, 72});
|
||||
const value_type v2(toml::array{"foo", "bar", "baz"});
|
||||
const value_type v (toml::array{v1, v2});
|
||||
|
||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||
toml::try_get<std::pair<std::vector<int>, std::vector<std::string>>>(v).unwrap();
|
||||
|
||||
CHECK_EQ(p.first.size(), 4u);
|
||||
CHECK_EQ(p.first.at(0), 42);
|
||||
CHECK_EQ(p.first.at(1), 54);
|
||||
CHECK_EQ(p.first.at(2), 69);
|
||||
CHECK_EQ(p.first.at(3), 72);
|
||||
|
||||
CHECK_EQ(p.second.size(), 3u);
|
||||
CHECK_EQ(p.second.at(0), "foo");
|
||||
CHECK_EQ(p.second.at(1), "bar");
|
||||
CHECK_EQ(p.second.at(2), "baz");
|
||||
|
||||
std::tuple<std::vector<int>, std::vector<std::string>> t =
|
||||
toml::try_get<std::tuple<std::vector<int>, std::vector<std::string>>>(v).unwrap();
|
||||
|
||||
CHECK_EQ(std::get<0>(t).at(0), 42);
|
||||
CHECK_EQ(std::get<0>(t).at(1), 54);
|
||||
CHECK_EQ(std::get<0>(t).at(2), 69);
|
||||
CHECK_EQ(std::get<0>(t).at(3), 72);
|
||||
|
||||
CHECK_EQ(std::get<1>(t).at(0), "foo");
|
||||
CHECK_EQ(std::get<1>(t).at(1), "bar");
|
||||
CHECK_EQ(std::get<1>(t).at(2), "baz");
|
||||
}
|
||||
{
|
||||
const value_type v1(toml::array{42, 54, 69, 72});
|
||||
const value_type v2(toml::array{"foo", "bar", "baz"});
|
||||
value_type v (toml::array{v1, v2});
|
||||
|
||||
std::pair<std::vector<int>, std::vector<std::string>> p =
|
||||
toml::try_get<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v)).unwrap();
|
||||
|
||||
CHECK_EQ(p.first.size(), 4u);
|
||||
CHECK_EQ(p.first.at(0), 42);
|
||||
CHECK_EQ(p.first.at(1), 54);
|
||||
CHECK_EQ(p.first.at(2), 69);
|
||||
CHECK_EQ(p.first.at(3), 72);
|
||||
|
||||
CHECK_EQ(p.second.size(), 3u);
|
||||
CHECK_EQ(p.second.at(0), "foo");
|
||||
CHECK_EQ(p.second.at(1), "bar");
|
||||
CHECK_EQ(p.second.at(2), "baz");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_get<table-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
const value_type v1(toml::table{
|
||||
{"key1", 1},
|
||||
{"key2", 2},
|
||||
{"key3", 3},
|
||||
{"key4", 4}
|
||||
});
|
||||
|
||||
const auto v = toml::try_get<std::map<std::string, int>>(v1).unwrap();
|
||||
CHECK_EQ(v.at("key1"), 1);
|
||||
CHECK_EQ(v.at("key2"), 2);
|
||||
CHECK_EQ(v.at("key3"), 3);
|
||||
CHECK_EQ(v.at("key4"), 4);
|
||||
}
|
||||
{
|
||||
value_type v1(toml::table{
|
||||
{"key1", 1},
|
||||
{"key2", 2},
|
||||
{"key3", 3},
|
||||
{"key4", 4}
|
||||
});
|
||||
const auto v = toml::try_get<std::map<std::string, int>>(std::move(v1)).unwrap();
|
||||
CHECK_EQ(v.at("key1"), 1);
|
||||
CHECK_EQ(v.at("key2"), 2);
|
||||
CHECK_EQ(v.at("key3"), 3);
|
||||
CHECK_EQ(v.at("key4"), 4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_get<time_point>(local_date)")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
value_type v1(toml::local_date{2018, toml::month_t::Apr, 1});
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::try_get<std::chrono::system_clock::time_point>(v1).unwrap());
|
||||
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 0;
|
||||
t.tm_min = 0;
|
||||
t.tm_sec = 0;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
CHECK_EQ(c, date);
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_get<duration>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
value_type v1(toml::local_time{12, 30, 45});
|
||||
const auto time = toml::try_get<std::chrono::seconds>(v1).unwrap();
|
||||
const bool result = time == std::chrono::hours(12) +
|
||||
std::chrono::minutes(30) +
|
||||
std::chrono::seconds(45);
|
||||
CHECK_UNARY(result);
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_get<time_point>(local_datetime)")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
value_type v1(toml::local_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 45}));
|
||||
|
||||
const auto date = std::chrono::system_clock::to_time_t(
|
||||
toml::try_get<std::chrono::system_clock::time_point>(v1).unwrap());
|
||||
|
||||
std::tm t;
|
||||
t.tm_year = 2018 - 1900;
|
||||
t.tm_mon = 4 - 1;
|
||||
t.tm_mday = 1;
|
||||
t.tm_hour = 12;
|
||||
t.tm_min = 30;
|
||||
t.tm_sec = 45;
|
||||
t.tm_isdst = -1;
|
||||
const auto c = std::mktime(&t);
|
||||
CHECK_EQ(c, date);
|
||||
}
|
||||
|
||||
TEST_CASE("testing toml::try_get<time_point>(offset_datetime)")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v1(toml::offset_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 0},
|
||||
toml::time_offset{9, 0}));
|
||||
// 2018-04-01T12:30:00+09:00
|
||||
// == 2018-04-01T03:30:00Z
|
||||
|
||||
const auto date = toml::try_get<std::chrono::system_clock::time_point>(v1).unwrap();
|
||||
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||
|
||||
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||
const auto tm = toml::detail::gmtime_s(std::addressof(timet));
|
||||
CHECK_EQ(tm.tm_year + 1900, 2018);
|
||||
CHECK_EQ(tm.tm_mon + 1, 4);
|
||||
CHECK_EQ(tm.tm_mday, 1);
|
||||
CHECK_EQ(tm.tm_hour, 3);
|
||||
CHECK_EQ(tm.tm_min, 30);
|
||||
CHECK_EQ(tm.tm_sec, 0);
|
||||
}
|
||||
|
||||
{
|
||||
value_type v1(toml::offset_datetime(
|
||||
toml::local_date{2018, toml::month_t::Apr, 1},
|
||||
toml::local_time{12, 30, 0},
|
||||
toml::time_offset{-8, 0}));
|
||||
// 2018-04-01T12:30:00-08:00
|
||||
//, 2018-04-01T20:30:00Z
|
||||
|
||||
const auto date = toml::try_get<std::chrono::system_clock::time_point>(v1).unwrap();
|
||||
const auto timet = std::chrono::system_clock::to_time_t(date);
|
||||
|
||||
// get time_t as gmtime (2018-04-01T03:30:00Z)
|
||||
const auto tm = toml::detail::gmtime_s(std::addressof(timet));
|
||||
CHECK_EQ(tm.tm_year + 1900, 2018);
|
||||
CHECK_EQ(tm.tm_mon + 1, 4);
|
||||
CHECK_EQ(tm.tm_mday, 1);
|
||||
CHECK_EQ(tm.tm_hour, 20);
|
||||
CHECK_EQ(tm.tm_min, 30);
|
||||
CHECK_EQ(tm.tm_sec, 0);
|
||||
}
|
||||
}
|
||||
@@ -1062,21 +1062,89 @@ TEST_CASE("testing array-accessors")
|
||||
{
|
||||
toml::value x({true, 42, "hoge"});
|
||||
|
||||
// at
|
||||
|
||||
CHECK_UNARY(x.at(0).is_boolean());
|
||||
CHECK_UNARY(x.at(1).is_integer());
|
||||
CHECK_UNARY(x.at(2).is_string());
|
||||
CHECK_EQ(x.at(0).as_boolean(), true);
|
||||
CHECK_EQ(x.at(1).as_integer(), 42);
|
||||
CHECK_EQ(x.at(2).as_string(), std::string("hoge"));
|
||||
CHECK_THROWS_AS(x.at(3), std::out_of_range);
|
||||
|
||||
CHECK_UNARY(as_const(x).at(0).is_boolean());
|
||||
CHECK_UNARY(as_const(x).at(1).is_integer());
|
||||
CHECK_UNARY(as_const(x).at(2).is_string());
|
||||
|
||||
CHECK_EQ(x.at(0).as_boolean(), true);
|
||||
CHECK_EQ(x.at(1).as_integer(), 42);
|
||||
CHECK_EQ(x.at(2).as_string(), std::string("hoge"));
|
||||
|
||||
CHECK_EQ(as_const(x).at(0).as_boolean(), true);
|
||||
CHECK_EQ(as_const(x).at(1).as_integer(), 42);
|
||||
CHECK_EQ(as_const(x).at(2).as_string(), std::string("hoge"));
|
||||
CHECK_THROWS_AS(as_const(x).at(3), std::out_of_range);
|
||||
|
||||
// update through at
|
||||
|
||||
x.at(0) = false;
|
||||
x.at(1) = 6 * 9;
|
||||
x.at(2) = 3.14;
|
||||
|
||||
CHECK_UNARY(x.at(0).is_boolean());
|
||||
CHECK_UNARY(x.at(1).is_integer());
|
||||
CHECK_UNARY(x.at(2).is_floating());
|
||||
CHECK_EQ(x.at(0).as_boolean(), false);
|
||||
CHECK_EQ(x.at(1).as_integer(), 6*9);
|
||||
CHECK_EQ(x.at(2).as_floating(), 3.14);
|
||||
|
||||
x.at(0) = true;
|
||||
x.at(1) = 42;
|
||||
x.at(2) = "hoge";
|
||||
|
||||
// try_at
|
||||
|
||||
CHECK_UNARY(x.try_at(0).is_ok());
|
||||
CHECK_UNARY(x.try_at(1).is_ok());
|
||||
CHECK_UNARY(x.try_at(2).is_ok());
|
||||
CHECK_UNARY(x.try_at(0).as_ok().is_boolean());
|
||||
CHECK_UNARY(x.try_at(1).as_ok().is_integer());
|
||||
CHECK_UNARY(x.try_at(2).as_ok().is_string());
|
||||
CHECK_UNARY_FALSE(x.try_at(0).is_err());
|
||||
CHECK_UNARY_FALSE(x.try_at(1).is_err());
|
||||
CHECK_UNARY_FALSE(x.try_at(2).is_err());
|
||||
CHECK_EQ(x.try_at(0).as_ok().as_boolean(), true);
|
||||
CHECK_EQ(x.try_at(1).as_ok().as_integer(), 42);
|
||||
CHECK_EQ(x.try_at(2).as_ok().as_string(), std::string("hoge"));
|
||||
CHECK_UNARY(x.try_at(3).is_err());
|
||||
|
||||
CHECK_UNARY(as_const(x).try_at(0).is_ok());
|
||||
CHECK_UNARY(as_const(x).try_at(1).is_ok());
|
||||
CHECK_UNARY(as_const(x).try_at(2).is_ok());
|
||||
CHECK_UNARY(as_const(x).try_at(0).as_ok().is_boolean());
|
||||
CHECK_UNARY(as_const(x).try_at(1).as_ok().is_integer());
|
||||
CHECK_UNARY(as_const(x).try_at(2).as_ok().is_string());
|
||||
CHECK_UNARY_FALSE(as_const(x).try_at(0).is_err());
|
||||
CHECK_UNARY_FALSE(as_const(x).try_at(1).is_err());
|
||||
CHECK_UNARY_FALSE(as_const(x).try_at(2).is_err());
|
||||
CHECK_EQ(as_const(x).try_at(0).as_ok().as_boolean(), true);
|
||||
CHECK_EQ(as_const(x).try_at(1).as_ok().as_integer(), 42);
|
||||
CHECK_EQ(as_const(x).try_at(2).as_ok().as_string(), std::string("hoge"));
|
||||
CHECK_UNARY(as_const(x).try_at(3).is_err());
|
||||
|
||||
// update through try_at
|
||||
|
||||
x.try_at(0).as_ok() = false;
|
||||
x.try_at(1).as_ok() = 6 * 9;
|
||||
x.try_at(2).as_ok() = 3.14;
|
||||
|
||||
CHECK_UNARY(x.at(0).is_boolean());
|
||||
CHECK_UNARY(x.at(1).is_integer());
|
||||
CHECK_UNARY(x.at(2).is_floating());
|
||||
CHECK_EQ(x.at(0).as_boolean(), false);
|
||||
CHECK_EQ(x.at(1).as_integer(), 6*9);
|
||||
CHECK_EQ(x.at(2).as_floating(), 3.14);
|
||||
|
||||
x.try_at(0).as_ok() = true;
|
||||
x.try_at(1).as_ok() = 42;
|
||||
x.try_at(2).as_ok() = "hoge";
|
||||
|
||||
// operator[]
|
||||
|
||||
CHECK_UNARY(x[0].is_boolean());
|
||||
CHECK_UNARY(x[1].is_integer());
|
||||
@@ -1086,6 +1154,8 @@ TEST_CASE("testing array-accessors")
|
||||
CHECK_EQ(x[1].as_integer(), 42);
|
||||
CHECK_EQ(x[2].as_string(), std::string("hoge"));
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
const toml::value v1(3.14);
|
||||
toml::value v2(2.71);
|
||||
|
||||
@@ -1143,13 +1213,83 @@ TEST_CASE("testing table-accessors")
|
||||
CHECK_EQ(x.count("d"), 0);
|
||||
CHECK_EQ(x.count("e"), 0);
|
||||
|
||||
// at
|
||||
|
||||
CHECK_UNARY(x.at("a").is_boolean());
|
||||
CHECK_UNARY(x.at("b").is_integer());
|
||||
CHECK_UNARY(x.at("c").is_string());
|
||||
|
||||
CHECK_EQ(x.at("a").as_boolean(), true);
|
||||
CHECK_EQ(x.at("b").as_integer(), 42);
|
||||
CHECK_EQ(x.at("c").as_string(), std::string("hoge"));
|
||||
CHECK_THROWS_AS(x.at("d"), std::out_of_range);
|
||||
|
||||
CHECK_UNARY(as_const(x).at("a").is_boolean());
|
||||
CHECK_UNARY(as_const(x).at("b").is_integer());
|
||||
CHECK_UNARY(as_const(x).at("c").is_string());
|
||||
CHECK_EQ(as_const(x).at("a").as_boolean(), true);
|
||||
CHECK_EQ(as_const(x).at("b").as_integer(), 42);
|
||||
CHECK_EQ(as_const(x).at("c").as_string(), std::string("hoge"));
|
||||
CHECK_THROWS_AS(as_const(x).at("d"), std::out_of_range);
|
||||
|
||||
// rewrite using at
|
||||
|
||||
x.at("a") = false;
|
||||
x.at("b") = 6*9;
|
||||
x.at("c") = 3.14;
|
||||
|
||||
CHECK_UNARY(x.at("a").is_boolean());
|
||||
CHECK_UNARY(x.at("b").is_integer());
|
||||
CHECK_UNARY(x.at("c").is_floating());
|
||||
CHECK_EQ(x.at("a").as_boolean(), false);
|
||||
CHECK_EQ(x.at("b").as_integer(), 6*9);
|
||||
CHECK_EQ(x.at("c").as_floating(), 3.14);
|
||||
|
||||
x.at("a") = true;
|
||||
x.at("b") = 42;
|
||||
x.at("c") = "hoge";
|
||||
|
||||
// try_at
|
||||
|
||||
CHECK_UNARY(x.try_at("a").is_ok());
|
||||
CHECK_UNARY(x.try_at("b").is_ok());
|
||||
CHECK_UNARY(x.try_at("c").is_ok());
|
||||
CHECK_UNARY(x.try_at("a").as_ok().is_boolean());
|
||||
CHECK_UNARY(x.try_at("b").as_ok().is_integer());
|
||||
CHECK_UNARY(x.try_at("c").as_ok().is_string());
|
||||
CHECK_EQ(x.try_at("a").as_ok().as_boolean(), true);
|
||||
CHECK_EQ(x.try_at("b").as_ok().as_integer(), 42);
|
||||
CHECK_EQ(x.try_at("c").as_ok().as_string(), std::string("hoge"));
|
||||
CHECK_UNARY(x.try_at("d").is_err());
|
||||
|
||||
CHECK_UNARY(as_const(x).try_at("a").is_ok());
|
||||
CHECK_UNARY(as_const(x).try_at("b").is_ok());
|
||||
CHECK_UNARY(as_const(x).try_at("c").is_ok());
|
||||
CHECK_UNARY(as_const(x).try_at("a").as_ok().is_boolean());
|
||||
CHECK_UNARY(as_const(x).try_at("b").as_ok().is_integer());
|
||||
CHECK_UNARY(as_const(x).try_at("c").as_ok().is_string());
|
||||
CHECK_EQ(as_const(x).try_at("a").as_ok().as_boolean(), true);
|
||||
CHECK_EQ(as_const(x).try_at("b").as_ok().as_integer(), 42);
|
||||
CHECK_EQ(as_const(x).try_at("c").as_ok().as_string(), std::string("hoge"));
|
||||
CHECK_UNARY(as_const(x).try_at("d").is_err());
|
||||
|
||||
// rewrite using try_at
|
||||
|
||||
x.try_at("a").as_ok() = false;
|
||||
x.try_at("b").as_ok() = 6*9;
|
||||
x.try_at("c").as_ok() = 3.14;
|
||||
|
||||
CHECK_UNARY(x.at("a").is_boolean());
|
||||
CHECK_UNARY(x.at("b").is_integer());
|
||||
CHECK_UNARY(x.at("c").is_floating());
|
||||
CHECK_EQ(x.at("a").as_boolean(), false);
|
||||
CHECK_EQ(x.at("b").as_integer(), 6*9);
|
||||
CHECK_EQ(x.at("c").as_floating(), 3.14);
|
||||
|
||||
x.try_at("a").as_ok() = true;
|
||||
x.try_at("b").as_ok() = 42;
|
||||
x.try_at("c").as_ok() = "hoge";
|
||||
|
||||
// operator[]
|
||||
|
||||
CHECK_UNARY(x["a"].is_boolean());
|
||||
CHECK_UNARY(x["b"].is_integer());
|
||||
|
||||
Reference in New Issue
Block a user