mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc562ae5cb | ||
|
|
83f37a18b1 | ||
|
|
dc7e443be4 | ||
|
|
59921c1eb7 | ||
|
|
a4d0189df3 | ||
|
|
3320d25abb | ||
|
|
8efb305e8b | ||
|
|
2baa47ef3d | ||
|
|
42734ea642 | ||
|
|
8596419e24 | ||
|
|
932acba7f1 | ||
|
|
b2a93eb267 | ||
|
|
a0ae1a6bfd | ||
|
|
044a66210d | ||
|
|
c4fb41b812 | ||
|
|
a610e75df0 | ||
|
|
0e84d0591b | ||
|
|
e004eaf006 | ||
|
|
7c336a52a0 | ||
|
|
bc7c5cd7a3 | ||
|
|
3c09d3046c | ||
|
|
7af0e66c25 | ||
|
|
8c20067493 | ||
|
|
89921483a8 | ||
|
|
1bc6ef9fce | ||
|
|
312996565d | ||
|
|
db46c1c64b | ||
|
|
34bf32a9e5 | ||
|
|
137f17f2e9 | ||
|
|
5e8d8d0243 | ||
|
|
9e27fd24b7 | ||
|
|
d023a93e3c | ||
|
|
995b25efe0 | ||
|
|
6ba0772053 | ||
|
|
a32289dc70 | ||
|
|
7149b3cb29 | ||
|
|
013d1e396f | ||
|
|
7cab13f6e5 | ||
|
|
74bea5368a |
33
.github/workflows/single-include.yml
vendored
Normal file
33
.github/workflows/single-include.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: gen-singlue-include
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
runs-on: Ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
g++-12 -std=c++20 -O2 tools/expand/main.cpp -o expand
|
||||
./expand include/toml.hpp > single_include.hpp
|
||||
- name: Check diff
|
||||
id: check-diff
|
||||
continue-on-error: true
|
||||
run: |
|
||||
diff single_include.hpp single_include/toml.hpp
|
||||
- name: Commit and Push
|
||||
if: steps.check-diff.outcome == 'failure'
|
||||
run: |
|
||||
mv single_include.hpp single_include/toml.hpp
|
||||
git config --global user.name "ToruNiina"
|
||||
git config --global user.email "ToruNiina@users.noreply.github.com"
|
||||
git add single_include/toml.hpp
|
||||
git commit -m "feat [skip ci]: update single_include"
|
||||
git push origin main
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,5 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(toml11 LANGUAGES CXX VERSION 4.0.0)
|
||||
|
||||
# project_source_dir has not been set yet
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/toml11/version.hpp" TOML11_MAJOR_VERSION_STRING
|
||||
REGEX "#define TOML11_VERSION_MAJOR ([0-9]+)")
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/toml11/version.hpp" TOML11_MINOR_VERSION_STRING
|
||||
REGEX "#define TOML11_VERSION_MINOR ([0-9]+)")
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/toml11/version.hpp" TOML11_PATCH_VERSION_STRING
|
||||
REGEX "#define TOML11_VERSION_PATCH ([0-9]+)")
|
||||
|
||||
string(REGEX REPLACE "#define TOML11_VERSION_MAJOR ([0-9]+)" "\\1" TOML11_VERSION_MAJOR "${TOML11_MAJOR_VERSION_STRING}")
|
||||
string(REGEX REPLACE "#define TOML11_VERSION_MINOR ([0-9]+)" "\\1" TOML11_VERSION_MINOR "${TOML11_MINOR_VERSION_STRING}")
|
||||
string(REGEX REPLACE "#define TOML11_VERSION_PATCH ([0-9]+)" "\\1" TOML11_VERSION_PATCH "${TOML11_PATCH_VERSION_STRING}")
|
||||
|
||||
project(toml11 LANGUAGES CXX VERSION "${TOML11_VERSION_MAJOR}.${TOML11_VERSION_MINOR}.${TOML11_VERSION_PATCH}")
|
||||
|
||||
include(CMakeDependentOption)
|
||||
include(CTest)
|
||||
|
||||
@@ -81,7 +81,7 @@ For more details, please refer to the [documentation](https://toruniina.github.i
|
||||
- [comments](#comments)
|
||||
- [error messages](#error-messages)
|
||||
- [serialization](#serialization)
|
||||
- [Breaking Changes from v3](breaking-changes-from-v3)
|
||||
- [Breaking Changes from v3](#changes-from-v3)
|
||||
- [Contributors](#contributors)
|
||||
- [Licensing Terms](#licensing-terms)
|
||||
|
||||
@@ -332,7 +332,7 @@ For details on possible formatting specifications, please refer to the [document
|
||||
|
||||
### configuring types
|
||||
|
||||
The examples directory provides usage examples, such as using
|
||||
[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.
|
||||
|
||||
Please refer to these examples for implementation guidance in such scenarios.
|
||||
|
||||
@@ -78,7 +78,7 @@ int main()
|
||||
- [comments](#comments)
|
||||
- [error messages](#error-messages)
|
||||
- [serialization](#serialization)
|
||||
- [Breaking Changes from v3](breaking-changes-from-v3)
|
||||
- [Breaking Changes from v3](#changes-from-v3)
|
||||
- [Contributors](#contributors)
|
||||
- [Licensing Terms](#licensing-terms)
|
||||
|
||||
@@ -331,7 +331,7 @@ std::cout << toml::format(input) << std::endl;
|
||||
|
||||
### configuring types
|
||||
|
||||
`examples`ディレクトリには、多倍長整数を使用する場合やユニコードを正規化する場合、
|
||||
[`examples`ディレクトリ](https://github.com/ToruNiina/toml11/tree/main/examples)には、多倍長整数を使用する場合やユニコードを正規化する場合、
|
||||
外部のリフレクションライブラリと連携する場合などの複雑な使用例を用意しています。
|
||||
|
||||
そのような状況での実装例として参照してください。
|
||||
|
||||
@@ -6,7 +6,22 @@ weight = 4
|
||||
|
||||
# Change Log
|
||||
|
||||
# Changes from v3
|
||||
# v4.0.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- Resolved naming conflict of `sematic_version::{major, minor}` with macros defined in `<sys/sysmacro.h>`
|
||||
- Fixed the definition of `operator<<` in `discard_comments`
|
||||
- Fixed the issue where the first blank line was not output in `format_location`
|
||||
- Fixed the issue where error messages pointing to `source_location` referring to lines containing only newline characters were displayed in two lines
|
||||
- Corrected links in the README
|
||||
- Corrected the title of the README in `example/unicode`
|
||||
|
||||
## Added
|
||||
|
||||
- Configured CI to automatically update `single_include/toml.hpp` when changes are made to `main`
|
||||
|
||||
# Changes from v3 to v4
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
-----
|
||||
|
||||
|
||||
@@ -6,7 +6,22 @@ weight = 4
|
||||
|
||||
# Change Log
|
||||
|
||||
# v3からの変化
|
||||
# v4.0.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- `sematic_version::{major, minor}` と `<sys/sysmacro.h>` 内で定義されるマクロの衝突を解消
|
||||
- `discard_comments` の `operator<<` の定義を修正
|
||||
- `format_location`を使用した際に最初の空行が出ない問題を解決
|
||||
- 改行文字のみを含む行を指す`source_location`でエラーメッセージを生成した際に、同じ行が二回表示される問題を解決
|
||||
- `README.md`内のリンクを修正
|
||||
- `example/unicode`のREADMEのタイトルを修正
|
||||
|
||||
## Added
|
||||
|
||||
- `main`に変更があったとき、`single_include/toml.hpp`を自動生成するようCIを設定
|
||||
|
||||
# v3からv4への変化
|
||||
|
||||
## 破壊的変更
|
||||
|
||||
|
||||
@@ -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()`
|
||||
|
||||
長さを返します。
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# reflect
|
||||
# unicode
|
||||
|
||||
Compare TOML key after NFC canonicalization.
|
||||
|
||||
|
||||
@@ -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 ...
|
||||
// }
|
||||
|
||||
@@ -444,7 +444,7 @@ inline bool operator>=(const discard_comments&, const discard_comments&) noexcep
|
||||
|
||||
inline void swap(const discard_comments&, const discard_comments&) noexcept {return;}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream&& os, const discard_comments&) {return os;}
|
||||
inline std::ostream& operator<<(std::ostream& os, const discard_comments&) {return os;}
|
||||
|
||||
} // toml11
|
||||
#endif // TOML11_COMMENTS_FWD_HPP
|
||||
|
||||
@@ -12,17 +12,6 @@
|
||||
namespace toml
|
||||
{
|
||||
|
||||
// To avoid non-threadsafe std::localtime. In C11 (not C++11!), localtime_s is
|
||||
// provided in the absolutely same purpose, but C++11 is actually not compatible
|
||||
// with C11. We need to dispatch the function depending on the OS.
|
||||
namespace detail
|
||||
{
|
||||
std::tm localtime_s(const std::time_t* src);
|
||||
std::tm gmtime_s(const std::time_t* src);
|
||||
} // detail
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
enum class month_t : std::uint8_t
|
||||
{
|
||||
Jan = 0,
|
||||
@@ -48,15 +37,15 @@ struct local_date
|
||||
std::uint8_t day{0}; // [1, 31]
|
||||
|
||||
local_date(int y, month_t m, int d)
|
||||
: year (static_cast<std::int16_t>(y)),
|
||||
month(static_cast<std::uint8_t>(m)),
|
||||
day (static_cast<std::uint8_t>(d))
|
||||
: year {static_cast<std::int16_t>(y)},
|
||||
month{static_cast<std::uint8_t>(m)},
|
||||
day {static_cast<std::uint8_t>(d)}
|
||||
{}
|
||||
|
||||
explicit local_date(const std::tm& t)
|
||||
: year (static_cast<std::int16_t>(t.tm_year + 1900)),
|
||||
month(static_cast<std::uint8_t>(t.tm_mon)),
|
||||
day (static_cast<std::uint8_t>(t.tm_mday))
|
||||
: year {static_cast<std::int16_t>(t.tm_year + 1900)},
|
||||
month{static_cast<std::uint8_t>(t.tm_mon)},
|
||||
day {static_cast<std::uint8_t>(t.tm_mday)}
|
||||
{}
|
||||
|
||||
explicit local_date(const std::chrono::system_clock::time_point& tp);
|
||||
@@ -95,19 +84,19 @@ struct local_time
|
||||
|
||||
local_time(int h, int m, int s,
|
||||
int ms = 0, int us = 0, int ns = 0)
|
||||
: hour (static_cast<std::uint8_t>(h)),
|
||||
minute(static_cast<std::uint8_t>(m)),
|
||||
second(static_cast<std::uint8_t>(s)),
|
||||
millisecond(static_cast<std::uint16_t>(ms)),
|
||||
microsecond(static_cast<std::uint16_t>(us)),
|
||||
nanosecond (static_cast<std::uint16_t>(ns))
|
||||
: hour {static_cast<std::uint8_t>(h)},
|
||||
minute{static_cast<std::uint8_t>(m)},
|
||||
second{static_cast<std::uint8_t>(s)},
|
||||
millisecond{static_cast<std::uint16_t>(ms)},
|
||||
microsecond{static_cast<std::uint16_t>(us)},
|
||||
nanosecond {static_cast<std::uint16_t>(ns)}
|
||||
{}
|
||||
|
||||
explicit local_time(const std::tm& t)
|
||||
: hour (static_cast<std::uint8_t>(t.tm_hour)),
|
||||
minute(static_cast<std::uint8_t>(t.tm_min)),
|
||||
second(static_cast<std::uint8_t>(t.tm_sec)),
|
||||
millisecond(0), microsecond(0), nanosecond(0)
|
||||
: hour {static_cast<std::uint8_t>(t.tm_hour)},
|
||||
minute{static_cast<std::uint8_t>(t.tm_min )},
|
||||
second{static_cast<std::uint8_t>(t.tm_sec )},
|
||||
millisecond{0}, microsecond{0}, nanosecond{0}
|
||||
{}
|
||||
|
||||
template<typename Rep, typename Period>
|
||||
@@ -160,8 +149,8 @@ struct time_offset
|
||||
std::int8_t minute{0}; // [-59, 59]
|
||||
|
||||
time_offset(int h, int m)
|
||||
: hour (static_cast<std::int8_t>(h)),
|
||||
minute(static_cast<std::int8_t>(m))
|
||||
: hour {static_cast<std::int8_t>(h)},
|
||||
minute{static_cast<std::int8_t>(m)}
|
||||
{}
|
||||
|
||||
operator std::chrono::minutes() const;
|
||||
@@ -192,9 +181,9 @@ struct local_datetime
|
||||
local_date date{};
|
||||
local_time time{};
|
||||
|
||||
local_datetime(local_date d, local_time t): date(d), time(t) {}
|
||||
local_datetime(local_date d, local_time t): date{d}, time{t} {}
|
||||
|
||||
explicit local_datetime(const std::tm& t): date(t), time(t){}
|
||||
explicit local_datetime(const std::tm& t): date{t}, time{t}{}
|
||||
|
||||
explicit local_datetime(const std::chrono::system_clock::time_point& tp);
|
||||
explicit local_datetime(const std::time_t t);
|
||||
@@ -230,10 +219,10 @@ struct offset_datetime
|
||||
time_offset offset{};
|
||||
|
||||
offset_datetime(local_date d, local_time t, time_offset o)
|
||||
: date(d), time(t), offset(o)
|
||||
: date{d}, time{t}, offset{o}
|
||||
{}
|
||||
offset_datetime(const local_datetime& dt, time_offset o)
|
||||
: date(dt.date), time(dt.time), offset(o)
|
||||
: date{dt.date}, time{dt.time}, offset{o}
|
||||
{}
|
||||
// use the current local timezone offset
|
||||
explicit offset_datetime(const local_datetime& ld);
|
||||
|
||||
@@ -232,12 +232,12 @@ struct value_with_format
|
||||
value_with_format& operator=(value_with_format&&) = default;
|
||||
|
||||
value_with_format(value_type v, format_type f)
|
||||
: value(std::move(v)), format(std::move(f))
|
||||
: value{std::move(v)}, format{std::move(f)}
|
||||
{}
|
||||
|
||||
template<typename U>
|
||||
value_with_format(value_with_format<U, format_type> other)
|
||||
: value(std::move(other.value)), format(std::move(other.format))
|
||||
: value{std::move(other.value)}, format{std::move(other.format)}
|
||||
{}
|
||||
|
||||
value_type value;
|
||||
|
||||
@@ -107,10 +107,8 @@ std::string format_location(
|
||||
{
|
||||
const auto lnw = detail::line_width(loc, msg, tail...);
|
||||
|
||||
std::ostringstream oss;
|
||||
detail::format_filename(oss, loc);
|
||||
|
||||
return oss.str() + detail::format_location_rec(lnw, loc.file_name(), loc, msg, tail...);
|
||||
const std::string f(""); // at the 1st iteration, no prev_filename is given
|
||||
return detail::format_location_rec(lnw, f, loc, msg, tail...);
|
||||
}
|
||||
|
||||
} // toml
|
||||
|
||||
@@ -78,7 +78,7 @@ TOML11_INLINE local_date::local_date(const std::chrono::system_clock::time_point
|
||||
}
|
||||
|
||||
TOML11_INLINE local_date::local_date(const std::time_t t)
|
||||
: local_date(std::chrono::system_clock::from_time_t(t))
|
||||
: local_date{std::chrono::system_clock::from_time_t(t)}
|
||||
{}
|
||||
|
||||
TOML11_INLINE local_date::operator std::chrono::system_clock::time_point() const
|
||||
@@ -294,7 +294,7 @@ TOML11_INLINE local_datetime::local_datetime(const std::chrono::system_clock::ti
|
||||
}
|
||||
|
||||
TOML11_INLINE local_datetime::local_datetime(const std::time_t t)
|
||||
: local_datetime(std::chrono::system_clock::from_time_t(t))
|
||||
: local_datetime{std::chrono::system_clock::from_time_t(t)}
|
||||
{}
|
||||
|
||||
TOML11_INLINE local_datetime::operator std::chrono::system_clock::time_point() const
|
||||
@@ -380,11 +380,11 @@ TOML11_INLINE std::string to_string(const local_datetime& dt)
|
||||
|
||||
|
||||
TOML11_INLINE offset_datetime::offset_datetime(const local_datetime& ld)
|
||||
: date(ld.date), time(ld.time), offset(get_local_offset(nullptr))
|
||||
: date{ld.date}, time{ld.time}, offset{get_local_offset(nullptr)}
|
||||
// use the current local timezone offset
|
||||
{}
|
||||
TOML11_INLINE offset_datetime::offset_datetime(const std::chrono::system_clock::time_point& tp)
|
||||
: offset(0, 0) // use gmtime
|
||||
: offset{0, 0} // use gmtime
|
||||
{
|
||||
const auto timet = std::chrono::system_clock::to_time_t(tp);
|
||||
const auto tm = detail::gmtime_s(&timet);
|
||||
@@ -392,14 +392,14 @@ TOML11_INLINE offset_datetime::offset_datetime(const std::chrono::system_clock::
|
||||
this->time = local_time(tm);
|
||||
}
|
||||
TOML11_INLINE offset_datetime::offset_datetime(const std::time_t& t)
|
||||
: offset(0, 0) // use gmtime
|
||||
: offset{0, 0} // use gmtime
|
||||
{
|
||||
const auto tm = detail::gmtime_s(&t);
|
||||
this->date = local_date(tm);
|
||||
this->time = local_time(tm);
|
||||
}
|
||||
TOML11_INLINE offset_datetime::offset_datetime(const std::tm& t)
|
||||
: offset(0, 0) // assume gmtime
|
||||
: offset{0, 0} // assume gmtime
|
||||
{
|
||||
this->date = local_date(t);
|
||||
this->time = local_time(t);
|
||||
|
||||
@@ -126,16 +126,53 @@ TOML11_INLINE std::vector<std::string> region::as_lines() const
|
||||
assert(this->is_ok());
|
||||
if(this->length_ == 0)
|
||||
{
|
||||
return {""};
|
||||
return std::vector<std::string>{""};
|
||||
}
|
||||
|
||||
const auto begin = std::next(this->source_->cbegin(), static_cast<difference_type>(this->first_));
|
||||
const auto end = std::next(this->source_->cbegin(), static_cast<difference_type>(this->last_ ));
|
||||
// Consider the following toml file
|
||||
// ```
|
||||
// array = [
|
||||
// ] # comment
|
||||
// ```
|
||||
// and the region represnets
|
||||
// ```
|
||||
// [
|
||||
// ]
|
||||
// ```
|
||||
// but we want to show the following.
|
||||
// ```
|
||||
// array = [
|
||||
// ] # comment
|
||||
// ```
|
||||
// So we need to find LFs before `begin` and after `end`.
|
||||
//
|
||||
// But, if region ends with LF, it should not include the next line.
|
||||
// ```
|
||||
// a = 42
|
||||
// ^^^- with the last LF
|
||||
// ```
|
||||
// So we start from `end-1` when looking for LF.
|
||||
|
||||
const auto line_begin = std::find(cxx::make_reverse_iterator(begin), this->source_->crend(), char_type('\n'));
|
||||
const auto begin_idx = static_cast<difference_type>(this->first_);
|
||||
const auto end_idx = static_cast<difference_type>(this->last_) - 1;
|
||||
|
||||
// length_ != 0, so begin < end. then begin <= end-1
|
||||
assert(begin_idx <= end_idx);
|
||||
|
||||
const auto begin = std::next(this->source_->cbegin(), begin_idx);
|
||||
const auto end = std::next(this->source_->cbegin(), end_idx);
|
||||
|
||||
const auto line_begin = std::find(cxx::make_reverse_iterator(begin), this->source_->crend(), char_type('\n')).base();
|
||||
const auto line_end = std::find(end, this->source_->cend(), char_type('\n'));
|
||||
|
||||
std::istringstream iss(make_string(line_begin.base(), line_end));
|
||||
const auto reg_lines = make_string(line_begin, line_end);
|
||||
|
||||
if(reg_lines == "") // the region is an empty line that only contains LF
|
||||
{
|
||||
return std::vector<std::string>{""};
|
||||
}
|
||||
|
||||
std::istringstream iss(reg_lines);
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::string line;
|
||||
|
||||
@@ -183,27 +183,27 @@ struct result
|
||||
using value_type = typename success_type::value_type;
|
||||
using error_type = typename failure_type::value_type;
|
||||
|
||||
result(success_type s): is_ok_(true), succ(std::move(s)) {}
|
||||
result(failure_type f): is_ok_(false), fail(std::move(f)) {}
|
||||
result(success_type s): is_ok_(true), succ_(std::move(s)) {}
|
||||
result(failure_type f): is_ok_(false), fail_(std::move(f)) {}
|
||||
|
||||
template<typename U, cxx::enable_if_t<cxx::conjunction<
|
||||
cxx::negation<std::is_same<cxx::remove_cvref_t<U>, value_type>>,
|
||||
std::is_convertible<cxx::remove_cvref_t<U>, value_type>
|
||||
>::value, std::nullptr_t> = nullptr>
|
||||
result(success<U> s): is_ok_(true), succ(std::move(s.value)) {}
|
||||
result(success<U> s): is_ok_(true), succ_(std::move(s.value)) {}
|
||||
|
||||
template<typename U, cxx::enable_if_t<cxx::conjunction<
|
||||
cxx::negation<std::is_same<cxx::remove_cvref_t<U>, error_type>>,
|
||||
std::is_convertible<cxx::remove_cvref_t<U>, error_type>
|
||||
>::value, std::nullptr_t> = nullptr>
|
||||
result(failure<U> f): is_ok_(false), fail(std::move(f.value)) {}
|
||||
result(failure<U> f): is_ok_(false), fail_(std::move(f.value)) {}
|
||||
|
||||
result& operator=(success_type s)
|
||||
{
|
||||
this->cleanup();
|
||||
this->is_ok_ = true;
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
|
||||
assert(tmp == std::addressof(this->succ));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(s));
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
return *this;
|
||||
}
|
||||
@@ -211,8 +211,8 @@ struct result
|
||||
{
|
||||
this->cleanup();
|
||||
this->is_ok_ = false;
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(f));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
return *this;
|
||||
}
|
||||
@@ -222,8 +222,8 @@ struct result
|
||||
{
|
||||
this->cleanup();
|
||||
this->is_ok_ = true;
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
|
||||
assert(tmp == std::addressof(this->succ));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(s.value));
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
return *this;
|
||||
}
|
||||
@@ -232,8 +232,8 @@ struct result
|
||||
{
|
||||
this->cleanup();
|
||||
this->is_ok_ = false;
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(f.value));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
return *this;
|
||||
}
|
||||
@@ -244,14 +244,14 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||
assert(tmp == std::addressof(this->succ));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.succ_);
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.fail_);
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
}
|
||||
@@ -259,14 +259,14 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||
assert(tmp == std::addressof(this->succ));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.succ_));
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.fail_));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
}
|
||||
@@ -276,14 +276,14 @@ struct result
|
||||
this->cleanup();
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
|
||||
assert(tmp == std::addressof(this->succ));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.succ_);
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.fail_);
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
is_ok_ = other.is_ok();
|
||||
@@ -294,14 +294,14 @@ struct result
|
||||
this->cleanup();
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||
assert(tmp == std::addressof(this->succ));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.succ_));
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.fail_));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
is_ok_ = other.is_ok();
|
||||
@@ -318,14 +318,14 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||
assert(tmp == std::addressof(this->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.as_err()));
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.as_err()));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
}
|
||||
@@ -341,14 +341,14 @@ struct result
|
||||
this->cleanup();
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
|
||||
assert(tmp == std::addressof(this->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.as_err()));
|
||||
assert(tmp == std::addressof(this->fail));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.as_err()));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
is_ok_ = other.is_ok();
|
||||
@@ -366,7 +366,7 @@ struct result
|
||||
{
|
||||
throw bad_result_access("toml::result: bad unwrap" + cxx::to_string(loc));
|
||||
}
|
||||
return this->succ.get();
|
||||
return this->succ_.get();
|
||||
}
|
||||
value_type const& unwrap(cxx::source_location loc = cxx::source_location::current()) const
|
||||
{
|
||||
@@ -374,18 +374,18 @@ struct result
|
||||
{
|
||||
throw bad_result_access("toml::result: bad unwrap" + cxx::to_string(loc));
|
||||
}
|
||||
return this->succ.get();
|
||||
return this->succ_.get();
|
||||
}
|
||||
|
||||
value_type& unwrap_or(value_type& opt) noexcept
|
||||
{
|
||||
if(this->is_err()) {return opt;}
|
||||
return this->succ.get();
|
||||
return this->succ_.get();
|
||||
}
|
||||
value_type const& unwrap_or(value_type const& opt) const noexcept
|
||||
{
|
||||
if(this->is_err()) {return opt;}
|
||||
return this->succ.get();
|
||||
return this->succ_.get();
|
||||
}
|
||||
|
||||
error_type& unwrap_err(cxx::source_location loc = cxx::source_location::current())
|
||||
@@ -394,7 +394,7 @@ struct result
|
||||
{
|
||||
throw bad_result_access("toml::result: bad unwrap_err" + cxx::to_string(loc));
|
||||
}
|
||||
return this->fail.get();
|
||||
return this->fail_.get();
|
||||
}
|
||||
error_type const& unwrap_err(cxx::source_location loc = cxx::source_location::current()) const
|
||||
{
|
||||
@@ -402,29 +402,29 @@ struct result
|
||||
{
|
||||
throw bad_result_access("toml::result: bad unwrap_err" + cxx::to_string(loc));
|
||||
}
|
||||
return this->fail.get();
|
||||
return this->fail_.get();
|
||||
}
|
||||
|
||||
value_type& as_ok() noexcept
|
||||
{
|
||||
assert(this->is_ok());
|
||||
return this->succ.get();
|
||||
return this->succ_.get();
|
||||
}
|
||||
value_type const& as_ok() const noexcept
|
||||
{
|
||||
assert(this->is_ok());
|
||||
return this->succ.get();
|
||||
return this->succ_.get();
|
||||
}
|
||||
|
||||
error_type& as_err() noexcept
|
||||
{
|
||||
assert(this->is_err());
|
||||
return this->fail.get();
|
||||
return this->fail_.get();
|
||||
}
|
||||
error_type const& as_err() const noexcept
|
||||
{
|
||||
assert(this->is_err());
|
||||
return this->fail.get();
|
||||
return this->fail_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -436,8 +436,8 @@ struct result
|
||||
#pragma GCC diagnostic ignored "-Wduplicated-branches"
|
||||
#endif
|
||||
|
||||
if(this->is_ok_) {this->succ.~success_type();}
|
||||
else {this->fail.~failure_type();}
|
||||
if(this->is_ok_) {this->succ_.~success_type();}
|
||||
else {this->fail_.~failure_type();}
|
||||
|
||||
#if defined(__GNUC__) && ! defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
@@ -450,8 +450,8 @@ struct result
|
||||
bool is_ok_;
|
||||
union
|
||||
{
|
||||
success_type succ;
|
||||
failure_type fail;
|
||||
success_type succ_;
|
||||
failure_type fail_;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace toml
|
||||
struct semantic_version
|
||||
{
|
||||
constexpr semantic_version(std::uint32_t mjr, std::uint32_t mnr, std::uint32_t p) noexcept
|
||||
: major(mjr), minor(mnr), patch(p)
|
||||
: major{mjr}, minor{mnr}, patch{p}
|
||||
{}
|
||||
|
||||
std::uint32_t major;
|
||||
@@ -87,17 +87,17 @@ struct spec
|
||||
}
|
||||
|
||||
constexpr explicit spec(const semantic_version& semver) noexcept
|
||||
: version(semver),
|
||||
v1_1_0_allow_control_characters_in_comments (semantic_version(1, 1, 0) <= semver),
|
||||
v1_1_0_allow_newlines_in_inline_tables (semantic_version(1, 1, 0) <= semver),
|
||||
v1_1_0_allow_trailing_comma_in_inline_tables(semantic_version(1, 1, 0) <= semver),
|
||||
v1_1_0_allow_non_english_in_bare_keys (semantic_version(1, 1, 0) <= semver),
|
||||
v1_1_0_add_escape_sequence_e (semantic_version(1, 1, 0) <= semver),
|
||||
v1_1_0_add_escape_sequence_x (semantic_version(1, 1, 0) <= semver),
|
||||
v1_1_0_make_seconds_optional (semantic_version(1, 1, 0) <= semver),
|
||||
ext_hex_float (false),
|
||||
ext_num_suffix(false),
|
||||
ext_null_value(false)
|
||||
: version{semver},
|
||||
v1_1_0_allow_control_characters_in_comments {semantic_version{1, 1, 0} <= semver},
|
||||
v1_1_0_allow_newlines_in_inline_tables {semantic_version{1, 1, 0} <= semver},
|
||||
v1_1_0_allow_trailing_comma_in_inline_tables{semantic_version{1, 1, 0} <= semver},
|
||||
v1_1_0_allow_non_english_in_bare_keys {semantic_version{1, 1, 0} <= semver},
|
||||
v1_1_0_add_escape_sequence_e {semantic_version{1, 1, 0} <= semver},
|
||||
v1_1_0_add_escape_sequence_x {semantic_version{1, 1, 0} <= semver},
|
||||
v1_1_0_make_seconds_optional {semantic_version{1, 1, 0} <= semver},
|
||||
ext_hex_float {false},
|
||||
ext_num_suffix{false},
|
||||
ext_null_value{false}
|
||||
{}
|
||||
|
||||
semantic_version version; // toml version
|
||||
|
||||
@@ -23,25 +23,25 @@ struct storage
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
explicit storage(value_type v): ptr(cxx::make_unique<T>(std::move(v))) {}
|
||||
explicit storage(value_type v): ptr_(cxx::make_unique<T>(std::move(v))) {}
|
||||
~storage() = default;
|
||||
|
||||
storage(const storage& rhs): ptr(cxx::make_unique<T>(*rhs.ptr)) {}
|
||||
storage(const storage& rhs): ptr_(cxx::make_unique<T>(*rhs.ptr_)) {}
|
||||
storage& operator=(const storage& rhs)
|
||||
{
|
||||
this->ptr = cxx::make_unique<T>(*rhs.ptr);
|
||||
this->ptr_ = cxx::make_unique<T>(*rhs.ptr_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
storage(storage&&) = default;
|
||||
storage& operator=(storage&&) = default;
|
||||
|
||||
bool is_ok() const noexcept {return static_cast<bool>(ptr);}
|
||||
bool is_ok() const noexcept {return static_cast<bool>(ptr_);}
|
||||
|
||||
value_type& get() const noexcept {return *ptr;}
|
||||
value_type& get() const noexcept {return *ptr_;}
|
||||
|
||||
private:
|
||||
std::unique_ptr<value_type> ptr;
|
||||
std::unique_ptr<value_type> ptr_;
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
@@ -90,12 +90,19 @@ 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>
|
||||
static std::false_type check(...);
|
||||
template<typename T, std::size_t S = sizeof(::toml::into<T>)>
|
||||
static std::true_type check(::toml::from<T>*);
|
||||
static std::true_type check(::toml::into<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
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
namespace toml
|
||||
{
|
||||
template<typename TypeConfig>
|
||||
class basic_value;
|
||||
|
||||
struct type_error final : public ::toml::exception
|
||||
{
|
||||
@@ -42,6 +44,15 @@ struct type_error final : public ::toml::exception
|
||||
// only for internal use
|
||||
namespace detail
|
||||
{
|
||||
template<typename TC>
|
||||
error_info make_type_error(const basic_value<TC>&, const std::string&, const value_t);
|
||||
|
||||
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>&);
|
||||
|
||||
@@ -1192,7 +1203,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::boolean)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_boolean(): ", value_t::boolean);
|
||||
this->throw_bad_cast("toml::value::as_boolean()", value_t::boolean);
|
||||
}
|
||||
return this->boolean_.value;
|
||||
}
|
||||
@@ -1200,7 +1211,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::integer)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_integer(): ", value_t::integer);
|
||||
this->throw_bad_cast("toml::value::as_integer()", value_t::integer);
|
||||
}
|
||||
return this->integer_.value;
|
||||
}
|
||||
@@ -1208,7 +1219,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::floating)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_floating(): ", value_t::floating);
|
||||
this->throw_bad_cast("toml::value::as_floating()", value_t::floating);
|
||||
}
|
||||
return this->floating_.value;
|
||||
}
|
||||
@@ -1216,7 +1227,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::string)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_string(): ", value_t::string);
|
||||
this->throw_bad_cast("toml::value::as_string()", value_t::string);
|
||||
}
|
||||
return this->string_.value;
|
||||
}
|
||||
@@ -1224,7 +1235,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::offset_datetime)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_offset_datetime(): ", value_t::offset_datetime);
|
||||
this->throw_bad_cast("toml::value::as_offset_datetime()", value_t::offset_datetime);
|
||||
}
|
||||
return this->offset_datetime_.value;
|
||||
}
|
||||
@@ -1232,7 +1243,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_datetime)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_datetime(): ", value_t::local_datetime);
|
||||
this->throw_bad_cast("toml::value::as_local_datetime()", value_t::local_datetime);
|
||||
}
|
||||
return this->local_datetime_.value;
|
||||
}
|
||||
@@ -1240,7 +1251,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_date)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_date(): ", value_t::local_date);
|
||||
this->throw_bad_cast("toml::value::as_local_date()", value_t::local_date);
|
||||
}
|
||||
return this->local_date_.value;
|
||||
}
|
||||
@@ -1248,7 +1259,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_time)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_time(): ", value_t::local_time);
|
||||
this->throw_bad_cast("toml::value::as_local_time()", value_t::local_time);
|
||||
}
|
||||
return this->local_time_.value;
|
||||
}
|
||||
@@ -1256,7 +1267,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::array)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_array(): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::as_array()", value_t::array);
|
||||
}
|
||||
return this->array_.value.get();
|
||||
}
|
||||
@@ -1264,7 +1275,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::table)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_table(): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::as_table()", value_t::table);
|
||||
}
|
||||
return this->table_.value.get();
|
||||
}
|
||||
@@ -1276,7 +1287,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::boolean)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_boolean(): ", value_t::boolean);
|
||||
this->throw_bad_cast("toml::value::as_boolean()", value_t::boolean);
|
||||
}
|
||||
return this->boolean_.value;
|
||||
}
|
||||
@@ -1284,7 +1295,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::integer)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_integer(): ", value_t::integer);
|
||||
this->throw_bad_cast("toml::value::as_integer()", value_t::integer);
|
||||
}
|
||||
return this->integer_.value;
|
||||
}
|
||||
@@ -1292,7 +1303,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::floating)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_floating(): ", value_t::floating);
|
||||
this->throw_bad_cast("toml::value::as_floating()", value_t::floating);
|
||||
}
|
||||
return this->floating_.value;
|
||||
}
|
||||
@@ -1300,7 +1311,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::string)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_string(): ", value_t::string);
|
||||
this->throw_bad_cast("toml::value::as_string()", value_t::string);
|
||||
}
|
||||
return this->string_.value;
|
||||
}
|
||||
@@ -1308,7 +1319,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::offset_datetime)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_offset_datetime(): ", value_t::offset_datetime);
|
||||
this->throw_bad_cast("toml::value::as_offset_datetime()", value_t::offset_datetime);
|
||||
}
|
||||
return this->offset_datetime_.value;
|
||||
}
|
||||
@@ -1316,7 +1327,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_datetime)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_datetime(): ", value_t::local_datetime);
|
||||
this->throw_bad_cast("toml::value::as_local_datetime()", value_t::local_datetime);
|
||||
}
|
||||
return this->local_datetime_.value;
|
||||
}
|
||||
@@ -1324,7 +1335,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_date)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_date(): ", value_t::local_date);
|
||||
this->throw_bad_cast("toml::value::as_local_date()", value_t::local_date);
|
||||
}
|
||||
return this->local_date_.value;
|
||||
}
|
||||
@@ -1332,7 +1343,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_time)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_time(): ", value_t::local_time);
|
||||
this->throw_bad_cast("toml::value::as_local_time()", value_t::local_time);
|
||||
}
|
||||
return this->local_time_.value;
|
||||
}
|
||||
@@ -1340,7 +1351,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::array)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_array(): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::as_array()", value_t::array);
|
||||
}
|
||||
return this->array_.value.get();
|
||||
}
|
||||
@@ -1348,7 +1359,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::table)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_table(): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::as_table()", value_t::table);
|
||||
}
|
||||
return this->table_.value.get();
|
||||
}
|
||||
@@ -1411,7 +1422,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::boolean)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_boolean_fmt(): ", value_t::boolean);
|
||||
this->throw_bad_cast("toml::value::as_boolean_fmt()", value_t::boolean);
|
||||
}
|
||||
return this->boolean_.format;
|
||||
}
|
||||
@@ -1419,7 +1430,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::integer)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_integer_fmt(): ", value_t::integer);
|
||||
this->throw_bad_cast("toml::value::as_integer_fmt()", value_t::integer);
|
||||
}
|
||||
return this->integer_.format;
|
||||
}
|
||||
@@ -1427,7 +1438,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::floating)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_floating_fmt(): ", value_t::floating);
|
||||
this->throw_bad_cast("toml::value::as_floating_fmt()", value_t::floating);
|
||||
}
|
||||
return this->floating_.format;
|
||||
}
|
||||
@@ -1435,7 +1446,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::string)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_string_fmt(): ", value_t::string);
|
||||
this->throw_bad_cast("toml::value::as_string_fmt()", value_t::string);
|
||||
}
|
||||
return this->string_.format;
|
||||
}
|
||||
@@ -1443,7 +1454,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::offset_datetime)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_offset_datetime_fmt(): ", value_t::offset_datetime);
|
||||
this->throw_bad_cast("toml::value::as_offset_datetime_fmt()", value_t::offset_datetime);
|
||||
}
|
||||
return this->offset_datetime_.format;
|
||||
}
|
||||
@@ -1451,7 +1462,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_datetime)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_datetime_fmt(): ", value_t::local_datetime);
|
||||
this->throw_bad_cast("toml::value::as_local_datetime_fmt()", value_t::local_datetime);
|
||||
}
|
||||
return this->local_datetime_.format;
|
||||
}
|
||||
@@ -1459,7 +1470,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_date)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_date_fmt(): ", value_t::local_date);
|
||||
this->throw_bad_cast("toml::value::as_local_date_fmt()", value_t::local_date);
|
||||
}
|
||||
return this->local_date_.format;
|
||||
}
|
||||
@@ -1467,7 +1478,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_time)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_time_fmt(): ", value_t::local_time);
|
||||
this->throw_bad_cast("toml::value::as_local_time_fmt()", value_t::local_time);
|
||||
}
|
||||
return this->local_time_.format;
|
||||
}
|
||||
@@ -1475,7 +1486,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::array)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_array_fmt(): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::as_array_fmt()", value_t::array);
|
||||
}
|
||||
return this->array_.format;
|
||||
}
|
||||
@@ -1483,7 +1494,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::table)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_table_fmt(): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::as_table_fmt()", value_t::table);
|
||||
}
|
||||
return this->table_.format;
|
||||
}
|
||||
@@ -1495,7 +1506,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::boolean)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_boolean_fmt(): ", value_t::boolean);
|
||||
this->throw_bad_cast("toml::value::as_boolean_fmt()", value_t::boolean);
|
||||
}
|
||||
return this->boolean_.format;
|
||||
}
|
||||
@@ -1503,7 +1514,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::integer)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_integer_fmt(): ", value_t::integer);
|
||||
this->throw_bad_cast("toml::value::as_integer_fmt()", value_t::integer);
|
||||
}
|
||||
return this->integer_.format;
|
||||
}
|
||||
@@ -1511,7 +1522,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::floating)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_floating_fmt(): ", value_t::floating);
|
||||
this->throw_bad_cast("toml::value::as_floating_fmt()", value_t::floating);
|
||||
}
|
||||
return this->floating_.format;
|
||||
}
|
||||
@@ -1519,7 +1530,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::string)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_string_fmt(): ", value_t::string);
|
||||
this->throw_bad_cast("toml::value::as_string_fmt()", value_t::string);
|
||||
}
|
||||
return this->string_.format;
|
||||
}
|
||||
@@ -1527,7 +1538,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::offset_datetime)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_offset_datetime_fmt(): ", value_t::offset_datetime);
|
||||
this->throw_bad_cast("toml::value::as_offset_datetime_fmt()", value_t::offset_datetime);
|
||||
}
|
||||
return this->offset_datetime_.format;
|
||||
}
|
||||
@@ -1535,7 +1546,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_datetime)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_datetime_fmt(): ", value_t::local_datetime);
|
||||
this->throw_bad_cast("toml::value::as_local_datetime_fmt()", value_t::local_datetime);
|
||||
}
|
||||
return this->local_datetime_.format;
|
||||
}
|
||||
@@ -1543,7 +1554,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_date)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_date_fmt(): ", value_t::local_date);
|
||||
this->throw_bad_cast("toml::value::as_local_date_fmt()", value_t::local_date);
|
||||
}
|
||||
return this->local_date_.format;
|
||||
}
|
||||
@@ -1551,7 +1562,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::local_time)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_local_time_fmt(): ", value_t::local_time);
|
||||
this->throw_bad_cast("toml::value::as_local_time_fmt()", value_t::local_time);
|
||||
}
|
||||
return this->local_time_.format;
|
||||
}
|
||||
@@ -1559,7 +1570,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::array)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_array_fmt(): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::as_array_fmt()", value_t::array);
|
||||
}
|
||||
return this->array_.format;
|
||||
}
|
||||
@@ -1567,7 +1578,7 @@ class basic_value
|
||||
{
|
||||
if(this->type_ != value_t::table)
|
||||
{
|
||||
this->throw_bad_cast("toml::value::as_table_fmt(): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::as_table_fmt()", value_t::table);
|
||||
}
|
||||
return this->table_.format;
|
||||
}
|
||||
@@ -1579,13 +1590,13 @@ class basic_value
|
||||
{
|
||||
if(!this->is_table())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::at(key_type): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::at(key_type)", value_t::table);
|
||||
}
|
||||
auto& table = this->as_table(std::nothrow);
|
||||
const auto found = table.find(k);
|
||||
if(found == table.end())
|
||||
{
|
||||
this->throw_key_not_found_error(k);
|
||||
this->throw_key_not_found_error("toml::value::at", k);
|
||||
}
|
||||
assert(found->first == k);
|
||||
return found->second;
|
||||
@@ -1594,17 +1605,55 @@ class basic_value
|
||||
{
|
||||
if(!this->is_table())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::at(key_type): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::at(key_type)", value_t::table);
|
||||
}
|
||||
const auto& table = this->as_table(std::nothrow);
|
||||
const auto found = table.find(k);
|
||||
if(found == table.end())
|
||||
{
|
||||
this->throw_key_not_found_error(k);
|
||||
this->throw_key_not_found_error("toml::value::at", k);
|
||||
}
|
||||
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())
|
||||
@@ -1613,7 +1662,7 @@ class basic_value
|
||||
}
|
||||
else if( ! this->is_table()) // initialized, but not a table
|
||||
{
|
||||
this->throw_bad_cast("toml::value::operator[](key_type): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::operator[](key_type)", value_t::table);
|
||||
}
|
||||
return (this->as_table(std::nothrow))[k];
|
||||
}
|
||||
@@ -1621,7 +1670,7 @@ class basic_value
|
||||
{
|
||||
if(!this->is_table())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::count(key_type): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::count(key_type)", value_t::table);
|
||||
}
|
||||
return this->as_table(std::nothrow).count(k);
|
||||
}
|
||||
@@ -1629,7 +1678,7 @@ class basic_value
|
||||
{
|
||||
if(!this->is_table())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::contains(key_type): ", value_t::table);
|
||||
this->throw_bad_cast("toml::value::contains(key_type)", value_t::table);
|
||||
}
|
||||
const auto& table = this->as_table(std::nothrow);
|
||||
return table.find(k) != table.end();
|
||||
@@ -1642,7 +1691,7 @@ class basic_value
|
||||
{
|
||||
if(!this->is_array())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::at(idx): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::at(idx)", value_t::array);
|
||||
}
|
||||
auto& ar = this->as_array(std::nothrow);
|
||||
|
||||
@@ -1662,7 +1711,7 @@ class basic_value
|
||||
{
|
||||
if(!this->is_array())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::at(idx): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::at(idx)", value_t::array);
|
||||
}
|
||||
const auto& ar = this->as_array(std::nothrow);
|
||||
|
||||
@@ -1680,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...
|
||||
@@ -1695,7 +1779,7 @@ class basic_value
|
||||
{
|
||||
if(!this->is_array())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::push_back(idx): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::push_back(idx)", value_t::array);
|
||||
}
|
||||
this->as_array(std::nothrow).push_back(x);
|
||||
return;
|
||||
@@ -1704,7 +1788,7 @@ class basic_value
|
||||
{
|
||||
if(!this->is_array())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::push_back(idx): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::push_back(idx)", value_t::array);
|
||||
}
|
||||
this->as_array(std::nothrow).push_back(std::move(x));
|
||||
return;
|
||||
@@ -1715,7 +1799,7 @@ class basic_value
|
||||
{
|
||||
if(!this->is_array())
|
||||
{
|
||||
this->throw_bad_cast("toml::value::emplace_back(idx): ", value_t::array);
|
||||
this->throw_bad_cast("toml::value::emplace_back(idx)", value_t::array);
|
||||
}
|
||||
auto& ar = this->as_array(std::nothrow);
|
||||
ar.emplace_back(std::forward<Ts>(args) ...);
|
||||
@@ -1793,52 +1877,15 @@ class basic_value
|
||||
[[noreturn]]
|
||||
void throw_bad_cast(const std::string& funcname, const value_t ty) const
|
||||
{
|
||||
throw type_error(format_error(make_error_info(
|
||||
funcname + "bad_cast to " + to_string(ty),
|
||||
this->location(), "the actual type is " + to_string(this->type()))),
|
||||
this->location());
|
||||
throw type_error(format_error(detail::make_type_error(*this, funcname, ty)),
|
||||
this->location());
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void throw_key_not_found_error(const key_type& key) const
|
||||
void throw_key_not_found_error(const std::string& funcname, const key_type& key) const
|
||||
{
|
||||
const auto loc = this->location();
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << color::red << "[error] " << color::reset
|
||||
<< "key \"" << key << "\" not found";
|
||||
|
||||
// the value is not from a file. no information can be appended.
|
||||
if( ! loc.is_ok())
|
||||
{
|
||||
throw std::out_of_range(oss.str());
|
||||
}
|
||||
|
||||
// The top-level table has its region at the 0th character of the file.
|
||||
// That means that, in the case when a key is not found in the top-level
|
||||
// table, the error message points to the first character. If the file has
|
||||
// the first table at the first line, the error message would be like this.
|
||||
// ```console
|
||||
// [error] key "a" not found
|
||||
// --> example.toml
|
||||
// |
|
||||
// 1 | [table]
|
||||
// | ^------ in this table
|
||||
// ```
|
||||
// It actually points to the top-level table at the first character, not
|
||||
// `[table]`. But it is too confusing. To avoid the confusion, the error
|
||||
// message should explicitly say "key not found in the top-level table".
|
||||
if(loc.first_line_number() == 1 && loc.length() == 0)
|
||||
{
|
||||
oss << " at the top-level table in \"" << loc.file_name() << "\"";
|
||||
throw std::out_of_range(oss.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal table.
|
||||
oss << format_location(loc, "in this table");
|
||||
throw std::out_of_range(oss.str());
|
||||
}
|
||||
throw std::out_of_range(format_error(
|
||||
detail::make_not_found_error(*this, funcname, key)));
|
||||
}
|
||||
|
||||
template<typename TC>
|
||||
@@ -2079,6 +2126,62 @@ std::string format_error(std::string title,
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename TC>
|
||||
error_info make_type_error(const basic_value<TC>& v, const std::string& fname, const value_t ty)
|
||||
{
|
||||
return make_error_info(fname + ": bad_cast to " + to_string(ty),
|
||||
v.location(), "the actual type is " + to_string(v.type()));
|
||||
}
|
||||
template<typename TC>
|
||||
error_info make_not_found_error(const basic_value<TC>& v, const std::string& fname, const std::string& key)
|
||||
{
|
||||
const auto loc = v.location();
|
||||
const std::string title = fname + ": key \"" + key + "\" not found";
|
||||
|
||||
std::vector<std::pair<source_location, std::string>> locs;
|
||||
if( ! loc.is_ok())
|
||||
{
|
||||
return error_info(title, locs);
|
||||
}
|
||||
|
||||
if(loc.first_line_number() == 1 && loc.first_column_number() == 1 && loc.length() == 1)
|
||||
{
|
||||
// The top-level table has its region at the 0th character of the file.
|
||||
// That means that, in the case when a key is not found in the top-level
|
||||
// table, the error message points to the first character. If the file has
|
||||
// the first table at the first line, the error message would be like this.
|
||||
// ```console
|
||||
// [error] key "a" not found
|
||||
// --> example.toml
|
||||
// |
|
||||
// 1 | [table]
|
||||
// | ^------ in this table
|
||||
// ```
|
||||
// It actually points to the top-level table at the first character, not
|
||||
// `[table]`. But it is too confusing. To avoid the confusion, the error
|
||||
// message should explicitly say "key not found in the top-level table".
|
||||
locs.emplace_back(v.location(), "at the top-level table");
|
||||
}
|
||||
else
|
||||
{
|
||||
locs.emplace_back(v.location(), "in this table");
|
||||
}
|
||||
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> \
|
||||
struct getter<TC, value_t::ty> \
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#define TOML11_VERSION_MAJOR 4
|
||||
#define TOML11_VERSION_MINOR 0
|
||||
#define TOML11_VERSION_PATCH 0
|
||||
#define TOML11_VERSION_PATCH 1
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error "__cplusplus is not defined"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,13 @@ set(TOML11_TEST_NAMES
|
||||
test_comments
|
||||
test_datetime
|
||||
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
|
||||
|
||||
@@ -17,6 +17,15 @@
|
||||
#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::find with toml type")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
@@ -17,6 +17,15 @@
|
||||
#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::get with toml types")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
|
||||
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