mirror of
https://github.com/marzer/tomlplusplus.git
synced 2025-02-23 18:40:04 +00:00
added proper non-exhaustive visitor support to node::visit
also: - fixed preprocessor snafu - fixed bool `print_to_stream` overload not being selected - added `TOML_SMALL_FLOAT_TYPE` - added is_XXXXX node type metafunctions - added additional API documentation
This commit is contained in:
parent
635dec5c8e
commit
abdd4f9993
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -15,3 +15,4 @@
|
|||||||
*.sln text encoding=UTF-8-BOM eol=crlf
|
*.sln text encoding=UTF-8-BOM eol=crlf
|
||||||
*.runsettings text encoding=UTF-8 eol=crlf
|
*.runsettings text encoding=UTF-8 eol=crlf
|
||||||
*.md text encoding=UTF-8 eol=lf
|
*.md text encoding=UTF-8 eol=lf
|
||||||
|
*.css text encoding=UTF-8 eol=lf
|
||||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2019 Mark Gillard
|
Copyright (c) 2019-2020 Mark Gillard
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
||||||
|
68
README.md
68
README.md
@ -1,10 +1,24 @@
|
|||||||
# toml++ (tomlplusplus)
|
# toml++ (tomlplusplus)
|
||||||
Header-only [TOML v0.5.0] parsing lib for C++17 and later.
|

|
||||||
|
[][v0.5.0]
|
||||||
[](https://circleci.com/gh/marzer/tomlplusplus)
|
[](https://circleci.com/gh/marzer/tomlplusplus)
|
||||||
|
[](https://github.com/marzer/tomlplusplus/blob/master/LICENSE)
|
||||||
|
|
||||||
|
`toml++` is a header-only toml parser and serializer for C++17, C++20 and whatever comes after.
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
# Usage
|
# Example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
/// example goes here.
|
||||||
|
```
|
||||||
|
You'll find some more code examples in
|
||||||
|
`examples` directory and plenty more as part of the [API documentation].
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
# Adding toml++ to your project
|
||||||
`toml++` comes in two flavours: Regular and Single-header.
|
`toml++` comes in two flavours: Regular and Single-header.
|
||||||
|
|
||||||
### Regular mode
|
### Regular mode
|
||||||
@ -12,27 +26,25 @@ Header-only [TOML v0.5.0] parsing lib for C++17 and later.
|
|||||||
2. `#include <toml++/toml.h>`
|
2. `#include <toml++/toml.h>`
|
||||||
|
|
||||||
### Single-header mode
|
### Single-header mode
|
||||||
1. Drop `toml.hpp` somewhere in your source tree
|
1. Drop `toml.hpp` wherever you like in your source tree
|
||||||
2. There is no step two
|
2. There is no step two
|
||||||
|
|
||||||
The API is the same regardless of how you consume the library. You'll find code examples in
|
The API is the same regardless of how you consume the library.
|
||||||
the `examples` directory.
|
|
||||||
|
|
||||||
<br>
|
### Configuration
|
||||||
|
|
||||||
# Configuration
|
|
||||||
A number of configurable options are exposed in the form of preprocessor macros. Most likely you
|
A number of configurable options are exposed in the form of preprocessor macros. Most likely you
|
||||||
won't need to mess with these at all, but in the event you do, set your overrides prior to including
|
won't need to mess with these at all, but in the event you do, set your overrides prior to including
|
||||||
toml++.
|
toml++.
|
||||||
|
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
|----------------------------|:--------------:|-----------------------------------|-----------------------------------------------------------------------------------------------|
|
|----------------------------|:--------------:|-----------------------------------|----------------------------------------------------------------------------------------------------------|
|
||||||
| `TOML_ASSERT(expr)` | function macro | `assert(expr)`<br>(or undefined) | Sets the assert function used by the library. |
|
| `TOML_ASSERT(expr)` | function macro | `assert(expr)`<br>(or undefined) | Sets the assert function used by the library. |
|
||||||
| `TOML_CHAR_8_STRINGS` | boolean | `0` | Uses C++20 [char8_t]-based strings as the toml string data type. |
|
| `TOML_CHAR_8_STRINGS` | boolean | `0` | Uses C++20 [char8_t]-based strings as the toml string data type. |
|
||||||
| `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |
|
| `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |
|
||||||
| `TOML_LARGE_FILES` | boolean | `0` | Uses 32-bit integers for line and column indices (instead of 16-bit). |
|
| `TOML_LARGE_FILES` | boolean | `0` | Uses 32-bit integers for line and column indices (instead of 16-bit). |
|
||||||
| `TOML_UNDEF_MACROS` | boolean | `1` | `#undefs` the library's internal macros at the end of the header. |
|
| `TOML_SMALL_FLOAT_TYPE` | type name | undefined | If your codebase has an additional 'small' float type (e.g. half-precision), this tells toml++ about it. |
|
||||||
| `TOML_UNRELEASED_FEATURES` | boolean | `1` | Enables support for [unreleased TOML language features] not yet part of a [numbered version]. |
|
| `TOML_UNDEF_MACROS` | boolean | `1` | `#undefs` the library's internal macros at the end of the header. |
|
||||||
|
| `TOML_UNRELEASED_FEATURES` | boolean | `1` | Enables support for [unreleased TOML language features] not yet part of a [numbered version]. |
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@ -44,7 +56,7 @@ addition of unreleased features from the [TOML master] and some sane cherry-pick
|
|||||||
The library advertises the most recent numbered language version it fully supports via the preprocessor
|
The library advertises the most recent numbered language version it fully supports via the preprocessor
|
||||||
defines `TOML_LANG_MAJOR`, `TOML_LANG_MINOR` and `TOML_LANG_REVISION`.
|
defines `TOML_LANG_MAJOR`, `TOML_LANG_MINOR` and `TOML_LANG_REVISION`.
|
||||||
|
|
||||||
### **🔸Unreleased features:**
|
### **🔸Unreleased TOML features:**
|
||||||
- [#356]: Allow leading zeros in the exponent part of a float
|
- [#356]: Allow leading zeros in the exponent part of a float
|
||||||
- [#516]: Allow newlines and trailing commas in inline tables
|
- [#516]: Allow newlines and trailing commas in inline tables
|
||||||
- [#562]: Allow hex floatingpoint values
|
- [#562]: Allow hex floatingpoint values
|
||||||
@ -59,7 +71,7 @@ defines `TOML_LANG_MAJOR`, `TOML_LANG_MINOR` and `TOML_LANG_REVISION`.
|
|||||||
_These can be disabled (and thus strict [TOML v0.5.0] compliance enforced) by specifying
|
_These can be disabled (and thus strict [TOML v0.5.0] compliance enforced) by specifying
|
||||||
`TOML_UNRELEASED_FEATURES = 0` (see [Configuration](#Configuration))._
|
`TOML_UNRELEASED_FEATURES = 0` (see [Configuration](#Configuration))._
|
||||||
|
|
||||||
### **🔹[v0.5.0](https://github.com/toml-lang/toml/releases/tag/v0.5.0) and earlier:**
|
### **🔹TOML v0.5.0 and earlier:**
|
||||||
- All features as of `<< release date >>`.
|
- All features as of `<< release date >>`.
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@ -69,8 +81,8 @@ Contributions are welcome, either by [reporting issues](https://github.com/marze
|
|||||||
or submitting pull requests. If you wish to submit a PR, please be aware that:
|
or submitting pull requests. If you wish to submit a PR, please be aware that:
|
||||||
- The single-header file `toml.hpp` is generated by a script; make your changes in the files in
|
- The single-header file `toml.hpp` is generated by a script; make your changes in the files in
|
||||||
`include`, **not** in `toml.hpp`.
|
`include`, **not** in `toml.hpp`.
|
||||||
- Your changes should compile warning-free on at least gcc 8.3.0, clang 8.0, and MSVC 19.2X
|
- Your changes should compile warning-free on at least one of gcc 8.3.0, clang 8.0, and MSVC 19.2X
|
||||||
(Visual Studio 2019).
|
(Visual Studio 2019). All three is a bonus.
|
||||||
- You should regenerate the single-header file as part of your PR (a CI check will fail if you don't).
|
- You should regenerate the single-header file as part of your PR (a CI check will fail if you don't).
|
||||||
|
|
||||||
### Regenerating toml.hpp
|
### Regenerating toml.hpp
|
||||||
@ -80,10 +92,10 @@ or submitting pull requests. If you wish to submit a PR, please be aware that:
|
|||||||
3. Run `python/generate_single_header.py`
|
3. Run `python/generate_single_header.py`
|
||||||
|
|
||||||
### Building and testing
|
### Building and testing
|
||||||
Testing is done using [catch2], included in the respository as a submodule under `tests/catch2`.
|
Testing is done using [Catch2], included in the respository as a submodule under `extern/Catch2`.
|
||||||
The first time you want to begin testing you'll need to ensure submodules have been fetched:
|
The first time you want to begin testing you'll need to ensure submodules have been fetched:
|
||||||
```bash
|
```bash
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive extern/Catch2
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Windows
|
#### Windows
|
||||||
@ -100,10 +112,8 @@ Install [meson] and [ninja] if necessary, then test with both gcc and clang:
|
|||||||
```bash
|
```bash
|
||||||
CXX=g++ meson build-gcc
|
CXX=g++ meson build-gcc
|
||||||
CXX=clang++ meson build-clang
|
CXX=clang++ meson build-clang
|
||||||
cd build-gcc
|
cd build-gcc && ninja && ninja test
|
||||||
ninja && ninja test
|
cd ../build-clang && ninja && ninja test
|
||||||
cd ../build-clang
|
|
||||||
ninja && ninja test
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@ -113,21 +123,23 @@ ninja && ninja test
|
|||||||
`toml++` is licensed under the terms of the MIT license - See [LICENSE].
|
`toml++` is licensed under the terms of the MIT license - See [LICENSE].
|
||||||
|
|
||||||
UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[Flexible and Economical UTF-8 Decoder]',
|
UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[Flexible and Economical UTF-8 Decoder]',
|
||||||
which is itself subject to the terms of the MIT license. The license text is included in the
|
which is itself subject to the terms of (what appears to be) the MIT license. The license text is included in the
|
||||||
[relevant part](https://github.com/marzer/tomlplusplus/blob/master/include/toml%2B%2B/toml_utf8.h)
|
[relevant part](https://github.com/marzer/tomlplusplus/blob/master/include/toml%2B%2B/toml_utf8.h)
|
||||||
of the toml++ source.
|
of the toml++ source.
|
||||||
|
|
||||||
|
[API documentation]: https://marzer.github.io/tomlplusplus/namespacetoml.html
|
||||||
[unreleased TOML language features]: https://github.com/marzer/tomlplusplus#unreleased-features
|
[unreleased TOML language features]: https://github.com/marzer/tomlplusplus#unreleased-features
|
||||||
[numbered version]: https://github.com/toml-lang/toml/releases
|
[numbered version]: https://github.com/toml-lang/toml/releases
|
||||||
[char8_t]: https://en.cppreference.com/w/cpp/keyword/char8_t
|
[char8_t]: https://en.cppreference.com/w/cpp/keyword/char8_t
|
||||||
[TOML master]: https://github.com/toml-lang/toml/blob/master/README.md
|
[TOML master]: https://github.com/toml-lang/toml/blob/master/README.md
|
||||||
[TOML issues list]: https://github.com/toml-lang/toml/issues
|
[TOML issues list]: https://github.com/toml-lang/toml/issues
|
||||||
[TOML v0.5.0]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md
|
[TOML v0.5.0]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md
|
||||||
|
[v0.5.0]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md
|
||||||
[LICENSE]: https://github.com/marzer/tomlplusplus/blob/master/LICENSE
|
[LICENSE]: https://github.com/marzer/tomlplusplus/blob/master/LICENSE
|
||||||
[Flexible and Economical UTF-8 Decoder]: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
[Flexible and Economical UTF-8 Decoder]: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||||
[meson]: https://mesonbuild.com/Getting-meson.html
|
[meson]: https://mesonbuild.com/Getting-meson.html
|
||||||
[ninja]: https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages
|
[ninja]: https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages
|
||||||
[catch2]: https://github.com/catchorg/Catch2
|
[Catch2]: https://github.com/catchorg/Catch2
|
||||||
[Test Adapter for Catch2]: https://marketplace.visualstudio.com/items?itemName=JohnnyHendriks.ext01
|
[Test Adapter for Catch2]: https://marketplace.visualstudio.com/items?itemName=JohnnyHendriks.ext01
|
||||||
[Visual Studio 2019]: https://visualstudio.microsoft.com/vs/
|
[Visual Studio 2019]: https://visualstudio.microsoft.com/vs/
|
||||||
[#356]: https://github.com/toml-lang/toml/issues/356
|
[#356]: https://github.com/toml-lang/toml/issues/356
|
||||||
|
@ -10,8 +10,12 @@ TAB_SIZE = 4
|
|||||||
HTML_EXTRA_FILES = tomlplusplus.js
|
HTML_EXTRA_FILES = tomlplusplus.js
|
||||||
SHOW_INCLUDE_FILES = NO
|
SHOW_INCLUDE_FILES = NO
|
||||||
##! M_THEME_COLOR = #22272e
|
##! M_THEME_COLOR = #22272e
|
||||||
##! M_LINKS_NAVBAR1 = pages
|
##! M_LINKS_NAVBAR1 = \
|
||||||
##! M_LINKS_NAVBAR2 = annotated
|
##! pages
|
||||||
|
##! M_LINKS_NAVBAR2 = \
|
||||||
|
##! namespaces \
|
||||||
|
##! annotated \
|
||||||
|
##! "<a target="_blank" href="https://github.com/marzer/tomlplusplus/">Github</a>"
|
||||||
##! M_SEARCH_DOWNLOAD_BINARY = NO
|
##! M_SEARCH_DOWNLOAD_BINARY = NO
|
||||||
##! M_CLASS_TREE_EXPAND_LEVELS = 3
|
##! M_CLASS_TREE_EXPAND_LEVELS = 3
|
||||||
##! M_FILE_TREE_EXPAND_LEVELS = 3
|
##! M_FILE_TREE_EXPAND_LEVELS = 3
|
||||||
@ -19,3 +23,4 @@ SHOW_INCLUDE_FILES = NO
|
|||||||
##! <a target="_blank" href="https://github.com/marzer/tomlplusplus/issues">Report an issue</a> \
|
##! <a target="_blank" href="https://github.com/marzer/tomlplusplus/issues">Report an issue</a> \
|
||||||
##! <br><br>Documentation generated using <a href="https://mcss.mosra.cz/">m.css</a>
|
##! <br><br>Documentation generated using <a href="https://mcss.mosra.cz/">m.css</a>
|
||||||
##! M_HTML_HEADER = <script src="tomlplusplus.js"></script>
|
##! M_HTML_HEADER = <script src="tomlplusplus.js"></script>
|
||||||
|
##! M_MAIN_PROJECT_URL = https://github.com/marzer/tomlplusplus/
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#error toml++ is a C++ library.
|
#error toml++ is a C++ library.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__clang__) or defined(__GNUC__)
|
#if defined(__clang__) || defined(__GNUC__)
|
||||||
#define TOML_GCC_ATTR(attr) __attribute__((attr))
|
#define TOML_GCC_ATTR(attr) __attribute__((attr))
|
||||||
#else
|
#else
|
||||||
#define TOML_GCC_ATTR(attr)
|
#define TOML_GCC_ATTR(attr)
|
||||||
@ -426,51 +426,12 @@ namespace toml
|
|||||||
TOML_PUSH_WARNINGS
|
TOML_PUSH_WARNINGS
|
||||||
TOML_DISABLE_INIT_WARNINGS
|
TOML_DISABLE_INIT_WARNINGS
|
||||||
|
|
||||||
#if !TOML_DOXYGEN && TOML_EXCEPTIONS
|
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
|
||||||
|
|
||||||
class parse_error final
|
|
||||||
: public std::runtime_error
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
source_region source_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
|
||||||
parse_error(const char* desc, source_region&& src) noexcept
|
|
||||||
: std::runtime_error{ desc },
|
|
||||||
source_{ std::move(src) }
|
|
||||||
{}
|
|
||||||
|
|
||||||
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
|
||||||
parse_error(const char* desc, const source_region& src) noexcept
|
|
||||||
: parse_error{ desc, source_region{ src } }
|
|
||||||
{}
|
|
||||||
|
|
||||||
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
|
||||||
parse_error(const char* desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
|
||||||
: parse_error{ desc, source_region{ position, position, path } }
|
|
||||||
{}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
std::string_view description() const noexcept
|
|
||||||
{
|
|
||||||
return std::string_view{ what() };
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
const source_region& source() const noexcept
|
|
||||||
{
|
|
||||||
return source_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/// \brief An error thrown/returned when parsing fails.
|
/// \brief An error thrown/returned when parsing fails.
|
||||||
///
|
///
|
||||||
/// \remarks This class inherits from `std::runtime_error` when `TOML_EXCEPTIONS` is `1`.
|
/// \remarks This class inherits from `std::runtime_error` when exceptions are enabled.
|
||||||
/// The public interface remains the same regardless of exception mode.
|
/// The public interface is the same regardless of exception mode.
|
||||||
class parse_error final
|
class parse_error final
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -511,6 +472,45 @@ namespace toml
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
class parse_error final
|
||||||
|
: public std::runtime_error
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
source_region source_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
||||||
|
parse_error(const char* desc, source_region&& src) noexcept
|
||||||
|
: std::runtime_error{ desc },
|
||||||
|
source_{ std::move(src) }
|
||||||
|
{}
|
||||||
|
|
||||||
|
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
||||||
|
parse_error(const char* desc, const source_region& src) noexcept
|
||||||
|
: parse_error{ desc, source_region{ src } }
|
||||||
|
{}
|
||||||
|
|
||||||
|
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
||||||
|
parse_error(const char* desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
||||||
|
: parse_error{ desc, source_region{ position, position, path } }
|
||||||
|
{}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
std::string_view description() const noexcept
|
||||||
|
{
|
||||||
|
return std::string_view{ what() };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
const source_region& source() const noexcept
|
||||||
|
{
|
||||||
|
return source_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TOML_POP_WARNINGS
|
TOML_POP_WARNINGS
|
||||||
@ -577,7 +577,11 @@ namespace toml::impl
|
|||||||
|| std::is_same_v<T, uint32_t>
|
|| std::is_same_v<T, uint32_t>
|
||||||
|| std::is_same_v<T, uint16_t>
|
|| std::is_same_v<T, uint16_t>
|
||||||
|| std::is_same_v<T, uint8_t>
|
|| std::is_same_v<T, uint8_t>
|
||||||
|| std::is_same_v<T, float>;
|
|| std::is_same_v<T, float>
|
||||||
|
#ifdef TOML_SMALL_FLOAT_TYPE
|
||||||
|
|| std::is_same_v<T, TOML_SMALL_FLOAT_TYPE>
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_value_or_node =
|
inline constexpr bool is_value_or_node =
|
||||||
@ -606,6 +610,9 @@ namespace toml::impl
|
|||||||
template <> struct value_promoter<uint16_t> { using type = int64_t; };
|
template <> struct value_promoter<uint16_t> { using type = int64_t; };
|
||||||
template <> struct value_promoter<uint8_t> { using type = int64_t; };
|
template <> struct value_promoter<uint8_t> { using type = int64_t; };
|
||||||
template <> struct value_promoter<float> { using type = double; };
|
template <> struct value_promoter<float> { using type = double; };
|
||||||
|
#ifdef TOML_SMALL_FLOAT_TYPE
|
||||||
|
template <> struct value_promoter<TOML_SMALL_FLOAT_TYPE> { using type = double; };
|
||||||
|
#endif
|
||||||
template <typename T> using promoted = typename impl::value_promoter<T>::type;
|
template <typename T> using promoted = typename impl::value_promoter<T>::type;
|
||||||
|
|
||||||
inline constexpr toml::string_view low_character_escape_table[] =
|
inline constexpr toml::string_view low_character_escape_table[] =
|
||||||
@ -682,7 +689,6 @@ namespace toml::impl
|
|||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
/// \brief Helper alias that wraps a type up as it's TOML node equivalent.
|
/// \brief Helper alias that wraps a type up as it's TOML node equivalent.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using node_of = typename impl::node_wrapper<T>::type;
|
using node_of = typename impl::node_wrapper<T>::type;
|
||||||
@ -691,6 +697,33 @@ namespace toml
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
using value_of = typename impl::node_unwrapper<T>::type;
|
using value_of = typename impl::node_unwrapper<T>::type;
|
||||||
|
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::table.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_table = std::is_same_v<impl::remove_cvref_t<T>, table>;
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::array.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_array = std::is_same_v<impl::remove_cvref_t<T>, array>;
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::value<string>.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_string = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<string>>;
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::value<int64_t>.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_integer = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<int64_t>>;
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::value<double>.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_floating_point = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<double>>;
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::value<bool>.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_boolean = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<bool>>;
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::value<toml::date>.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_date = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<date>>;
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::value<toml::time>.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_time = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<time>>;
|
||||||
|
/// \brief Metafunction for determining if a type is a toml::value<toml::date_time>.
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_date_time = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<date_time>>;
|
||||||
|
|
||||||
/// \brief Pretty-prints the value of a node_type to a stream.
|
/// \brief Pretty-prints the value of a node_type to a stream.
|
||||||
template <typename CHAR>
|
template <typename CHAR>
|
||||||
|
@ -3,10 +3,14 @@
|
|||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
/// \brief A local date.
|
||||||
struct date final
|
struct date final
|
||||||
{
|
{
|
||||||
|
/// \brief The year component.
|
||||||
uint16_t year;
|
uint16_t year;
|
||||||
|
/// \brief The month component, from 1 - 12.
|
||||||
uint8_t month;
|
uint8_t month;
|
||||||
|
/// \brief The day component, from 1 - 31.
|
||||||
uint8_t day;
|
uint8_t day;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@ -34,11 +38,16 @@ namespace toml
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief A local time-of-day.
|
||||||
struct time final
|
struct time final
|
||||||
{
|
{
|
||||||
|
/// \brief The hour component, from 0 - 23.
|
||||||
uint8_t hour;
|
uint8_t hour;
|
||||||
|
/// \brief The minute component, from 0 - 59.
|
||||||
uint8_t minute;
|
uint8_t minute;
|
||||||
|
/// \brief The second component, from 0 - 59.
|
||||||
uint8_t second;
|
uint8_t second;
|
||||||
|
/// \brief The fractional nanoseconds component, from 0 - 999999999.
|
||||||
uint32_t nanosecond;
|
uint32_t nanosecond;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@ -65,8 +74,10 @@ namespace toml
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief A timezone offset.
|
||||||
struct time_offset final
|
struct time_offset final
|
||||||
{
|
{
|
||||||
|
/// \brief Offset from UTC+0, in minutes.
|
||||||
int16_t minutes;
|
int16_t minutes;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@ -96,10 +107,14 @@ namespace toml
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief A date-time.
|
||||||
struct date_time final
|
struct date_time final
|
||||||
{
|
{
|
||||||
|
/// \brief The date component.
|
||||||
toml::date date;
|
toml::date date;
|
||||||
|
/// \brief The time component.
|
||||||
toml::time time;
|
toml::time time;
|
||||||
|
/// \brief The timezone offset component.
|
||||||
std::optional<toml::time_offset> time_offset;
|
std::optional<toml::time_offset> time_offset;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
|
@ -61,8 +61,7 @@ namespace toml::impl
|
|||||||
return node.visit([](const auto& n) noexcept
|
return node.visit([](const auto& n) noexcept
|
||||||
-> size_t
|
-> size_t
|
||||||
{
|
{
|
||||||
using node_t = impl::remove_cvref_t<decltype(n)>;
|
if constexpr (is_table<decltype(n)>)
|
||||||
if constexpr (std::is_same_v<node_t, table>)
|
|
||||||
{
|
{
|
||||||
if (n.empty())
|
if (n.empty())
|
||||||
return 2_sz; // "{}"
|
return 2_sz; // "{}"
|
||||||
@ -71,7 +70,7 @@ namespace toml::impl
|
|||||||
weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", "
|
weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", "
|
||||||
return weight;
|
return weight;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, array>)
|
else if constexpr (is_array<decltype(n)>)
|
||||||
{
|
{
|
||||||
if (n.empty())
|
if (n.empty())
|
||||||
return 2_sz; // "[]"
|
return 2_sz; // "[]"
|
||||||
@ -80,11 +79,11 @@ namespace toml::impl
|
|||||||
weight += default_formatter_inline_columns(elem) + 2_sz; // + ", "
|
weight += default_formatter_inline_columns(elem) + 2_sz; // + ", "
|
||||||
return weight;
|
return weight;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<string>>)
|
else if constexpr (is_string<decltype(n)>)
|
||||||
{
|
{
|
||||||
return n.get().length() + 2_sz; // + ""
|
return n.get().length() + 2_sz; // + ""
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<int64_t>>)
|
else if constexpr (is_integer<decltype(n)>)
|
||||||
{
|
{
|
||||||
auto v = n.get();
|
auto v = n.get();
|
||||||
if (!v)
|
if (!v)
|
||||||
@ -97,7 +96,7 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
return weight + static_cast<size_t>(std::log10(static_cast<double>(v)));
|
return weight + static_cast<size_t>(std::log10(static_cast<double>(v)));
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<double>>)
|
else if constexpr (is_floating_point<decltype(n)>)
|
||||||
{
|
{
|
||||||
auto v = n.get();
|
auto v = n.get();
|
||||||
if (v == 0.0)
|
if (v == 0.0)
|
||||||
@ -110,15 +109,15 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
return weight + static_cast<size_t>(std::log10(v));
|
return weight + static_cast<size_t>(std::log10(v));
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<bool>>)
|
else if constexpr (is_boolean<decltype(n)>)
|
||||||
{
|
{
|
||||||
return 5_sz;
|
return 5_sz;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<date>> || std::is_same_v<node_t, value<time>>)
|
else if constexpr (is_date<decltype(n)> || is_time<decltype(n)>)
|
||||||
{
|
{
|
||||||
return 10_sz;
|
return 10_sz;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<date_time>>)
|
else if constexpr (is_date_time<decltype(n)>)
|
||||||
{
|
{
|
||||||
return 30_sz;
|
return 30_sz;
|
||||||
}
|
}
|
||||||
|
@ -98,12 +98,12 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static constexpr auto is_date_time =
|
static constexpr auto is_dt =
|
||||||
std::is_same_v<T, date>
|
std::is_same_v<T, date>
|
||||||
|| std::is_same_v<T, time>
|
|| std::is_same_v<T, time>
|
||||||
|| std::is_same_v<T, date_time>;
|
|| std::is_same_v<T, date_time>;
|
||||||
|
|
||||||
if constexpr (is_date_time)
|
if constexpr (is_dt)
|
||||||
{
|
{
|
||||||
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
|
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
|
||||||
print_to_stream('"', *stream_);
|
print_to_stream('"', *stream_);
|
||||||
@ -111,7 +111,7 @@ namespace toml::impl
|
|||||||
|
|
||||||
*stream_ << val;
|
*stream_ << val;
|
||||||
|
|
||||||
if constexpr (is_date_time)
|
if constexpr (is_dt)
|
||||||
{
|
{
|
||||||
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
|
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
|
||||||
print_to_stream('"', *stream_);
|
print_to_stream('"', *stream_);
|
||||||
|
@ -27,17 +27,18 @@ namespace toml
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||||
node_of<T>* reinterpret_as() noexcept
|
node_of<T>& ref_cast() & noexcept { return *reinterpret_cast<node_of<T>*>(this); }
|
||||||
{
|
|
||||||
return reinterpret_cast<node_of<T>*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||||
const node_of<T>* reinterpret_as() const noexcept
|
node_of<T>&& ref_cast() && noexcept { return std::move(*reinterpret_cast<node_of<T>*>(this)); }
|
||||||
{
|
|
||||||
return reinterpret_cast<const node_of<T>*>(this);
|
template <typename T>
|
||||||
}
|
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||||
|
const node_of<T>& ref_cast() const & noexcept { return *reinterpret_cast<const node_of<T>*>(this); }
|
||||||
|
|
||||||
|
template <typename N, typename T>
|
||||||
|
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
|
||||||
|
|
||||||
node() noexcept = default;
|
node() noexcept = default;
|
||||||
node(const node&) = delete;
|
node(const node&) = delete;
|
||||||
@ -47,11 +48,9 @@ namespace toml
|
|||||||
|
|
||||||
virtual ~node() noexcept = default;
|
virtual ~node() noexcept = default;
|
||||||
|
|
||||||
|
|
||||||
/// \brief Returns the node's type identifier.
|
/// \brief Returns the node's type identifier.
|
||||||
[[nodiscard]] virtual node_type type() const noexcept = 0;
|
[[nodiscard]] virtual node_type type() const noexcept = 0;
|
||||||
|
|
||||||
|
|
||||||
/// \brief Returns true if this node is a table.
|
/// \brief Returns true if this node is a table.
|
||||||
[[nodiscard]] virtual bool is_table() const noexcept = 0;
|
[[nodiscard]] virtual bool is_table() const noexcept = 0;
|
||||||
/// \brief Returns true if this node is an array.
|
/// \brief Returns true if this node is an array.
|
||||||
@ -76,7 +75,6 @@ namespace toml
|
|||||||
/// \brief Returns true if this node is an array containing only tables.
|
/// \brief Returns true if this node is an array containing only tables.
|
||||||
[[nodiscard]] virtual bool is_array_of_tables() const noexcept { return false; }
|
[[nodiscard]] virtual bool is_array_of_tables() const noexcept { return false; }
|
||||||
|
|
||||||
|
|
||||||
/// \brief Checks if a node is a specific type.
|
/// \brief Checks if a node is a specific type.
|
||||||
///
|
///
|
||||||
/// \tparam T The
|
/// \tparam T The
|
||||||
@ -102,15 +100,24 @@ namespace toml
|
|||||||
else if constexpr (std::is_same_v<type, time>) return is_time();
|
else if constexpr (std::is_same_v<type, time>) return is_time();
|
||||||
else if constexpr (std::is_same_v<type, date_time>) return is_date_time();
|
else if constexpr (std::is_same_v<type, date_time>) return is_date_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Returns a pointer to the node as a toml::table, if it is one.
|
||||||
[[nodiscard]] virtual table* as_table() noexcept { return nullptr; }
|
[[nodiscard]] virtual table* as_table() noexcept { return nullptr; }
|
||||||
|
/// \brief Returns a pointer to the node as a toml::array, if it is one.
|
||||||
[[nodiscard]] virtual array* as_array() noexcept { return nullptr; }
|
[[nodiscard]] virtual array* as_array() noexcept { return nullptr; }
|
||||||
|
/// \brief Returns a pointer to the node as a toml::value<string>, if it is one.
|
||||||
[[nodiscard]] virtual value<string>* as_string() noexcept { return nullptr; }
|
[[nodiscard]] virtual value<string>* as_string() noexcept { return nullptr; }
|
||||||
|
/// \brief Returns a pointer to the node as a toml::value<int64_t>, if it is one.
|
||||||
[[nodiscard]] virtual value<int64_t>* as_integer() noexcept { return nullptr; }
|
[[nodiscard]] virtual value<int64_t>* as_integer() noexcept { return nullptr; }
|
||||||
|
/// \brief Returns a pointer to the node as a toml::value<double>, if it is one.
|
||||||
[[nodiscard]] virtual value<double>* as_floating_point() noexcept { return nullptr; }
|
[[nodiscard]] virtual value<double>* as_floating_point() noexcept { return nullptr; }
|
||||||
|
/// \brief Returns a pointer to the node as a toml::value<bool>, if it is one.
|
||||||
[[nodiscard]] virtual value<bool>* as_boolean() noexcept { return nullptr; }
|
[[nodiscard]] virtual value<bool>* as_boolean() noexcept { return nullptr; }
|
||||||
|
/// \brief Returns a pointer to the node as a toml::value<date>, if it is one.
|
||||||
[[nodiscard]] virtual value<date>* as_date() noexcept { return nullptr; }
|
[[nodiscard]] virtual value<date>* as_date() noexcept { return nullptr; }
|
||||||
|
/// \brief Returns a pointer to the node as a toml::value<time>, if it is one.
|
||||||
[[nodiscard]] virtual value<time>* as_time() noexcept { return nullptr; }
|
[[nodiscard]] virtual value<time>* as_time() noexcept { return nullptr; }
|
||||||
|
/// \brief Returns a pointer to the node as a toml::value<date_time>, if it is one.
|
||||||
[[nodiscard]] virtual value<date_time>* as_date_time() noexcept { return nullptr; }
|
[[nodiscard]] virtual value<date_time>* as_date_time() noexcept { return nullptr; }
|
||||||
|
|
||||||
[[nodiscard]] virtual const table* as_table() const noexcept { return nullptr; }
|
[[nodiscard]] virtual const table* as_table() const noexcept { return nullptr; }
|
||||||
@ -123,6 +130,27 @@ namespace toml
|
|||||||
[[nodiscard]] virtual const value<time>* as_time() const noexcept { return nullptr; }
|
[[nodiscard]] virtual const value<time>* as_time() const noexcept { return nullptr; }
|
||||||
[[nodiscard]] virtual const value<date_time>* as_date_time() const noexcept { return nullptr; }
|
[[nodiscard]] virtual const value<date_time>* as_date_time() const noexcept { return nullptr; }
|
||||||
|
|
||||||
|
/// \brief Gets a pointer to the node as a more specific node type.
|
||||||
|
///
|
||||||
|
/// \details \cpp
|
||||||
|
///
|
||||||
|
/// auto int_value = node->as<int64_t>();
|
||||||
|
/// auto tbl = node->as<toml::table>();
|
||||||
|
/// if (int_value)
|
||||||
|
/// std::cout << "Node is a value<int64_t>" << std::endl;
|
||||||
|
/// else if (tbl)
|
||||||
|
/// std::cout << "Node is a table" << std::endl;
|
||||||
|
///
|
||||||
|
/// // fully-qualified value node types also work:
|
||||||
|
/// auto int_value2 = node->as<toml::value<int64_t>>();
|
||||||
|
/// if (int_value2)
|
||||||
|
/// std::cout << "Node is a value<int64_t>" << std::endl;
|
||||||
|
///
|
||||||
|
/// \ecpp
|
||||||
|
///
|
||||||
|
/// \tparam T The node type or TOML value type to cast to.
|
||||||
|
///
|
||||||
|
/// \returns A pointer to the node as the given type, or nullptr if it was a different type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||||
node_of<T>* as() noexcept
|
node_of<T>* as() noexcept
|
||||||
@ -144,6 +172,7 @@ namespace toml
|
|||||||
else if constexpr (std::is_same_v<type, date_time>) return as_date_time();
|
else if constexpr (std::is_same_v<type, date_time>) return as_date_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Gets a pointer to the node as a more specific node type (const overload).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||||
const node_of<T>* as() const noexcept
|
const node_of<T>* as() const noexcept
|
||||||
@ -165,6 +194,7 @@ namespace toml
|
|||||||
else if constexpr (std::is_same_v<type, date_time>) return as_date_time();
|
else if constexpr (std::is_same_v<type, date_time>) return as_date_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Returns the source region responsible for generating this node during parsing.
|
||||||
[[nodiscard]] const source_region& source() const noexcept
|
[[nodiscard]] const source_region& source() const noexcept
|
||||||
{
|
{
|
||||||
return source_;
|
return source_;
|
||||||
@ -172,94 +202,166 @@ namespace toml
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// this is done using a static helper to preserve const categories
|
template <typename FUNC, typename N, typename T, bool = std::is_invocable_v<FUNC, ref_cast_type<N, T>>>
|
||||||
// (otherwise I'd have to implement this function twice)
|
struct visit_return_type final
|
||||||
// (const propagation in C++: a modern horror story)
|
{
|
||||||
|
using type = decltype(std::declval<FUNC>()(std::declval<ref_cast_type<N, T>>()));
|
||||||
|
};
|
||||||
|
template <typename FUNC, typename N, typename T>
|
||||||
|
struct visit_return_type<FUNC, N, T, false> final
|
||||||
|
{
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A, typename B>
|
||||||
|
using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>;
|
||||||
|
|
||||||
|
// this is done using a static helper to preserve const and ref categories
|
||||||
|
// (otherwise I'd have to implement this function thrice)
|
||||||
|
// ((propagation in C++: a modern horror story))
|
||||||
template <typename N, typename FUNC>
|
template <typename N, typename FUNC>
|
||||||
TOML_GCC_ATTR(nonnull)
|
static decltype(auto) do_visit(N&& node, FUNC&& visitor) TOML_MAY_THROW
|
||||||
static decltype(auto) do_visit(N* node, FUNC&& visitor) TOML_MAY_THROW
|
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<table>())>
|
std::is_invocable_v<FUNC&&, ref_cast_type<N&&, table>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<array>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, array>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<string>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, string>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<int64_t>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, int64_t>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<double>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, double>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<bool>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, bool>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<time>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, time>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date_time>())>,
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date_time>>,
|
||||||
"Visitors must be invocable for at least one of the toml::node specializations"
|
"Visitors must be invocable for at least one of the toml::node specializations"
|
||||||
);
|
);
|
||||||
|
|
||||||
static constexpr auto is_exhaustive =
|
switch (node.type())
|
||||||
std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<table>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<array>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<string>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<int64_t>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<double>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<bool>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<time>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date_time>())>;
|
|
||||||
|
|
||||||
switch (node->type())
|
|
||||||
{
|
{
|
||||||
case node_type::table:
|
case node_type::table:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<table>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, table>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<table>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<table>());
|
||||||
break;
|
break;
|
||||||
case node_type::array:
|
case node_type::array:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<array>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, array>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<array>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<array>());
|
||||||
break;
|
break;
|
||||||
case node_type::string:
|
case node_type::string:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<string>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, string>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<string>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<string>());
|
||||||
break;
|
break;
|
||||||
case node_type::integer:
|
case node_type::integer:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<int64_t>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, int64_t>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<int64_t>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<int64_t>());
|
||||||
break;
|
break;
|
||||||
case node_type::floating_point:
|
case node_type::floating_point:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<double>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, double>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<double>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<double>());
|
||||||
break;
|
break;
|
||||||
case node_type::boolean:
|
case node_type::boolean:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<bool>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, bool>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<bool>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<bool>());
|
||||||
break;
|
break;
|
||||||
case node_type::date:
|
case node_type::date:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<date>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<date>());
|
||||||
break;
|
break;
|
||||||
case node_type::time:
|
case node_type::time:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<time>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, time>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<time>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<time>());
|
||||||
break;
|
break;
|
||||||
case node_type::date_time:
|
case node_type::date_time:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date_time>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date_time>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<date_time>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<date_time>());
|
||||||
break;
|
break;
|
||||||
TOML_NO_DEFAULT_CASE;
|
TOML_NO_DEFAULT_CASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr auto is_exhaustive =
|
||||||
|
std::is_invocable_v<FUNC&&, ref_cast_type<N&&, table>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, array>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, string>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, int64_t>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, double>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, bool>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, time>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date_time>>;
|
||||||
|
|
||||||
if constexpr (is_exhaustive)
|
if constexpr (is_exhaustive)
|
||||||
TOML_UNREACHABLE;
|
TOML_UNREACHABLE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using return_type =
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, table>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, array>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, string>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, int64_t>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, double>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, bool>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, date>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, time>::type,
|
||||||
|
typename visit_return_type<FUNC&&, N&&, date_time>::type
|
||||||
|
>>>>>>>>;
|
||||||
|
|
||||||
|
if constexpr (!std::is_void_v<return_type>)
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_default_constructible_v<return_type>,
|
||||||
|
"Non-exhaustive visitors must return a default-constructible type, or void"
|
||||||
|
);
|
||||||
|
return return_type{};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// \brief Invokes a visitor on the node based on the node's concrete type.
|
||||||
|
///
|
||||||
|
/// \details Visitation is useful when you expect
|
||||||
|
/// a node to be one of a set number of types and need
|
||||||
|
/// to handle these types differently. Using `visit()` allows
|
||||||
|
/// you to eliminate some of the casting/conversion boilerplate: \cpp
|
||||||
|
///
|
||||||
|
/// node.visit([](auto&& n)
|
||||||
|
/// {
|
||||||
|
/// if constexpr (toml::is_string<decltype(n)>)
|
||||||
|
/// do_something_with_a_string(n.get());
|
||||||
|
/// else if constexpr (toml::is_floating_point<decltype(n)>)
|
||||||
|
/// do_something_with_a_float(n.get());
|
||||||
|
/// else
|
||||||
|
/// throw std::exception("Expected string or integer")
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// \ecpp
|
||||||
|
///
|
||||||
|
/// \tparam FUNC A callable type invocable with one or more of the
|
||||||
|
/// toml++ node types.
|
||||||
|
///
|
||||||
|
/// \param visitor The visitor object.
|
||||||
|
///
|
||||||
|
/// \returns The return value of the visitor.
|
||||||
|
/// Must be default-constructible if non-void and your visitor is not exhaustive.
|
||||||
|
///
|
||||||
|
/// \see https://en.wikipedia.org/wiki/Visitor_pattern
|
||||||
template <typename FUNC>
|
template <typename FUNC>
|
||||||
decltype(auto) visit(FUNC&& visitor) TOML_MAY_THROW
|
decltype(auto) visit(FUNC&& visitor) & TOML_MAY_THROW
|
||||||
{
|
{
|
||||||
return do_visit(this, std::forward<FUNC>(visitor));
|
return do_visit(*this, std::forward<FUNC>(visitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Invokes a visitor on the node based on the node's concrete type (rvalue overload).
|
||||||
template <typename FUNC>
|
template <typename FUNC>
|
||||||
decltype(auto) visit(FUNC&& visitor) const TOML_MAY_THROW
|
decltype(auto) visit(FUNC&& visitor) && TOML_MAY_THROW
|
||||||
{
|
{
|
||||||
return do_visit(this, std::forward<FUNC>(visitor));
|
return do_visit(std::move(*this), std::forward<FUNC>(visitor));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Invokes a visitor on the node based on the node's concrete type (const overload).
|
||||||
|
template <typename FUNC>
|
||||||
|
decltype(auto) visit(FUNC&& visitor) const& TOML_MAY_THROW
|
||||||
|
{
|
||||||
|
return do_visit(*this, std::forward<FUNC>(visitor));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
#if TOML_EXCEPTIONS
|
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
|
||||||
|
|
||||||
using parse_result = table;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
|
/// \brief The result of a parsing operation.
|
||||||
|
///
|
||||||
|
/// \remarks This type only exists when exceptions are disabled,
|
||||||
|
/// otherwise `parse_result` is a simple alias for `toml::table`.
|
||||||
class parse_result final
|
class parse_result final
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -69,7 +69,7 @@ namespace toml
|
|||||||
|
|
||||||
[[nodiscard]] table& operator* () & noexcept { return get(); }
|
[[nodiscard]] table& operator* () & noexcept { return get(); }
|
||||||
[[nodiscard]] table&& operator* () && noexcept { return std::move(get()); }
|
[[nodiscard]] table&& operator* () && noexcept { return std::move(get()); }
|
||||||
[[nodiscard]] const table& operator* () const & noexcept { return get(); }
|
[[nodiscard]] const table& operator* () const& noexcept { return get(); }
|
||||||
|
|
||||||
[[nodiscard]] table* operator-> () noexcept { return &get(); }
|
[[nodiscard]] table* operator-> () noexcept { return &get(); }
|
||||||
[[nodiscard]] const table* operator-> () const noexcept { return &get(); }
|
[[nodiscard]] const table* operator-> () const noexcept { return &get(); }
|
||||||
@ -133,6 +133,10 @@ namespace toml
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
using parse_result = table;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1938,7 +1942,7 @@ namespace toml::impl
|
|||||||
if constexpr (!TOML_LANG_HIGHER_THAN(0, 5, 0)) // toml/issues/665
|
if constexpr (!TOML_LANG_HIGHER_THAN(0, 5, 0)) // toml/issues/665
|
||||||
{
|
{
|
||||||
// arrays must be homogeneous in toml 0.5.0 and earlier
|
// arrays must be homogeneous in toml 0.5.0 and earlier
|
||||||
if (!val->reinterpret_as<array>()->is_homogeneous())
|
if (!val->ref_cast<array>().is_homogeneous())
|
||||||
TOML_ERROR(
|
TOML_ERROR(
|
||||||
"Arrays cannot contain values of different types in TOML 0.5.0 and earlier.",
|
"Arrays cannot contain values of different types in TOML 0.5.0 and earlier.",
|
||||||
begin_pos,
|
begin_pos,
|
||||||
@ -2406,7 +2410,7 @@ namespace toml::impl
|
|||||||
const auto header_begin_pos = cp->position;
|
const auto header_begin_pos = cp->position;
|
||||||
source_position header_end_pos;
|
source_position header_end_pos;
|
||||||
key key;
|
key key;
|
||||||
bool is_array = false;
|
bool is_arr = false;
|
||||||
|
|
||||||
//parse header
|
//parse header
|
||||||
{
|
{
|
||||||
@ -2426,7 +2430,7 @@ namespace toml::impl
|
|||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
eof_check();
|
eof_check();
|
||||||
is_array = true;
|
is_arr = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip past any whitespace that followed the '['
|
// skip past any whitespace that followed the '['
|
||||||
@ -2464,12 +2468,12 @@ namespace toml::impl
|
|||||||
if (*cp != U']')
|
if (*cp != U']')
|
||||||
abort_with_error(
|
abort_with_error(
|
||||||
"Encountered unexpected character while parsing table"sv,
|
"Encountered unexpected character while parsing table"sv,
|
||||||
(is_array ? " array"sv : ""sv), " header; expected ']', saw '"sv, *cp, '\''
|
(is_arr ? " array"sv : ""sv), " header; expected ']', saw '"sv, *cp, '\''
|
||||||
);
|
);
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
// consume the second closing ']'
|
// consume the second closing ']'
|
||||||
if (is_array)
|
if (is_arr)
|
||||||
{
|
{
|
||||||
eof_check();
|
eof_check();
|
||||||
|
|
||||||
@ -2488,7 +2492,7 @@ namespace toml::impl
|
|||||||
{
|
{
|
||||||
if (!consume_comment() && !consume_line_break())
|
if (!consume_comment() && !consume_line_break())
|
||||||
abort_with_error(
|
abort_with_error(
|
||||||
"Encountered unexpected character after table"sv, (is_array ? " array"sv : ""sv),
|
"Encountered unexpected character after table"sv, (is_arr ? " array"sv : ""sv),
|
||||||
" header; expected a comment or whitespace, saw '"sv, *cp, '\''
|
" header; expected a comment or whitespace, saw '"sv, *cp, '\''
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -2507,31 +2511,31 @@ namespace toml::impl
|
|||||||
key.segments[i],
|
key.segments[i],
|
||||||
std::make_unique<table>()
|
std::make_unique<table>()
|
||||||
).first->second.get();
|
).first->second.get();
|
||||||
implicit_tables.push_back(child->reinterpret_as<table>());
|
implicit_tables.push_back(&child->ref_cast<table>());
|
||||||
child->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
child->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
parent = child->reinterpret_as<table>();
|
parent = &child->ref_cast<table>();
|
||||||
}
|
}
|
||||||
else if (child->is_table())
|
else if (child->is_table())
|
||||||
{
|
{
|
||||||
parent = child->reinterpret_as<table>();
|
parent = &child->ref_cast<table>();
|
||||||
}
|
}
|
||||||
else if (child->is_array() && find(table_arrays, child->reinterpret_as<array>()))
|
else if (child->is_array() && find(table_arrays, &child->ref_cast<array>()))
|
||||||
{
|
{
|
||||||
// table arrays are a special case;
|
// table arrays are a special case;
|
||||||
// the spec dictates we select the most recently declared element in the array.
|
// the spec dictates we select the most recently declared element in the array.
|
||||||
TOML_ASSERT(!child->reinterpret_as<array>()->values.empty());
|
TOML_ASSERT(!child->ref_cast<array>().values.empty());
|
||||||
TOML_ASSERT(child->reinterpret_as<array>()->values.back()->is_table());
|
TOML_ASSERT(child->ref_cast<array>().values.back()->is_table());
|
||||||
parent = child->reinterpret_as<array>()->values.back()->reinterpret_as<table>();
|
parent = &child->ref_cast<array>().values.back()->ref_cast<table>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!is_array && child->type() == node_type::table)
|
if (!is_arr && child->type() == node_type::table)
|
||||||
abort_with_error("Attempt to redefine existing table '"sv, recording_buffer, '\'');
|
abort_with_error("Attempt to redefine existing table '"sv, recording_buffer, '\'');
|
||||||
else
|
else
|
||||||
abort_with_error(
|
abort_with_error(
|
||||||
"Attempt to redefine existing "sv, child->type(),
|
"Attempt to redefine existing "sv, child->type(),
|
||||||
" '"sv, recording_buffer,
|
" '"sv, recording_buffer,
|
||||||
"' as "sv, is_array ? "array-of-tables"sv : "table"sv
|
"' as "sv, is_arr ? "array-of-tables"sv : "table"sv
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2545,23 +2549,23 @@ namespace toml::impl
|
|||||||
{
|
{
|
||||||
// if it's an array we need to make the array and it's first table element,
|
// if it's an array we need to make the array and it's first table element,
|
||||||
// set the starting regions, and return the table element
|
// set the starting regions, and return the table element
|
||||||
if (is_array)
|
if (is_arr)
|
||||||
{
|
{
|
||||||
auto tab_arr = parent->values.emplace(key.segments.back(),std::make_unique<array>())
|
auto tab_arr = &parent->values.emplace(key.segments.back(),std::make_unique<array>())
|
||||||
.first->second->reinterpret_as<array>();
|
.first->second->ref_cast<array>();
|
||||||
table_arrays.push_back(tab_arr);
|
table_arrays.push_back(tab_arr);
|
||||||
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
|
|
||||||
tab_arr->values.push_back(std::make_unique<table>());
|
tab_arr->values.push_back(std::make_unique<table>());
|
||||||
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
return tab_arr->values.back()->reinterpret_as<table>();
|
return &tab_arr->values.back()->ref_cast<table>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise we're just making a table
|
//otherwise we're just making a table
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tab = parent->values.emplace(key.segments.back(),std::make_unique<table>())
|
auto tab = &parent->values.emplace(key.segments.back(),std::make_unique<table>())
|
||||||
.first->second->reinterpret_as<table>();
|
.first->second->ref_cast<table>();
|
||||||
tab->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
tab->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
@ -2573,19 +2577,19 @@ namespace toml::impl
|
|||||||
// otherwise this is a redefinition error.
|
// otherwise this is a redefinition error.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_array && matching_node->is_array() && find(table_arrays, matching_node->reinterpret_as<array>()))
|
if (is_arr && matching_node->is_array() && find(table_arrays, &matching_node->ref_cast<array>()))
|
||||||
{
|
{
|
||||||
auto tab_arr = matching_node->reinterpret_as<array>();
|
auto tab_arr = &matching_node->ref_cast<array>();
|
||||||
tab_arr->values.push_back(std::make_unique<table>());
|
tab_arr->values.push_back(std::make_unique<table>());
|
||||||
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
return tab_arr->values.back()->reinterpret_as<table>();
|
return &tab_arr->values.back()->ref_cast<table>();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!is_array
|
else if (!is_arr
|
||||||
&& matching_node->is_table()
|
&& matching_node->is_table()
|
||||||
&& !implicit_tables.empty())
|
&& !implicit_tables.empty())
|
||||||
{
|
{
|
||||||
auto tbl = matching_node->reinterpret_as<table>();
|
auto tbl = &matching_node->ref_cast<table>();
|
||||||
const auto idx = find(implicit_tables, tbl);
|
const auto idx = find(implicit_tables, tbl);
|
||||||
if (idx)
|
if (idx)
|
||||||
{
|
{
|
||||||
@ -2597,13 +2601,13 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if we get here it's a redefinition error.
|
//if we get here it's a redefinition error.
|
||||||
if (!is_array && matching_node->type() == node_type::table)
|
if (!is_arr && matching_node->type() == node_type::table)
|
||||||
abort_with_error("Attempt to redefine existing table '"sv, recording_buffer, '\'');
|
abort_with_error("Attempt to redefine existing table '"sv, recording_buffer, '\'');
|
||||||
else
|
else
|
||||||
abort_with_error(
|
abort_with_error(
|
||||||
"Attempt to redefine existing "sv, matching_node->type(),
|
"Attempt to redefine existing "sv, matching_node->type(),
|
||||||
" '"sv, recording_buffer,
|
" '"sv, recording_buffer,
|
||||||
"' as "sv, is_array ? "array-of-tables"sv : "table"sv
|
"' as "sv, is_arr ? "array-of-tables"sv : "table"sv
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TOML_ERROR_CHECK({});
|
TOML_ERROR_CHECK({});
|
||||||
@ -2629,18 +2633,18 @@ namespace toml::impl
|
|||||||
std::move(kvp.key.segments[i]),
|
std::move(kvp.key.segments[i]),
|
||||||
std::make_unique<table>()
|
std::make_unique<table>()
|
||||||
).first->second.get();
|
).first->second.get();
|
||||||
dotted_key_tables.push_back(child->reinterpret_as<table>());
|
dotted_key_tables.push_back(&child->ref_cast<table>());
|
||||||
dotted_key_tables.back()->inline_ = true;
|
dotted_key_tables.back()->inline_ = true;
|
||||||
child->source_ = kvp.value->source_;
|
child->source_ = kvp.value->source_;
|
||||||
}
|
}
|
||||||
else if (!child->is_table() || !find(dotted_key_tables, child->reinterpret_as<table>()))
|
else if (!child->is_table() || !find(dotted_key_tables, &child->ref_cast<table>()))
|
||||||
{
|
{
|
||||||
abort_with_error("Attempt to redefine "sv, child->type(), " as dotted key-value pair"sv);
|
abort_with_error("Attempt to redefine "sv, child->type(), " as dotted key-value pair"sv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
child->source_.end = kvp.value->source_.end;
|
child->source_.end = kvp.value->source_.end;
|
||||||
TOML_ERROR_CHECK();
|
TOML_ERROR_CHECK();
|
||||||
tab = child->reinterpret_as<table>();
|
tab = &child->ref_cast<table>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2739,7 +2743,7 @@ namespace toml::impl
|
|||||||
|
|
||||||
if (type == node_type::table)
|
if (type == node_type::table)
|
||||||
{
|
{
|
||||||
auto& tbl = *nde.reinterpret_as<table>();
|
auto& tbl = nde.ref_cast<table>();
|
||||||
if (tbl.inline_) //inline tables (and all their inline descendants) are already correctly terminated
|
if (tbl.inline_) //inline tables (and all their inline descendants) are already correctly terminated
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2753,7 +2757,7 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
else //arrays
|
else //arrays
|
||||||
{
|
{
|
||||||
auto& arr = *nde.reinterpret_as<array>();
|
auto& arr = nde.ref_cast<array>();
|
||||||
auto end = nde.source_.end;
|
auto end = nde.source_.end;
|
||||||
for (auto& v : arr.values)
|
for (auto& v : arr.values)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +160,7 @@ namespace toml::impl
|
|||||||
|
|
||||||
template <typename CHAR>
|
template <typename CHAR>
|
||||||
TOML_ALWAYS_INLINE
|
TOML_ALWAYS_INLINE
|
||||||
void print_to_stream(bool& val, std::basic_ostream<CHAR>& stream) TOML_MAY_THROW
|
void print_to_stream(bool val, std::basic_ostream<CHAR>& stream) TOML_MAY_THROW
|
||||||
{
|
{
|
||||||
static_assert(sizeof(CHAR) == 1);
|
static_assert(sizeof(CHAR) == 1);
|
||||||
print_to_stream(val ? "true"sv : "false"sv, stream);
|
print_to_stream(val ? "true"sv : "false"sv, stream);
|
||||||
|
@ -132,4 +132,7 @@ namespace toml
|
|||||||
value(uint8_t) -> value<int64_t>;
|
value(uint8_t) -> value<int64_t>;
|
||||||
value(uint16_t) -> value<int64_t>;
|
value(uint16_t) -> value<int64_t>;
|
||||||
value(uint32_t) -> value<int64_t>;
|
value(uint32_t) -> value<int64_t>;
|
||||||
|
#ifdef TOML_SMALL_FLOAT_TYPE
|
||||||
|
value(TOML_SMALL_FLOAT_TYPE) -> value<double>;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -708,8 +708,8 @@ def main():
|
|||||||
# post-process html files
|
# post-process html files
|
||||||
fixes = [
|
fixes = [
|
||||||
CustomTagsFix()
|
CustomTagsFix()
|
||||||
, NavBarFix()
|
# , NavBarFix()
|
||||||
, IndexHrefFix()
|
# , IndexHrefFix()
|
||||||
, ModifiersFix1()
|
, ModifiersFix1()
|
||||||
, ModifiersFix2()
|
, ModifiersFix2()
|
||||||
, InlineNamespaceFix1()
|
, InlineNamespaceFix1()
|
||||||
|
374
toml.hpp
374
toml.hpp
@ -22,7 +22,7 @@
|
|||||||
//
|
//
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Copyright (c) 2019 Mark Gillard
|
// Copyright (c) 2019-2020 Mark Gillard
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
||||||
@ -81,7 +81,7 @@
|
|||||||
#error toml++ is a C++ library.
|
#error toml++ is a C++ library.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__clang__) or defined(__GNUC__)
|
#if defined(__clang__) || defined(__GNUC__)
|
||||||
#define TOML_GCC_ATTR(attr) __attribute__((attr))
|
#define TOML_GCC_ATTR(attr) __attribute__((attr))
|
||||||
#else
|
#else
|
||||||
#define TOML_GCC_ATTR(attr)
|
#define TOML_GCC_ATTR(attr)
|
||||||
@ -441,46 +441,7 @@ namespace toml
|
|||||||
TOML_PUSH_WARNINGS
|
TOML_PUSH_WARNINGS
|
||||||
TOML_DISABLE_INIT_WARNINGS
|
TOML_DISABLE_INIT_WARNINGS
|
||||||
|
|
||||||
#if !TOML_DOXYGEN && TOML_EXCEPTIONS
|
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
|
||||||
|
|
||||||
class parse_error final
|
|
||||||
: public std::runtime_error
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
source_region source_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
|
||||||
parse_error(const char* desc, source_region&& src) noexcept
|
|
||||||
: std::runtime_error{ desc },
|
|
||||||
source_{ std::move(src) }
|
|
||||||
{}
|
|
||||||
|
|
||||||
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
|
||||||
parse_error(const char* desc, const source_region& src) noexcept
|
|
||||||
: parse_error{ desc, source_region{ src } }
|
|
||||||
{}
|
|
||||||
|
|
||||||
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
|
||||||
parse_error(const char* desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
|
||||||
: parse_error{ desc, source_region{ position, position, path } }
|
|
||||||
{}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
std::string_view description() const noexcept
|
|
||||||
{
|
|
||||||
return std::string_view{ what() };
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
const source_region& source() const noexcept
|
|
||||||
{
|
|
||||||
return source_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class parse_error final
|
class parse_error final
|
||||||
{
|
{
|
||||||
@ -519,6 +480,45 @@ namespace toml
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
class parse_error final
|
||||||
|
: public std::runtime_error
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
source_region source_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
||||||
|
parse_error(const char* desc, source_region&& src) noexcept
|
||||||
|
: std::runtime_error{ desc },
|
||||||
|
source_{ std::move(src) }
|
||||||
|
{}
|
||||||
|
|
||||||
|
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
||||||
|
parse_error(const char* desc, const source_region& src) noexcept
|
||||||
|
: parse_error{ desc, source_region{ src } }
|
||||||
|
{}
|
||||||
|
|
||||||
|
TOML_NODISCARD_CTOR TOML_GCC_ATTR(nonnull)
|
||||||
|
parse_error(const char* desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
||||||
|
: parse_error{ desc, source_region{ position, position, path } }
|
||||||
|
{}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
std::string_view description() const noexcept
|
||||||
|
{
|
||||||
|
return std::string_view{ what() };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
const source_region& source() const noexcept
|
||||||
|
{
|
||||||
|
return source_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TOML_POP_WARNINGS
|
TOML_POP_WARNINGS
|
||||||
@ -584,7 +584,11 @@ namespace toml::impl
|
|||||||
|| std::is_same_v<T, uint32_t>
|
|| std::is_same_v<T, uint32_t>
|
||||||
|| std::is_same_v<T, uint16_t>
|
|| std::is_same_v<T, uint16_t>
|
||||||
|| std::is_same_v<T, uint8_t>
|
|| std::is_same_v<T, uint8_t>
|
||||||
|| std::is_same_v<T, float>;
|
|| std::is_same_v<T, float>
|
||||||
|
#ifdef TOML_SMALL_FLOAT_TYPE
|
||||||
|
|| std::is_same_v<T, TOML_SMALL_FLOAT_TYPE>
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_value_or_node =
|
inline constexpr bool is_value_or_node =
|
||||||
@ -613,6 +617,9 @@ namespace toml::impl
|
|||||||
template <> struct value_promoter<uint16_t> { using type = int64_t; };
|
template <> struct value_promoter<uint16_t> { using type = int64_t; };
|
||||||
template <> struct value_promoter<uint8_t> { using type = int64_t; };
|
template <> struct value_promoter<uint8_t> { using type = int64_t; };
|
||||||
template <> struct value_promoter<float> { using type = double; };
|
template <> struct value_promoter<float> { using type = double; };
|
||||||
|
#ifdef TOML_SMALL_FLOAT_TYPE
|
||||||
|
template <> struct value_promoter<TOML_SMALL_FLOAT_TYPE> { using type = double; };
|
||||||
|
#endif
|
||||||
template <typename T> using promoted = typename impl::value_promoter<T>::type;
|
template <typename T> using promoted = typename impl::value_promoter<T>::type;
|
||||||
|
|
||||||
inline constexpr toml::string_view low_character_escape_table[] =
|
inline constexpr toml::string_view low_character_escape_table[] =
|
||||||
@ -688,13 +695,31 @@ namespace toml::impl
|
|||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using node_of = typename impl::node_wrapper<T>::type;
|
using node_of = typename impl::node_wrapper<T>::type;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using value_of = typename impl::node_unwrapper<T>::type;
|
using value_of = typename impl::node_unwrapper<T>::type;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_table = std::is_same_v<impl::remove_cvref_t<T>, table>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_array = std::is_same_v<impl::remove_cvref_t<T>, array>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_string = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<string>>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_integer = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<int64_t>>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_floating_point = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<double>>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_boolean = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<bool>>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_date = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<date>>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_time = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<time>>;
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_date_time = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<date_time>>;
|
||||||
|
|
||||||
template <typename CHAR>
|
template <typename CHAR>
|
||||||
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, node_type rhs) TOML_MAY_THROW
|
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, node_type rhs) TOML_MAY_THROW
|
||||||
{
|
{
|
||||||
@ -1015,7 +1040,7 @@ namespace toml::impl
|
|||||||
|
|
||||||
template <typename CHAR>
|
template <typename CHAR>
|
||||||
TOML_ALWAYS_INLINE
|
TOML_ALWAYS_INLINE
|
||||||
void print_to_stream(bool& val, std::basic_ostream<CHAR>& stream) TOML_MAY_THROW
|
void print_to_stream(bool val, std::basic_ostream<CHAR>& stream) TOML_MAY_THROW
|
||||||
{
|
{
|
||||||
static_assert(sizeof(CHAR) == 1);
|
static_assert(sizeof(CHAR) == 1);
|
||||||
print_to_stream(val ? "true"sv : "false"sv, stream);
|
print_to_stream(val ? "true"sv : "false"sv, stream);
|
||||||
@ -1159,17 +1184,18 @@ namespace toml
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||||
node_of<T>* reinterpret_as() noexcept
|
node_of<T>& ref_cast() & noexcept { return *reinterpret_cast<node_of<T>*>(this); }
|
||||||
{
|
|
||||||
return reinterpret_cast<node_of<T>*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||||
const node_of<T>* reinterpret_as() const noexcept
|
node_of<T>&& ref_cast() && noexcept { return std::move(*reinterpret_cast<node_of<T>*>(this)); }
|
||||||
{
|
|
||||||
return reinterpret_cast<const node_of<T>*>(this);
|
template <typename T>
|
||||||
}
|
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||||
|
const node_of<T>& ref_cast() const & noexcept { return *reinterpret_cast<const node_of<T>*>(this); }
|
||||||
|
|
||||||
|
template <typename N, typename T>
|
||||||
|
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
|
||||||
|
|
||||||
node() noexcept = default;
|
node() noexcept = default;
|
||||||
node(const node&) = delete;
|
node(const node&) = delete;
|
||||||
@ -1281,94 +1307,136 @@ namespace toml
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// this is done using a static helper to preserve const categories
|
template <typename FUNC, typename N, typename T, bool = std::is_invocable_v<FUNC, ref_cast_type<N, T>>>
|
||||||
// (otherwise I'd have to implement this function twice)
|
struct visit_return_type final
|
||||||
// (const propagation in C++: a modern horror story)
|
{
|
||||||
|
using type = decltype(std::declval<FUNC>()(std::declval<ref_cast_type<N, T>>()));
|
||||||
|
};
|
||||||
|
template <typename FUNC, typename N, typename T>
|
||||||
|
struct visit_return_type<FUNC, N, T, false> final
|
||||||
|
{
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A, typename B>
|
||||||
|
using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>;
|
||||||
|
|
||||||
|
// this is done using a static helper to preserve const and ref categories
|
||||||
|
// (otherwise I'd have to implement this function thrice)
|
||||||
|
// ((propagation in C++: a modern horror story))
|
||||||
template <typename N, typename FUNC>
|
template <typename N, typename FUNC>
|
||||||
TOML_GCC_ATTR(nonnull)
|
static decltype(auto) do_visit(N&& node, FUNC&& visitor) TOML_MAY_THROW
|
||||||
static decltype(auto) do_visit(N* node, FUNC&& visitor) TOML_MAY_THROW
|
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<table>())>
|
std::is_invocable_v<FUNC&&, ref_cast_type<N&&, table>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<array>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, array>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<string>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, string>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<int64_t>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, int64_t>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<double>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, double>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<bool>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, bool>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<time>())>
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, time>>
|
||||||
|| std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date_time>())>,
|
|| std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date_time>>,
|
||||||
"Visitors must be invocable for at least one of the toml::node specializations"
|
"Visitors must be invocable for at least one of the toml::node specializations"
|
||||||
);
|
);
|
||||||
|
|
||||||
static constexpr auto is_exhaustive =
|
switch (node.type())
|
||||||
std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<table>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<array>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<string>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<int64_t>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<double>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<bool>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<time>())>
|
|
||||||
&& std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date_time>())>;
|
|
||||||
|
|
||||||
switch (node->type())
|
|
||||||
{
|
{
|
||||||
case node_type::table:
|
case node_type::table:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<table>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, table>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<table>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<table>());
|
||||||
break;
|
break;
|
||||||
case node_type::array:
|
case node_type::array:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<array>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, array>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<array>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<array>());
|
||||||
break;
|
break;
|
||||||
case node_type::string:
|
case node_type::string:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<string>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, string>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<string>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<string>());
|
||||||
break;
|
break;
|
||||||
case node_type::integer:
|
case node_type::integer:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<int64_t>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, int64_t>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<int64_t>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<int64_t>());
|
||||||
break;
|
break;
|
||||||
case node_type::floating_point:
|
case node_type::floating_point:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<double>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, double>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<double>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<double>());
|
||||||
break;
|
break;
|
||||||
case node_type::boolean:
|
case node_type::boolean:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<bool>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, bool>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<bool>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<bool>());
|
||||||
break;
|
break;
|
||||||
case node_type::date:
|
case node_type::date:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<date>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<date>());
|
||||||
break;
|
break;
|
||||||
case node_type::time:
|
case node_type::time:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<time>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, time>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<time>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<time>());
|
||||||
break;
|
break;
|
||||||
case node_type::date_time:
|
case node_type::date_time:
|
||||||
if constexpr (std::is_invocable_v<FUNC&&, decltype(*node->template reinterpret_as<date_time>())>)
|
if constexpr (std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date_time>>)
|
||||||
return std::forward<FUNC>(visitor)(*node->template reinterpret_as<date_time>());
|
return std::forward<FUNC>(visitor)(std::forward<N>(node).template ref_cast<date_time>());
|
||||||
break;
|
break;
|
||||||
TOML_NO_DEFAULT_CASE;
|
TOML_NO_DEFAULT_CASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr auto is_exhaustive =
|
||||||
|
std::is_invocable_v<FUNC&&, ref_cast_type<N&&, table>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, array>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, string>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, int64_t>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, double>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, bool>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, time>>
|
||||||
|
&& std::is_invocable_v<FUNC&&, ref_cast_type<N&&, date_time>>;
|
||||||
|
|
||||||
if constexpr (is_exhaustive)
|
if constexpr (is_exhaustive)
|
||||||
TOML_UNREACHABLE;
|
TOML_UNREACHABLE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using return_type =
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, table>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, array>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, string>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, int64_t>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, double>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, bool>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, date>::type,
|
||||||
|
nonvoid<typename visit_return_type<FUNC&&, N&&, time>::type,
|
||||||
|
typename visit_return_type<FUNC&&, N&&, date_time>::type
|
||||||
|
>>>>>>>>;
|
||||||
|
|
||||||
|
if constexpr (!std::is_void_v<return_type>)
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_default_constructible_v<return_type>,
|
||||||
|
"Non-exhaustive visitors must return a default-constructible type, or void"
|
||||||
|
);
|
||||||
|
return return_type{};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
template <typename FUNC>
|
template <typename FUNC>
|
||||||
decltype(auto) visit(FUNC&& visitor) TOML_MAY_THROW
|
decltype(auto) visit(FUNC&& visitor) & TOML_MAY_THROW
|
||||||
{
|
{
|
||||||
return do_visit(this, std::forward<FUNC>(visitor));
|
return do_visit(*this, std::forward<FUNC>(visitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FUNC>
|
template <typename FUNC>
|
||||||
decltype(auto) visit(FUNC&& visitor) const TOML_MAY_THROW
|
decltype(auto) visit(FUNC&& visitor) && TOML_MAY_THROW
|
||||||
{
|
{
|
||||||
return do_visit(this, std::forward<FUNC>(visitor));
|
return do_visit(std::move(*this), std::forward<FUNC>(visitor));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FUNC>
|
||||||
|
decltype(auto) visit(FUNC&& visitor) const& TOML_MAY_THROW
|
||||||
|
{
|
||||||
|
return do_visit(*this, std::forward<FUNC>(visitor));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1934,6 +2002,9 @@ namespace toml
|
|||||||
value(uint8_t) -> value<int64_t>;
|
value(uint8_t) -> value<int64_t>;
|
||||||
value(uint16_t) -> value<int64_t>;
|
value(uint16_t) -> value<int64_t>;
|
||||||
value(uint32_t) -> value<int64_t>;
|
value(uint32_t) -> value<int64_t>;
|
||||||
|
#ifdef TOML_SMALL_FLOAT_TYPE
|
||||||
|
value(TOML_SMALL_FLOAT_TYPE) -> value<double>;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
@ -3816,11 +3887,7 @@ namespace toml::impl
|
|||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
#if TOML_EXCEPTIONS
|
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
|
||||||
|
|
||||||
using parse_result = table;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class parse_result final
|
class parse_result final
|
||||||
{
|
{
|
||||||
@ -3878,7 +3945,7 @@ namespace toml
|
|||||||
|
|
||||||
[[nodiscard]] table& operator* () & noexcept { return get(); }
|
[[nodiscard]] table& operator* () & noexcept { return get(); }
|
||||||
[[nodiscard]] table&& operator* () && noexcept { return std::move(get()); }
|
[[nodiscard]] table&& operator* () && noexcept { return std::move(get()); }
|
||||||
[[nodiscard]] const table& operator* () const & noexcept { return get(); }
|
[[nodiscard]] const table& operator* () const& noexcept { return get(); }
|
||||||
[[nodiscard]] table* operator-> () noexcept { return &get(); }
|
[[nodiscard]] table* operator-> () noexcept { return &get(); }
|
||||||
[[nodiscard]] const table* operator-> () const noexcept { return &get(); }
|
[[nodiscard]] const table* operator-> () const noexcept { return &get(); }
|
||||||
[[nodiscard]] operator table& () noexcept { return get(); }
|
[[nodiscard]] operator table& () noexcept { return get(); }
|
||||||
@ -3939,6 +4006,10 @@ namespace toml
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
using parse_result = table;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5742,7 +5813,7 @@ namespace toml::impl
|
|||||||
if constexpr (!TOML_LANG_HIGHER_THAN(0, 5, 0)) // toml/issues/665
|
if constexpr (!TOML_LANG_HIGHER_THAN(0, 5, 0)) // toml/issues/665
|
||||||
{
|
{
|
||||||
// arrays must be homogeneous in toml 0.5.0 and earlier
|
// arrays must be homogeneous in toml 0.5.0 and earlier
|
||||||
if (!val->reinterpret_as<array>()->is_homogeneous())
|
if (!val->ref_cast<array>().is_homogeneous())
|
||||||
TOML_ERROR(
|
TOML_ERROR(
|
||||||
"Arrays cannot contain values of different types in TOML 0.5.0 and earlier.",
|
"Arrays cannot contain values of different types in TOML 0.5.0 and earlier.",
|
||||||
begin_pos,
|
begin_pos,
|
||||||
@ -6210,7 +6281,7 @@ namespace toml::impl
|
|||||||
const auto header_begin_pos = cp->position;
|
const auto header_begin_pos = cp->position;
|
||||||
source_position header_end_pos;
|
source_position header_end_pos;
|
||||||
key key;
|
key key;
|
||||||
bool is_array = false;
|
bool is_arr = false;
|
||||||
|
|
||||||
//parse header
|
//parse header
|
||||||
{
|
{
|
||||||
@ -6230,7 +6301,7 @@ namespace toml::impl
|
|||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
eof_check();
|
eof_check();
|
||||||
is_array = true;
|
is_arr = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip past any whitespace that followed the '['
|
// skip past any whitespace that followed the '['
|
||||||
@ -6268,12 +6339,12 @@ namespace toml::impl
|
|||||||
if (*cp != U']')
|
if (*cp != U']')
|
||||||
abort_with_error(
|
abort_with_error(
|
||||||
"Encountered unexpected character while parsing table"sv,
|
"Encountered unexpected character while parsing table"sv,
|
||||||
(is_array ? " array"sv : ""sv), " header; expected ']', saw '"sv, *cp, '\''
|
(is_arr ? " array"sv : ""sv), " header; expected ']', saw '"sv, *cp, '\''
|
||||||
);
|
);
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
// consume the second closing ']'
|
// consume the second closing ']'
|
||||||
if (is_array)
|
if (is_arr)
|
||||||
{
|
{
|
||||||
eof_check();
|
eof_check();
|
||||||
|
|
||||||
@ -6292,7 +6363,7 @@ namespace toml::impl
|
|||||||
{
|
{
|
||||||
if (!consume_comment() && !consume_line_break())
|
if (!consume_comment() && !consume_line_break())
|
||||||
abort_with_error(
|
abort_with_error(
|
||||||
"Encountered unexpected character after table"sv, (is_array ? " array"sv : ""sv),
|
"Encountered unexpected character after table"sv, (is_arr ? " array"sv : ""sv),
|
||||||
" header; expected a comment or whitespace, saw '"sv, *cp, '\''
|
" header; expected a comment or whitespace, saw '"sv, *cp, '\''
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -6311,31 +6382,31 @@ namespace toml::impl
|
|||||||
key.segments[i],
|
key.segments[i],
|
||||||
std::make_unique<table>()
|
std::make_unique<table>()
|
||||||
).first->second.get();
|
).first->second.get();
|
||||||
implicit_tables.push_back(child->reinterpret_as<table>());
|
implicit_tables.push_back(&child->ref_cast<table>());
|
||||||
child->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
child->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
parent = child->reinterpret_as<table>();
|
parent = &child->ref_cast<table>();
|
||||||
}
|
}
|
||||||
else if (child->is_table())
|
else if (child->is_table())
|
||||||
{
|
{
|
||||||
parent = child->reinterpret_as<table>();
|
parent = &child->ref_cast<table>();
|
||||||
}
|
}
|
||||||
else if (child->is_array() && find(table_arrays, child->reinterpret_as<array>()))
|
else if (child->is_array() && find(table_arrays, &child->ref_cast<array>()))
|
||||||
{
|
{
|
||||||
// table arrays are a special case;
|
// table arrays are a special case;
|
||||||
// the spec dictates we select the most recently declared element in the array.
|
// the spec dictates we select the most recently declared element in the array.
|
||||||
TOML_ASSERT(!child->reinterpret_as<array>()->values.empty());
|
TOML_ASSERT(!child->ref_cast<array>().values.empty());
|
||||||
TOML_ASSERT(child->reinterpret_as<array>()->values.back()->is_table());
|
TOML_ASSERT(child->ref_cast<array>().values.back()->is_table());
|
||||||
parent = child->reinterpret_as<array>()->values.back()->reinterpret_as<table>();
|
parent = &child->ref_cast<array>().values.back()->ref_cast<table>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!is_array && child->type() == node_type::table)
|
if (!is_arr && child->type() == node_type::table)
|
||||||
abort_with_error("Attempt to redefine existing table '"sv, recording_buffer, '\'');
|
abort_with_error("Attempt to redefine existing table '"sv, recording_buffer, '\'');
|
||||||
else
|
else
|
||||||
abort_with_error(
|
abort_with_error(
|
||||||
"Attempt to redefine existing "sv, child->type(),
|
"Attempt to redefine existing "sv, child->type(),
|
||||||
" '"sv, recording_buffer,
|
" '"sv, recording_buffer,
|
||||||
"' as "sv, is_array ? "array-of-tables"sv : "table"sv
|
"' as "sv, is_arr ? "array-of-tables"sv : "table"sv
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6349,23 +6420,23 @@ namespace toml::impl
|
|||||||
{
|
{
|
||||||
// if it's an array we need to make the array and it's first table element,
|
// if it's an array we need to make the array and it's first table element,
|
||||||
// set the starting regions, and return the table element
|
// set the starting regions, and return the table element
|
||||||
if (is_array)
|
if (is_arr)
|
||||||
{
|
{
|
||||||
auto tab_arr = parent->values.emplace(key.segments.back(),std::make_unique<array>())
|
auto tab_arr = &parent->values.emplace(key.segments.back(),std::make_unique<array>())
|
||||||
.first->second->reinterpret_as<array>();
|
.first->second->ref_cast<array>();
|
||||||
table_arrays.push_back(tab_arr);
|
table_arrays.push_back(tab_arr);
|
||||||
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
|
|
||||||
tab_arr->values.push_back(std::make_unique<table>());
|
tab_arr->values.push_back(std::make_unique<table>());
|
||||||
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
return tab_arr->values.back()->reinterpret_as<table>();
|
return &tab_arr->values.back()->ref_cast<table>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise we're just making a table
|
//otherwise we're just making a table
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto tab = parent->values.emplace(key.segments.back(),std::make_unique<table>())
|
auto tab = &parent->values.emplace(key.segments.back(),std::make_unique<table>())
|
||||||
.first->second->reinterpret_as<table>();
|
.first->second->ref_cast<table>();
|
||||||
tab->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
tab->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
@ -6377,19 +6448,19 @@ namespace toml::impl
|
|||||||
// otherwise this is a redefinition error.
|
// otherwise this is a redefinition error.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_array && matching_node->is_array() && find(table_arrays, matching_node->reinterpret_as<array>()))
|
if (is_arr && matching_node->is_array() && find(table_arrays, &matching_node->ref_cast<array>()))
|
||||||
{
|
{
|
||||||
auto tab_arr = matching_node->reinterpret_as<array>();
|
auto tab_arr = &matching_node->ref_cast<array>();
|
||||||
tab_arr->values.push_back(std::make_unique<table>());
|
tab_arr->values.push_back(std::make_unique<table>());
|
||||||
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||||
return tab_arr->values.back()->reinterpret_as<table>();
|
return &tab_arr->values.back()->ref_cast<table>();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!is_array
|
else if (!is_arr
|
||||||
&& matching_node->is_table()
|
&& matching_node->is_table()
|
||||||
&& !implicit_tables.empty())
|
&& !implicit_tables.empty())
|
||||||
{
|
{
|
||||||
auto tbl = matching_node->reinterpret_as<table>();
|
auto tbl = &matching_node->ref_cast<table>();
|
||||||
const auto idx = find(implicit_tables, tbl);
|
const auto idx = find(implicit_tables, tbl);
|
||||||
if (idx)
|
if (idx)
|
||||||
{
|
{
|
||||||
@ -6401,13 +6472,13 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if we get here it's a redefinition error.
|
//if we get here it's a redefinition error.
|
||||||
if (!is_array && matching_node->type() == node_type::table)
|
if (!is_arr && matching_node->type() == node_type::table)
|
||||||
abort_with_error("Attempt to redefine existing table '"sv, recording_buffer, '\'');
|
abort_with_error("Attempt to redefine existing table '"sv, recording_buffer, '\'');
|
||||||
else
|
else
|
||||||
abort_with_error(
|
abort_with_error(
|
||||||
"Attempt to redefine existing "sv, matching_node->type(),
|
"Attempt to redefine existing "sv, matching_node->type(),
|
||||||
" '"sv, recording_buffer,
|
" '"sv, recording_buffer,
|
||||||
"' as "sv, is_array ? "array-of-tables"sv : "table"sv
|
"' as "sv, is_arr ? "array-of-tables"sv : "table"sv
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TOML_ERROR_CHECK({});
|
TOML_ERROR_CHECK({});
|
||||||
@ -6433,18 +6504,18 @@ namespace toml::impl
|
|||||||
std::move(kvp.key.segments[i]),
|
std::move(kvp.key.segments[i]),
|
||||||
std::make_unique<table>()
|
std::make_unique<table>()
|
||||||
).first->second.get();
|
).first->second.get();
|
||||||
dotted_key_tables.push_back(child->reinterpret_as<table>());
|
dotted_key_tables.push_back(&child->ref_cast<table>());
|
||||||
dotted_key_tables.back()->inline_ = true;
|
dotted_key_tables.back()->inline_ = true;
|
||||||
child->source_ = kvp.value->source_;
|
child->source_ = kvp.value->source_;
|
||||||
}
|
}
|
||||||
else if (!child->is_table() || !find(dotted_key_tables, child->reinterpret_as<table>()))
|
else if (!child->is_table() || !find(dotted_key_tables, &child->ref_cast<table>()))
|
||||||
{
|
{
|
||||||
abort_with_error("Attempt to redefine "sv, child->type(), " as dotted key-value pair"sv);
|
abort_with_error("Attempt to redefine "sv, child->type(), " as dotted key-value pair"sv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
child->source_.end = kvp.value->source_.end;
|
child->source_.end = kvp.value->source_.end;
|
||||||
TOML_ERROR_CHECK();
|
TOML_ERROR_CHECK();
|
||||||
tab = child->reinterpret_as<table>();
|
tab = &child->ref_cast<table>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6543,7 +6614,7 @@ namespace toml::impl
|
|||||||
|
|
||||||
if (type == node_type::table)
|
if (type == node_type::table)
|
||||||
{
|
{
|
||||||
auto& tbl = *nde.reinterpret_as<table>();
|
auto& tbl = nde.ref_cast<table>();
|
||||||
if (tbl.inline_) //inline tables (and all their inline descendants) are already correctly terminated
|
if (tbl.inline_) //inline tables (and all their inline descendants) are already correctly terminated
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -6557,7 +6628,7 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
else //arrays
|
else //arrays
|
||||||
{
|
{
|
||||||
auto& arr = *nde.reinterpret_as<array>();
|
auto& arr = nde.ref_cast<array>();
|
||||||
auto end = nde.source_.end;
|
auto end = nde.source_.end;
|
||||||
for (auto& v : arr.values)
|
for (auto& v : arr.values)
|
||||||
{
|
{
|
||||||
@ -6978,12 +7049,12 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static constexpr auto is_date_time =
|
static constexpr auto is_dt =
|
||||||
std::is_same_v<T, date>
|
std::is_same_v<T, date>
|
||||||
|| std::is_same_v<T, time>
|
|| std::is_same_v<T, time>
|
||||||
|| std::is_same_v<T, date_time>;
|
|| std::is_same_v<T, date_time>;
|
||||||
|
|
||||||
if constexpr (is_date_time)
|
if constexpr (is_dt)
|
||||||
{
|
{
|
||||||
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
|
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
|
||||||
print_to_stream('"', *stream_);
|
print_to_stream('"', *stream_);
|
||||||
@ -6991,7 +7062,7 @@ namespace toml::impl
|
|||||||
|
|
||||||
*stream_ << val;
|
*stream_ << val;
|
||||||
|
|
||||||
if constexpr (is_date_time)
|
if constexpr (is_dt)
|
||||||
{
|
{
|
||||||
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
|
if ((flags_ & format_flags::quote_dates_and_times) != format_flags::none)
|
||||||
print_to_stream('"', *stream_);
|
print_to_stream('"', *stream_);
|
||||||
@ -7086,8 +7157,7 @@ namespace toml::impl
|
|||||||
return node.visit([](const auto& n) noexcept
|
return node.visit([](const auto& n) noexcept
|
||||||
-> size_t
|
-> size_t
|
||||||
{
|
{
|
||||||
using node_t = impl::remove_cvref_t<decltype(n)>;
|
if constexpr (is_table<decltype(n)>)
|
||||||
if constexpr (std::is_same_v<node_t, table>)
|
|
||||||
{
|
{
|
||||||
if (n.empty())
|
if (n.empty())
|
||||||
return 2_sz; // "{}"
|
return 2_sz; // "{}"
|
||||||
@ -7096,7 +7166,7 @@ namespace toml::impl
|
|||||||
weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", "
|
weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", "
|
||||||
return weight;
|
return weight;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, array>)
|
else if constexpr (is_array<decltype(n)>)
|
||||||
{
|
{
|
||||||
if (n.empty())
|
if (n.empty())
|
||||||
return 2_sz; // "[]"
|
return 2_sz; // "[]"
|
||||||
@ -7105,11 +7175,11 @@ namespace toml::impl
|
|||||||
weight += default_formatter_inline_columns(elem) + 2_sz; // + ", "
|
weight += default_formatter_inline_columns(elem) + 2_sz; // + ", "
|
||||||
return weight;
|
return weight;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<string>>)
|
else if constexpr (is_string<decltype(n)>)
|
||||||
{
|
{
|
||||||
return n.get().length() + 2_sz; // + ""
|
return n.get().length() + 2_sz; // + ""
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<int64_t>>)
|
else if constexpr (is_integer<decltype(n)>)
|
||||||
{
|
{
|
||||||
auto v = n.get();
|
auto v = n.get();
|
||||||
if (!v)
|
if (!v)
|
||||||
@ -7122,7 +7192,7 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
return weight + static_cast<size_t>(std::log10(static_cast<double>(v)));
|
return weight + static_cast<size_t>(std::log10(static_cast<double>(v)));
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<double>>)
|
else if constexpr (is_floating_point<decltype(n)>)
|
||||||
{
|
{
|
||||||
auto v = n.get();
|
auto v = n.get();
|
||||||
if (v == 0.0)
|
if (v == 0.0)
|
||||||
@ -7135,15 +7205,15 @@ namespace toml::impl
|
|||||||
}
|
}
|
||||||
return weight + static_cast<size_t>(std::log10(v));
|
return weight + static_cast<size_t>(std::log10(v));
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<bool>>)
|
else if constexpr (is_boolean<decltype(n)>)
|
||||||
{
|
{
|
||||||
return 5_sz;
|
return 5_sz;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<date>> || std::is_same_v<node_t, value<time>>)
|
else if constexpr (is_date<decltype(n)> || is_time<decltype(n)>)
|
||||||
{
|
{
|
||||||
return 10_sz;
|
return 10_sz;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<node_t, value<date_time>>)
|
else if constexpr (is_date_time<decltype(n)>)
|
||||||
{
|
{
|
||||||
return 30_sz;
|
return 30_sz;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user