mirror of
https://github.com/marzer/tomlplusplus.git
synced 2024-09-15 15:13:21 +00:00
Merge branch 'v3'
This commit is contained in:
commit
5c5abfd8e9
@ -4,7 +4,7 @@ jobs:
|
||||
|
||||
debug_clang:
|
||||
docker:
|
||||
- image: marzer/cpp_dev:0.1.0
|
||||
- image: marzer/cpp_dev:0.2.0
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
@ -23,12 +23,13 @@ jobs:
|
||||
- run:
|
||||
name: Building and testing with clang
|
||||
command: |
|
||||
CXX_LD=lld CXX=clang++ meson build --buildtype=debug -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false -Db_lto=false
|
||||
update-alternatives --install /usr/bin/ld.lld ld.lld /usr/bin/ld.lld-13 130
|
||||
CXX_LD=lld CXX=clang++ meson build --buildtype=debug -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false -Db_lto=false -Dasan_examples=true
|
||||
cd build && meson compile -j 4 && meson test --num-processes 1 --verbose
|
||||
|
||||
release_clang:
|
||||
docker:
|
||||
- image: marzer/cpp_dev:0.1.0
|
||||
- image: marzer/cpp_dev:0.2.0
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
@ -39,12 +40,13 @@ jobs:
|
||||
- run:
|
||||
name: Building and testing with clang
|
||||
command: |
|
||||
CXX_LD=lld CXX=clang++ meson build --buildtype=release -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false -Db_lto=false
|
||||
update-alternatives --install /usr/bin/ld.lld ld.lld /usr/bin/ld.lld-13 130
|
||||
CXX_LD=lld CXX=clang++ meson build --buildtype=release -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false -Db_lto=false -Dasan_examples=true
|
||||
cd build && meson compile -j 4 && meson test --num-processes 1 --verbose
|
||||
|
||||
debug_gcc:
|
||||
docker:
|
||||
- image: marzer/cpp_dev:0.1.0
|
||||
- image: marzer/cpp_dev:0.2.0
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
@ -55,12 +57,13 @@ jobs:
|
||||
- run:
|
||||
name: Building and testing with gcc
|
||||
command: |
|
||||
update-alternatives --install /usr/bin/ld.lld ld.lld /usr/bin/ld.lld-13 130
|
||||
CXX_LD=lld CXX=g++ meson build --buildtype=debug -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false -Db_lto=false
|
||||
cd build && meson compile -j 4 && meson test --num-processes 1 --verbose
|
||||
|
||||
release_gcc:
|
||||
docker:
|
||||
- image: marzer/cpp_dev:0.1.0
|
||||
- image: marzer/cpp_dev:0.2.0
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
@ -71,12 +74,13 @@ jobs:
|
||||
- run:
|
||||
name: Building and testing with gcc
|
||||
command: |
|
||||
update-alternatives --install /usr/bin/ld.lld ld.lld /usr/bin/ld.lld-13 130
|
||||
CXX_LD=lld CXX=g++ meson build --buildtype=release -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false -Db_lto=false
|
||||
cd build && meson compile -j 4 && meson test --num-processes 1 --verbose
|
||||
|
||||
generate_dox:
|
||||
docker:
|
||||
- image: marzer/cpp_dev:0.1.0
|
||||
- image: marzer/cpp_dev:0.2.0
|
||||
resource_class: small
|
||||
steps:
|
||||
- checkout
|
||||
|
@ -25,8 +25,15 @@ AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- TOML_ABSTRACT_BASE
|
||||
- TOML_CLOSED_ENUM
|
||||
- TOML_CLOSED_FLAGS_ENUM
|
||||
- TOML_EMPTY_BASES
|
||||
- TOML_FLAGS_ENUM
|
||||
- TOML_LIKELY_CASE
|
||||
- TOML_OPEN_ENUM
|
||||
- TOML_OPEN_FLAGS_ENUM
|
||||
- TOML_TRIVIAL_ABI
|
||||
- TOML_UNLIKELY_CASE
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
@ -96,7 +103,7 @@ IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: true
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: BeforeHash
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: Indent
|
||||
IndentRequires: false
|
||||
IndentWidth: 4
|
||||
@ -124,6 +131,7 @@ PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Left
|
||||
ReferenceAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortJavaStaticImport: Before
|
||||
@ -155,13 +163,17 @@ StatementMacros:
|
||||
- TOML_ALWAYS_INLINE
|
||||
- TOML_API
|
||||
- TOML_ATTR
|
||||
- TOML_CONSTEVAL
|
||||
- TOML_CONST_GETTER
|
||||
- TOML_CONST_INLINE_GETTER
|
||||
- TOML_EXTERN
|
||||
- TOML_EXTERNAL_LINKAGE
|
||||
- TOML_INTERNAL_LINKAGE
|
||||
- TOML_MEMBER_ATTR
|
||||
- TOML_NEVER_INLINE
|
||||
- TOML_NODISCARD
|
||||
- TOML_NODISCARD_CTOR
|
||||
- TOML_PURE_GETTER
|
||||
- TOML_PURE_INLINE_GETTER
|
||||
- TOML_RETURNS_BY_THROWING
|
||||
TabWidth: 4
|
||||
TypenameMacros:
|
||||
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1,5 +1,6 @@
|
||||
* text=auto encoding=UTF-8
|
||||
|
||||
*.bat text eol=lf encoding=UTF-8
|
||||
*.c text eol=lf encoding=UTF-8
|
||||
*.cpp text eol=lf encoding=UTF-8
|
||||
*.css text eol=lf encoding=UTF-8
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -13,3 +13,6 @@
|
||||
[submodule "external/tloptional"]
|
||||
path = external/tloptional
|
||||
url = https://github.com/TartanLlama/optional.git
|
||||
[submodule "external/json"]
|
||||
path = external/json
|
||||
url = https://github.com/nlohmann/json.git
|
||||
|
517
CHANGELOG.md
Normal file
517
CHANGELOG.md
Normal file
@ -0,0 +1,517 @@
|
||||
# Changelog
|
||||
|
||||
<!--
|
||||
template:
|
||||
|
||||
## [vX.X.X](https://github.com/marzer/tomlplusplus/releases/tag/vX.X.X) - YYYY-MM-DD
|
||||
|
||||
#### Fixes:
|
||||
#### Additions:
|
||||
#### Changes:
|
||||
#### Removals:
|
||||
#### Build system:
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
## [v3.0.0](https://github.com/marzer/tomlplusplus/releases/tag/v3.0.0) - 2022-01-11
|
||||
|
||||
|
||||
This release will be a major version bump, so it's ABI breaks all around.
|
||||
Any changes that are likely to cause migration issues (API changes, build system breakage, etc.) are indicated with ⚠️.
|
||||
|
||||
#### Fixes:
|
||||
- ⚠️ fixed `toml::table` init-list constructor requiring double-brackets
|
||||
- ⚠️ fixed `TOML_API` + extern templates causing linker errors in some circumstances
|
||||
- ⚠️ fixed incorrect `noexcept` specifications on many functions
|
||||
- ⚠️ fixed missing `TOML_API` on some interfaces
|
||||
- fixed `toml::json_formatter` not formatting inf and nan incorrectly
|
||||
- fixed a number of spec conformance issues (#127, #128, #129, #130, #131, #132, #135) (@moorereason)
|
||||
- fixed an illegal table redefinition edge case (#112) (@python36)
|
||||
- fixed documentation issues
|
||||
- fixed GCC bug causing memory leak during parse failures (#123, #124) (@rsmmr, @ronalabraham)
|
||||
- fixed incorrect handling of vertical whitespace in keys when printing TOML to streams
|
||||
- fixed incorrect source position in redefinition error messages
|
||||
- fixed missing includes `<initializer_list>`, `<utility>`
|
||||
- fixed parser not correctly round-tripping the format of binary and octal integers in some cases
|
||||
- fixed some incorrect unicode scalar sequence transformations (#125)
|
||||
- fixed strong exception guarantee edge-cases in `toml::table` and `toml::array`
|
||||
|
||||
#### Additions:
|
||||
- added value flags to array + table insert methods (#44) (@levicki)
|
||||
- added support for Unicode 14.0
|
||||
- added support for ref categories and cv-qualifiers in `toml::node::ref()`
|
||||
- added magic `toml::value_flags` constant `toml::preserve_source_value_flags`
|
||||
- added clang's enum annotation attributes to all enums
|
||||
- added `TOML_ENABLE_FORMATTERS` option
|
||||
- added `toml::yaml_formatter`
|
||||
- added `toml::value` copy+move constructor overloads with flags override
|
||||
- added `toml::table::prune()`
|
||||
- added `toml::table::lower_bound()` (same semantics as `std::map::lower_bound()`)
|
||||
- added `toml::table::emplace_hint()` (same semantics as `std::map::emplace_hint()`)
|
||||
- added `toml::table::at()` (same semantics as `std::map::at()`)
|
||||
- added `toml::node_view::operator==`
|
||||
- added `toml::key` - provides a facility to access the source_regions of parsed keys (#82) (@vaartis)
|
||||
- added `toml::is_key<>` and toml::is_key_or_convertible<>` metafunctions
|
||||
- added `toml::format_flags::relaxed_float_precision` (#89) (@vaartis)
|
||||
- added `toml::format_flags::quote_infinities_and_nans`
|
||||
- added `toml::format_flags::indent_sub_tables` (#120) (@W4RH4WK)
|
||||
- added `toml::format_flags::indent_array_elements` (#120) (@W4RH4WK)
|
||||
- added `toml::format_flags::allow_unicode_strings`
|
||||
- added `toml::format_flags::allow_real_tabs_in_strings`
|
||||
- added `toml::format_flags::allow_octal_integers`
|
||||
- added `toml::format_flags::allow_hexadecimal_integers`
|
||||
- added `toml::format_flags::allow_binary_integers`
|
||||
- added `toml::date_time` converting constructors from `toml::date` and `toml::time`
|
||||
- added `toml::at_path()`, `toml::node::at_path()` and `toml::node_view::at_path()` for qualified path-based lookups (#118) (@ben-crowhurst)
|
||||
- added `toml::array::resize()` param `default_init_flags`
|
||||
- added `toml::array::replace()` (#109) (@LebJe)
|
||||
- added `toml::array::prune()`
|
||||
- added `toml::array::at()` (same semantics as `std::vector::at()`)
|
||||
- added `parse_benchmark` example
|
||||
- added `operator->` to `toml::value` for class types
|
||||
|
||||
#### Changes:
|
||||
- ⚠️ `toml::format_flags` is now backed by `uint64_t` (was previously `uint8_t`)
|
||||
- ⚠️ `toml::source_index` is now an alias for `uint32_t` unconditionally (was previously dependent on `TOML_LARGE_FILES`)
|
||||
- ⚠️ `toml::table` now uses `toml::key` as the key type (was previously `std::string`)
|
||||
- ⚠️ `toml::value_flags` is now backed by `uint16_t` (was previously `uint8_t`)
|
||||
- ⚠️ made all overloaded operators 'hidden friends' where possible
|
||||
- ⚠️ renamed `toml::default_formatter` to `toml::toml_formatter` (`toml::default_formatter` is now an alias)
|
||||
- ⚠️ renamed `TOML_PARSER` option to `TOML_ENABLE_PARSER` (`TOML_PARSER` will continue to work but is deprecated)
|
||||
- ⚠️ renamed `TOML_UNRELEASED_FEATURES` to `TOML_ENABLE_UNRELEASED_FEATURES` (`TOML_UNRELEASED_FEATURES` will continue to work but is deprecated)
|
||||
- ⚠️ renamed `TOML_WINDOWS_COMPAT` to `TOML_ENABLE_WINDOWS_COMPAT` (`TOML_WINDOWS_COMPAT` will continue to work but is deprecated)
|
||||
- applied clang-format to all the things 🎉️
|
||||
- exposed `TOML_NAMESPACE_START` and `TOML_NAMESPACE_END` macros to help with ADL specialization scenarios
|
||||
- improved performance of parser
|
||||
- made date/time constructors accept any integral types
|
||||
- moved all implementation headers to `/impl`
|
||||
- renamed all implementation headers to `.h` and 'source' headers to `.inl`
|
||||
- updated conformance tests
|
||||
|
||||
#### Removals:
|
||||
- ⚠️ removed `toml::format_flags::allow_value_format_flags`
|
||||
- ⚠️ removed `TOML_LARGE_FILES` (it is now default - explicitly setting `TOML_LARGE_FILES` to `0` will invoke an `#error`)
|
||||
- ⚠️ removed unnecessary template machinery (esp. where ostreams were involved)
|
||||
- removed unnecessary uses of `final`
|
||||
|
||||
#### Build system:
|
||||
- ⚠️ increased minimum required meson version to `0.54.0`
|
||||
- disabled 'install' path when being used as a meson subproject (#114) (@Tachi107)
|
||||
- fixed builds failing with meson 0.6.0 (#117) (@Tachi107)
|
||||
- general meson improvements and fixes (#115) (@Tachi107)
|
||||
- used `override_dependency` where supported (#116) (@Tachi107)
|
||||
|
||||
|
||||
|
||||
## [v2.5.0](https://github.com/marzer/tomlplusplus/releases/tag/v2.5.0) - 2021-07-11
|
||||
|
||||
#### Fixes:
|
||||
- fixed linkage error with windows compat mode
|
||||
- fixed `TOML_CONSTEVAL` broken in MSVC (again)
|
||||
- fixed minor documentation bugs
|
||||
- fixed cmake project version being incorrect (#110) (@GiulioRomualdi)
|
||||
|
||||
#### Additions:
|
||||
- added support for lowercase 't' and 'z' in datetimes (per spec)
|
||||
- added natvis file to cmake install (#106) (@Ryan-rsm-McKenzie)
|
||||
- added VS cpp.hint file to cmake install
|
||||
- added metafunctions `is_container`, `is_chronological`, `is_value`, `is_node`, `inserted_type_of`
|
||||
|
||||
#### Changes:
|
||||
- improved debug code size by removing unnecessary std::forwards and std::moves
|
||||
- modernized the CMake build files (#102, #103, #105) (@friendlyanon)
|
||||
- updated conformance tests
|
||||
|
||||
|
||||
|
||||
## [v2.4.0](https://github.com/marzer/tomlplusplus/releases/tag/v2.4.0) - 2021-05-19
|
||||
|
||||
#### Fixes:
|
||||
- fixed `node::value()` not retrieving inf and nan correctly
|
||||
- fixed dotted kvps being unable to add subtables (#61) (@Validark)
|
||||
- fixed linker error on linux ICC (#83) (@blackwer)
|
||||
- fixed segfault JSON-formatting a failed `parse_result` (#96) (@proydakov)
|
||||
- fixed spurious newline after JSON formatting a table
|
||||
- fixed VS intellisense not detecting `TOML_COMPILER_EXCEPTIONS` correctly
|
||||
- fixed crash with pathologically-nested inputs (#100) (@geeknik)
|
||||
- fixed `parse_result` natvis
|
||||
- fixed false-positive `char8_t` support detection on older compilers
|
||||
- fixed unnecessary `#include <Windows.h>` Windows builds (@BeastLe9enD)
|
||||
- fixed `TOML_CONSTEVAL` breaking on VS 16.10.0pre2
|
||||
- fixed spurious warnings with MSVC /Wall
|
||||
- fixed missing blank lines between consecutive empty tables/A-o-T
|
||||
- fixed unnecessary `TOML_API` declarations
|
||||
- fixed many small documentation issues
|
||||
|
||||
#### Additions:
|
||||
- added proper cmake support (#85) (@ClausKlein)
|
||||
- added cmake FetchContent information to documentation (#101) (@proydakov)
|
||||
|
||||
#### Removals:
|
||||
- removed explicit `#include <fstream>` requirement for `parse_file()`
|
||||
|
||||
|
||||
|
||||
## [v2.3.0](https://github.com/marzer/tomlplusplus/releases/tag/v2.3.0) - 2020-12-29
|
||||
|
||||
#### Fixes:
|
||||
- fixed compiler errors caused by `<charconv>` with Apple-flavoured clang
|
||||
- fixed array and table iterators missing `iterator_category` (#77) (@HazardyKnusperkeks)
|
||||
- fixed `Wuseless-cast` warnings on GCC 10 (#75) (@HazardyKnusperkeks)
|
||||
- fixed formatter not correctly line wrapping in some rare circumstances (#73) (@89z)
|
||||
- fixed an unnecessary global compiler flag breaking builds when used as a meson subproject (#72) (@jamabr)
|
||||
- fixed link error caused by `<charconv>` on emscripten (#71) (@suy)
|
||||
- fixed ambiguity with the `toml::literals` inline namespace (#69) (@std-any-emplace)
|
||||
- fixed formatter emitting superfluous newlines after printing tables (#68) (@std-any-emplace)
|
||||
- fixed array and table iterators not converting between const and non-const versions of themselves (#67) (@std-any-emplace)
|
||||
- fixed some parser crashes when given pathologically-malformed UTF-8 (#65) (@sneves)
|
||||
|
||||
|
||||
|
||||
## [v2.2.0](https://github.com/marzer/tomlplusplus/releases/tag/v2.2.0) - 2020-08-09
|
||||
|
||||
#### Fixes:
|
||||
- fixed some issues building with VS2017 (#55) (@sobczyk)
|
||||
- fixed `_Float16` erroneously detected as supported on g++ (#57) (@sobczyk)
|
||||
- fixed `<Windows.h>` causing compilation failure on mingw (#63) (@rezahousseini)
|
||||
- fixed CMake and pkg-config files not being installed into architecture-agnostic directories (#59) (@tambry)
|
||||
- fixed memory leak during parsing (#64) (@sneves)
|
||||
- fixed ambiguous `operator==` error on MSVC (#56) (@HellsingDarge)
|
||||
|
||||
#### Additions:
|
||||
- added additional node_view constructors
|
||||
- added ability to specify serialization format of integer values
|
||||
- added integer value serialization format round trip (e.g. hex in, hex out)
|
||||
|
||||
#### Changes:
|
||||
- updated conformance tests
|
||||
- TOML version bump to v1.0.0-rc.3
|
||||
- refactors and cleanups based on feedback given [here](https://medium.com/@julienjorge/code-review-of-toml-f816a6071120)
|
||||
|
||||
#### Build system:
|
||||
- renamed build options to `snake_case`
|
||||
- tests, examples and cmake config now explicitly disabled when used as a subproject
|
||||
- removed small_binaries (it's now implicit when building as release)
|
||||
- bumped minimum meson version to 0.53
|
||||
|
||||
|
||||
|
||||
## [v2.1.0](https://github.com/marzer/tomlplusplus/releases/tag/v2.1.0) - 2020-07-11
|
||||
|
||||
#### Fixes:
|
||||
- fixed inconsistent emission of leading/trailing newlines when writing a table to an ostream (#48) (@levicki)
|
||||
- fixed `Wcast-align` warning spam on ARM
|
||||
- fixed `array::insert` not working correctly in some cases
|
||||
- fixed `node::value_or()` not having the same semantics as `node::value()` (#50) (@whiterabbit963)
|
||||
- fixed 'misleading assignment' of rvalue node_views (#52) (@Reedbeta)
|
||||
- fixed some issues handling infinities and NaNs (#51) (@Reedbeta)
|
||||
- fixed some minor documentation issues
|
||||
|
||||
#### Additions:
|
||||
- added support for `__fp16`, `_Float16`, `__float128`, `__int128_t` and `__uint128_t`
|
||||
- added copy construction/assignment for arrays, tables and values
|
||||
- added insert, emplace, push_back etc. compatibility with node_views
|
||||
- added `node::is_homogenous`
|
||||
- added `table::is_homogenous`
|
||||
- added `value::is_homogenous` (just for generic code's sake)
|
||||
- added `is_homogenous` overload for identifying failure-causing element
|
||||
- added implicit conversion operator from `node` to `node_view` (#52) (@Reedbeta)
|
||||
|
||||
#### Changes:
|
||||
- renamed `TOML_ALL_INLINE` to `TOML_HEADER_ONLY` (the old name will still work, but is no longer documented)
|
||||
- general cleanup
|
||||
|
||||
|
||||
|
||||
## [v2.0.0](https://github.com/marzer/tomlplusplus/releases/tag/v2.0.0) - 2020-07-20
|
||||
|
||||
This release contains a fairly significant number of 'quality of life' improvements, yay! But also necessitates an ABI
|
||||
break (hence the version number bump). Changes that might block a migration are annotated with ⚠️.
|
||||
|
||||
#### Fixes:
|
||||
- fixed infinity and NaN-related code breaking when using `-ffast-math` and friends
|
||||
- fixed narrowing conversion warnings when constructing int values from unsigned
|
||||
- fixed Visual Studio debugger native visualizations for `date`, `time`, `time_offset`, `date_time`
|
||||
- fixed some static assert messages being badly formatted on clang
|
||||
- fixed internal macro `assert_or_assume` leaking out of `toml_parser.hpp`
|
||||
|
||||
#### Additions:
|
||||
- added additional types allowed in `node::value()` and `node::value_or()` ([see `value()` dox for examples](https://marzer.github.io/tomlplusplus/classtoml_1_1node.html#ab144c1ae90338b6b03f6af0574c87993))
|
||||
- added additional types allowed in `node_view::value()` and `node_view::value_or()`
|
||||
- added `node::value_exact()` and `node_view::value_exact()`
|
||||
- added support for interop with wide strings on Windows:
|
||||
- added wide-string path arg overloads of `parse()` and `parse_file()`
|
||||
- added wide-string support to all relevant `table` and `array` ops
|
||||
- added wide-string support to `node::value(), node::value_or()`
|
||||
- added wide-string support to `node_view::value(), node_view::value_or()`
|
||||
- added wide-string support to `value<string>` constructor
|
||||
- added wide-string overloads of `node_view::operator[]`
|
||||
- added `source_region::wide_path()`
|
||||
- added `TOML_WINDOWS_COMPAT` switch for explicitly enabling/disabling this stuff
|
||||
- added emission of 'literal' strings to the TOML serializer
|
||||
- added lots of minor documentation fixes and improvements
|
||||
- added Visual Studio debugger native visualizations for `table`, `array`, `parse_result`, and `parse_error` (#46) (@Reedbeta)
|
||||
- added non-template version of `array::is_homogeneous()`
|
||||
- added explicit instantiations of more template types when `!TOML_ALL_INLINE`
|
||||
|
||||
#### Changes:
|
||||
- ⚠️ deprecated `parse_result::get()` in favour of `parse_result::table()`
|
||||
- ⚠️ deprecated `node_view::get()` in favour of `node_view::node()`
|
||||
- ⚠️ simplified internal ABI namespaces
|
||||
- improved the quality of many static_assert error messages
|
||||
|
||||
#### Removals:
|
||||
- ⚠️ renamed `date_time::time_offset` to just 'offset'
|
||||
- ⚠️ removed `TOML_CHAR_8_STRINGS` since it no longer makes sense
|
||||
|
||||
|
||||
|
||||
## [v1.3.3](https://github.com/marzer/tomlplusplus/releases/tag/v1.3.3) - 2020-06-29
|
||||
|
||||
#### Fixes:
|
||||
- fixed some minor TOML spec conformance bugs
|
||||
- fixed BOM check causing EOF on very short iostream inputs
|
||||
- fixed `std::numeric_limits::max()` getting broken by macros in some environments
|
||||
- fixed 'unknown pragma' warning spam in older versions of GCC
|
||||
- fixed a few minor documentation issues
|
||||
|
||||
#### Additions:
|
||||
- added rvalue overload of `array::flatten`
|
||||
- added conformance tests from `BurntSushi/toml-test` and `iarna/toml-spec-tests`
|
||||
- added `toml::inserter` as a workaround for nested construction of single-element `toml::arrays` performing move-construction instead
|
||||
- added license boilerplate to test files
|
||||
|
||||
#### Changes:
|
||||
- refactored the parser to reduce binary size
|
||||
|
||||
|
||||
|
||||
## [v1.3.2](https://github.com/marzer/tomlplusplus/releases/tag/v1.3.2) - 2020-06-19
|
||||
|
||||
#### Fixes:
|
||||
- fixed single-digit negative integers parsing as positive
|
||||
- fixed parse failure when parsing an empty file
|
||||
- fixed multi-line strings being allowed in keys
|
||||
- fixed overflow for very long binary integer literals
|
||||
|
||||
#### Changes:
|
||||
- improved the performance of toml::parse_file
|
||||
- improved the performance of printing to streams for deepy-nested TOML data
|
||||
|
||||
|
||||
|
||||
## [v1.3.0](https://github.com/marzer/tomlplusplus/releases/tag/v1.3.0) - 2020-06-02
|
||||
|
||||
#### Fixes:
|
||||
- fixed `formatter::print_inline()` causing compilation failures in DLL builds
|
||||
- fixed BOMs occasionally causing overflow/crash in char8 mode
|
||||
- fixed some spurious warnings in GCC 10
|
||||
- fixed clang static analyzer warning in BOM handling code
|
||||
|
||||
#### Additions:
|
||||
- added `table_iterator::operator ->`
|
||||
- added `array::resize()` and `array::truncate()`
|
||||
- added `array::capacity()`, `array::shrink_to_fit()`, `array::max_size()`
|
||||
- added non-const -> const conversion for table and array iterators
|
||||
|
||||
#### Changes:
|
||||
- renamed table iterator proxy pair members to `first` and `second` to match STL
|
||||
|
||||
|
||||
|
||||
## [v1.2.5](https://github.com/marzer/tomlplusplus/releases/tag/v1.2.5) - 2020-04-24
|
||||
|
||||
#### Fixes:
|
||||
- fixed some multi-line string parsing issues
|
||||
- fixed pedantic warnings on gcc 10 and clang 11
|
||||
- fixed `is_unicode_XXXXXX` functions being wrong in some cases
|
||||
- fixed `TOML_LIKELY` not being correct on older versions of gcc and clang
|
||||
- fixed minor documentation issues (#26, #38) (@prince-chrismc)
|
||||
|
||||
#### Additions:
|
||||
- added additional error message cases to the parser
|
||||
- added `error_printer` example
|
||||
- added `toml_generator` example
|
||||
|
||||
#### Changes:
|
||||
- improved unicode-related codegen
|
||||
|
||||
|
||||
|
||||
## [v1.2.3](https://github.com/marzer/tomlplusplus/releases/tag/v1.2.3) - 2020-04-11
|
||||
|
||||
#### Fixes:
|
||||
- fixed printing of inf and nan
|
||||
- fixed parser not handling floats with leading '.' characters
|
||||
- fixed pedantic vtable warnings on clang with -Weverything
|
||||
- fixed a number of documentation bugs
|
||||
- fixed `TOML_UNRELEASED_FEATURES` default being 1 (it should have been 0)
|
||||
|
||||
#### Additions:
|
||||
- added `TOML_PARSER` configuration option
|
||||
- added `TOML_LIB_SINGLE_HEADER` indicator
|
||||
- added doxygen page for the configuration options
|
||||
- added SPDX-License-Identifiers around the place
|
||||
|
||||
#### Changes:
|
||||
- split some header files up to make future maintenance easier
|
||||
- refactored and greatly simplified parser
|
||||
|
||||
|
||||
|
||||
## [v1.2.0](https://github.com/marzer/tomlplusplus/releases/tag/v1.2.0) - 2020-04-07
|
||||
|
||||
#### Fixes:
|
||||
- fixed some parsing and printing ops being locale-dependent
|
||||
- fixed some parsing errors at EOF when `TOML_EXCEPTIONS = 0`
|
||||
- fixed some unreferenced variable warnings on older compilers
|
||||
- fixed some 'maybe-uninitialized' false-positives on GCC9
|
||||
- fixed pkgconfig subdir being wrong
|
||||
|
||||
#### Additions:
|
||||
- added support for implementations without `<charconv>`
|
||||
- added cmake package config generator (#22) (@GiulioRomualdi)
|
||||
- added build config feature option `GENERATE_CMAKE_CONFIG`
|
||||
- added many new tests
|
||||
|
||||
|
||||
|
||||
## [v1.1.0](https://github.com/marzer/tomlplusplus/releases/tag/v1.1.0) - 2020-04-03
|
||||
|
||||
#### Fixes:
|
||||
- fixed some parser error paths not returning early enough `TOML_EXCEPTIONS=0`
|
||||
- fixed a number of minor documentation issues
|
||||
|
||||
#### Additions:
|
||||
- added support for [TOML 1.0.0-rc.1](https://github.com/toml-lang/toml/releases/tag/v1.0.0-rc.1) 🎉
|
||||
- added `operator[]`, `begin()`, `end()` to `toml::parse_result` for `TOML_EXCEPTIONS=0`
|
||||
- added additional compilation speed improvements for `TOML_ALL_INLINE=0`
|
||||
- added more specific error messages for parsing errors relating to prohibited codepoints
|
||||
- added a large number of additional tests
|
||||
- added support for installation with meson (#16) (@ximion)
|
||||
- added the array and table iterators to the `toml` namespace
|
||||
|
||||
|
||||
|
||||
## [v1.0.0](https://github.com/marzer/tomlplusplus/releases/tag/1.0.0) - 2020-03-28
|
||||
|
||||
#### Fixes:
|
||||
- fixed minor documentation issues
|
||||
|
||||
#### Changes:
|
||||
- refactoring of ABI-based inline namespaces
|
||||
|
||||
|
||||
|
||||
## [v0.6.0](https://github.com/marzer/tomlplusplus/releases/tag/v0.6.0) - 2020-03-24
|
||||
|
||||
#### Fixes:
|
||||
- fixed minor preprocessor/macro issues
|
||||
- fixed minor documentation issues
|
||||
|
||||
#### Additions:
|
||||
- added `<cassert>` include directly in 'debug' builds when `TOML_ASSERT` isn't defined
|
||||
- added Clang's `[[trivial_abi]]` attribute to `date`, `time`, `time_offset`
|
||||
|
||||
|
||||
|
||||
## [v0.5.0](https://github.com/marzer/tomlplusplus/releases/tag/v0.5.0) - 2020-03-18
|
||||
|
||||
#### Fixes:
|
||||
- fixed crash when reaching EOF while parsing a string when exceptions are disabled
|
||||
- fixed some attribute warnings in GCC
|
||||
- fixed build with GCC 8.2.0 (#15) (@shdnx)
|
||||
- fixed exception mode detection sometimes being incorrect on MSVC
|
||||
- fixed compilation on older implementations without `std::launder`
|
||||
- fixed `json_formatter` type deduction on older compilers
|
||||
|
||||
#### Additions:
|
||||
- added support for Unicode 13.0
|
||||
- added support for `\xHH` escape sequences ([toml/pull/796](https://github.com/toml-lang/toml/pull/796))
|
||||
- added short-form license preamble to all source files
|
||||
- added build configuration option for compiling examples
|
||||
|
||||
|
||||
|
||||
## [v0.4.3](https://github.com/marzer/tomlplusplus/releases/tag/v0.4.3) - 2020-03-10
|
||||
|
||||
#### Fixes:
|
||||
- fixed ICE in VS2019 when using `/std:c++17` instead of `/std:c++latest
|
||||
|
||||
#### Additions:
|
||||
- added `#error` when `TOML_EXCEPTIONS` is set to `1` but compiler exceptions were disabled
|
||||
|
||||
#### Changes:
|
||||
- parsing performance improvements
|
||||
|
||||
|
||||
|
||||
## [v0.4.0](https://github.com/marzer/tomlplusplus/releases/tag/v0.4.0) - 2020-03-05
|
||||
|
||||
#### Fixes:
|
||||
- fixed `parse_file()` failing to compile with plain string literals
|
||||
- fixed tests being built when used as a meson subproject (#14) (@shdnx)
|
||||
|
||||
#### Additions:
|
||||
- added support for compiling into DLLs on windows (`TOML_API`)
|
||||
- added support for explicitly setting the `TOML_EXCEPTION` mode
|
||||
- added `TOML_OPTIONAL_TYPE` customization point
|
||||
- added `node::ref()` and `node_view::ref()`
|
||||
|
||||
|
||||
|
||||
## [v0.3.0](https://github.com/marzer/tomlplusplus/releases/tag/v0.3.0) - 2020-03-01
|
||||
|
||||
#### Fixes:
|
||||
- fixed some pedantic clang warnings
|
||||
- fixed some minor documentation errors
|
||||
|
||||
#### Additions:
|
||||
- added `node::value()` and `node::value_or()`
|
||||
- added `node_view::value()`
|
||||
- added relops for the date/time classes
|
||||
- added `TOML_ALL_INLINE` and `TOML_IMPLEMENTATION` options
|
||||
- added preliminary support for ICC
|
||||
|
||||
#### Removals:
|
||||
- removed `<cmath>` dependency
|
||||
|
||||
|
||||
|
||||
## [v0.2.1](https://github.com/marzer/tomlplusplus/releases/tag/v0.2.1) - 2020-02-26
|
||||
|
||||
#### Fixes:
|
||||
- fixed minor printing bug in `operator<<(ostream, source_position)`
|
||||
- fixed minor documentation issues
|
||||
|
||||
#### Additions:
|
||||
- added `operator<<(ostream&, parse_error)`
|
||||
|
||||
#### Changes:
|
||||
- improved quality of error messages for boolean and inf/nan parsing
|
||||
|
||||
|
||||
|
||||
## [v0.2.0](https://github.com/marzer/tomlplusplus/releases/tag/v0.2.0) - 2020-02-23
|
||||
|
||||
#### Fixes:
|
||||
- fixed truncation of floating-point values when using ostreams
|
||||
- fixed missing value deduction guides for dates and times
|
||||
- fixed potential ODR issues relating to exception mode handling etc.
|
||||
- fixed some documentation issues
|
||||
|
||||
#### Additions:
|
||||
- added serialization round-trip tests
|
||||
- added `node::is_number()`
|
||||
- added `node_view::is_number()`
|
||||
- added `node_view::value_or()`
|
||||
- added hexfloat parsing support for all implementations (not just `<charconv>` ones)
|
||||
|
||||
|
||||
|
||||
## [v0.1.0](https://github.com/marzer/tomlplusplus/releases/tag/v0.1.0) - 2020-02-20
|
||||
|
||||
- First public release, yay! 🎉️
|
||||
|
@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(
|
||||
tomlplusplus
|
||||
VERSION 2.6.0
|
||||
DESCRIPTION "Header-only TOML config file parser and serializer for C++17 (and later!)"
|
||||
VERSION 3.0.0
|
||||
DESCRIPTION "Header-only TOML config file parser and serializer for C++17"
|
||||
HOMEPAGE_URL "https://marzer.github.io/tomlplusplus/"
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
@ -3,8 +3,10 @@ Contributions are very welcome! Either by [reporting issues] or submitting pull
|
||||
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
|
||||
`include`, **not** in `toml.hpp`.
|
||||
- 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). All three is a bonus.
|
||||
- Your changes should compile warning-free on at least one of:
|
||||
- GCC 8 or higher
|
||||
- Clang 8 or higher
|
||||
- MSVC 19.2X (Visual Studio 2019) or higher
|
||||
- You should regenerate the single-header file as part of your PR (a CI check will fail if you don't).
|
||||
|
||||
<br>
|
||||
@ -27,7 +29,7 @@ git submodule update --init --depth 1 external/Catch2 external/tloptional
|
||||
|
||||
### Testing on Windows with Visual Studio
|
||||
|
||||
Install [Visual Studio 2019] and [Test Adapter for Catch2], then open `vs/toml++.sln` and build the
|
||||
Install [Visual Studio] and [Test Adapter for Catch2], then open `toml++.sln` and build the
|
||||
projects in the `tests` solution folder. Visual Studio's Test Explorer should pick these up and
|
||||
allow you to run the tests directly.
|
||||
|
||||
@ -62,10 +64,19 @@ cd build-gcc-debug && ninja && ninja test \
|
||||
&& cd ..
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
[Visual Studio 2019]: https://visualstudio.microsoft.com/vs/
|
||||
## Testing with the [toml-test] suite
|
||||
As an optional extra you may wish to test against the 'official' test TOML test suite, [BurntSushi/toml-test]. See the
|
||||
instructions at [toml-test/README](./toml-test/README.md). Note that the toml++ tests already consume tests from the
|
||||
offical suite via a C++ code-generation script so you are not expected to take this extra step as part of contributing
|
||||
to the library.
|
||||
|
||||
[Visual Studio]: https://visualstudio.microsoft.com/vs/
|
||||
[Test Adapter for Catch2]: https://marketplace.visualstudio.com/items?itemName=JohnnyHendriks.ext01
|
||||
[reporting issues]: https://github.com/marzer/tomlplusplus/issues
|
||||
[Catch2]: https://github.com/catchorg/Catch2
|
||||
[meson]: https://mesonbuild.com/Getting-meson.html
|
||||
[ninja]: https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages
|
||||
[toml-test]: https://github.com/BurntSushi/toml-test
|
||||
[BurntSushi/toml-test]: https://github.com/BurntSushi/toml-test
|
||||
|
69
README.md
69
README.md
@ -24,8 +24,8 @@
|
||||
- Proper UTF-8 handling (incl. BOM)
|
||||
- Works with or without exceptions
|
||||
- Doesn't require RTTI
|
||||
- First-class support for serializing to JSON
|
||||
- Tested on Clang (6+), GCC (7+) and MSVC (VS2019)
|
||||
- Support for serializing to JSON and YAML
|
||||
- Tested on Clang (6+), GCC (7+) and MSVC (VS2019, VS2022)
|
||||
- Tested on x64, x86 and ARM
|
||||
|
||||
<br>
|
||||
@ -79,6 +79,8 @@ std::cout << config << "\n";
|
||||
// re-serialize as JSON
|
||||
std::cout << toml::json_formatter{ config } << "\n";
|
||||
|
||||
// re-serialize as YAML
|
||||
std::cout << toml::yaml_formatter{ config } << "\n";
|
||||
|
||||
```
|
||||
You'll find some more code examples in the `examples` directory, and plenty more as part of the [API documentation].
|
||||
@ -97,13 +99,13 @@ You'll find some more code examples in the `examples` directory, and plenty more
|
||||
2. `#include <toml++/toml.h>`
|
||||
|
||||
### Conan
|
||||
Add `tomlplusplus/2.5.0` to your conanfile.
|
||||
Add `tomlplusplus/3.0.0` to your conanfile.
|
||||
|
||||
### DDS
|
||||
Add `tomlpp` to your `package.json5`, e.g.:
|
||||
```
|
||||
depends: [
|
||||
'tomlpp^2.5.0',
|
||||
'tomlpp^3.0.0',
|
||||
]
|
||||
```
|
||||
> ℹ️ _[What is DDS?](https://dds.pizza/)_
|
||||
@ -119,7 +121,7 @@ include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
tomlplusplus
|
||||
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
|
||||
GIT_TAG v2.5.0
|
||||
GIT_TAG v3.0.0
|
||||
)
|
||||
FetchContent_MakeAvailable(tomlplusplus)
|
||||
```
|
||||
@ -130,27 +132,32 @@ FetchContent_MakeAvailable(tomlplusplus)
|
||||
in the C++ ecosystem. I'm also a cmake novice, for better or worse. If there's an integration option missing be
|
||||
assured that I fully support it being added, and welcome [pull requests](./CONTRIBUTING.md)!
|
||||
|
||||
### What about dependencies?
|
||||
If you just want to consume `toml++` as a regular library then you don't have any dependencies to worry about.
|
||||
There's a few test-related dependencies to be aware of if you're working on the library, though.
|
||||
See [CONTRIBUTING] for information.
|
||||
|
||||
<br>
|
||||
|
||||
# Configuration
|
||||
A number of configurable options are exposed in the form of preprocessor `#defines`. Most likely you
|
||||
A number of configurable options are exposed in the form of preprocessor `#defines` Most likely you
|
||||
won't need to mess with these at all, but if you do, set them before including toml++.
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|----------------------------|:--------------:|-----------------------------------|----------------------------------------------------------------------------------------------------------------------|
|
||||
| `TOML_HEADER_ONLY` | boolean | `1` | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). |
|
||||
| `TOML_API` | define | undefined | API annotation to add to public symbols (e.g. `__declspec(dllexport)` on Windows). |
|
||||
| `TOML_ASSERT(expr)` | function macro | `assert(expr)`<br>(or undefined) | Sets the assert function used by the library. |
|
||||
| `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |
|
||||
| `TOML_EXCEPTIONS` | boolean | per your compiler's settings | Sets whether the library uses exceptions. |
|
||||
| `TOML_IMPLEMENTATION` | define | undefined | Define this to enable compilation of the library's implementation. Meaningless if `TOML_HEADER_ONLY` is `1`. |
|
||||
| `TOML_LARGE_FILES` | boolean | `0` | Uses 32-bit integers for line and column indices (instead of 16-bit). |
|
||||
| `TOML_OPTIONAL_TYPE` | type name | undefined | Overrides the `optional<T>` type used by the library if you need [something better than std::optional]. |
|
||||
| `TOML_PARSER` | boolean | `1` | Disable this to prevent inclusion of the parser-related parts of the library if you don't need them. |
|
||||
| `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_SMALL_INT_TYPE` | type name | undefined | If your codebase has an additional 'small' integer type (e.g. 24-bits), this tells toml++ about it. |
|
||||
| `TOML_UNRELEASED_FEATURES` | boolean | `0` | Enables support for [unreleased TOML language features] not yet part of a [numbered version]. |
|
||||
| `TOML_WINDOWS_COMPAT` | boolean | `1` on Windows | Enables support for transparent conversion between wide and narrow strings in some places when building for Windows. |
|
||||
| Option | Type | Description | Default |
|
||||
|-----------------------------------|:--------------:|----------------------------------------------------------------------------------------------------------|------------------------|
|
||||
| `TOML_API` | define | API annotation to add to public symbols (e.g. `__declspec(dllexport)` on Windows). | undefined |
|
||||
| `TOML_ASSERT(expr)` | function macro | Sets the assert function used by the library. | `assert()` |
|
||||
| `TOML_CONFIG_HEADER` | string literal | Includes the given header file before the rest of the library. | undefined |
|
||||
| `TOML_ENABLE_FORMATTERS` | boolean | Enables the formatters. Set to `0` if you don't need them to improve compile times and binary size. | `1` |
|
||||
| `TOML_ENABLE_PARSER` | boolean | Enables the parser. Set to `0` if you don't need it to improve compile times and binary size. | `1` |
|
||||
| `TOML_ENABLE_UNRELEASED_FEATURES` | boolean | Enables support for [unreleased TOML language features]. | `0` |
|
||||
| `TOML_ENABLE_WINDOWS_COMPAT` | boolean | Enables support for transparent conversion between wide and narrow strings. | `1` on Windows |
|
||||
| `TOML_EXCEPTIONS` | boolean | Sets whether the library uses exceptions. | per compiler settings |
|
||||
| `TOML_HEADER_ONLY` | boolean | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library).| `1` |
|
||||
| `TOML_IMPLEMENTATION` | define | Define this to enable compilation of the library's implementation when `TOML_HEADER_ONLY` == `0`. | undefined |
|
||||
| `TOML_OPTIONAL_TYPE` | type name | Overrides the `optional<T>` type used by the library if you need [something better than std::optional]. | undefined |
|
||||
| `TOML_SMALL_FLOAT_TYPE` | type name | If your codebase has a custom 'small float' type (e.g. half-precision), this tells toml++ about it. | undefined |
|
||||
| `TOML_SMALL_INT_TYPE` | type name | If your codebase has a custom 'small integer' type (e.g. 24-bits), this tells toml++ about it. | undefined |
|
||||
|
||||
> ℹ️ _A number of these have ABI implications; the library uses inline namespaces to prevent you from accidentally
|
||||
linking incompatible combinations together._
|
||||
@ -165,15 +172,15 @@ support for a number of unreleased features from the [TOML master] and some sane
|
||||
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_PATCH`.
|
||||
|
||||
### 🔸️ **Unreleased language features:**
|
||||
### **Unreleased language features:**
|
||||
- [#516]: Allow newlines and trailing commas in inline tables
|
||||
- [#562]: Allow hex floating-point values
|
||||
- [#644]: Support `+` in key names
|
||||
- [#671]: Local time of day format should support `09:30` as opposed to `09:30:00`
|
||||
- [#687]: Relax bare key restrictions to allow additional unicode characters
|
||||
- [#709]: Include an \xHH escape code sequence
|
||||
- [#796]: Include an \xHH escape code sequence
|
||||
|
||||
> ℹ️ _`#define TOML_UNRELEASED_FEATURES 1` to enable these features (see [Configuration](#Configuration))._
|
||||
> ℹ️ _`#define TOML_ENABLE_UNRELEASED_FEATURES 1` to enable these features (see [Configuration](#Configuration))._
|
||||
|
||||
### 🔹️ **TOML v1.0.0:**
|
||||
All features supported, including:
|
||||
@ -206,6 +213,7 @@ UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[
|
||||
- **[@bobfang1992](https://github.com/bobfang1992)** - Reported a bug and created a [wrapper in python](https://github.com/bobfang1992/pytomlpp)
|
||||
- **[@GiulioRomualdi](https://github.com/GiulioRomualdi)** - Added cmake+meson support
|
||||
- **[@levicki](https://github.com/levicki)** - Helped design some new features
|
||||
- **[@moorereason](https://github.com/moorereason)** - Reported a whole bunch of bugs
|
||||
- **[@mosra](https://github.com/mosra)** - Created the awesome [m.css] used to generate the API docs
|
||||
- **[@ned14](https://github.com/ned14)** - Reported a bunch of bugs and helped design some new features
|
||||
- **[@okureta](https://github.com/okureta)** - Reported a bug
|
||||
@ -214,13 +222,13 @@ UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[
|
||||
- **[@Reedbeta](https://github.com/Reedbeta)** - Fixed a bug and added additional Visual Studio debugger native visualizers
|
||||
- **[@Ryan-rsm-McKenzie](https://github.com/Ryan-rsm-McKenzie)** - Add natvis file to cmake install script
|
||||
- **[@shdnx](https://github.com/shdnx)** - Fixed a bug on GCC 8.2.0 and some meson config issues
|
||||
- **[@sobczyk](https://github.com/sobczyk)** - Reported some bugs
|
||||
- **[@sneves](https://github.com/sneves)** - Helped fix a number of parser bugs
|
||||
- **[@sobczyk](https://github.com/sobczyk)** - Reported some bugs
|
||||
- **[@std-any-emplace](https://github.com/std-any-emplace)** - Reported some bugs
|
||||
- **[@traversaro](https://github.com/traversaro)** - Added vcpkg support and reported a bunch of bugs
|
||||
- **[@ximion](https://github.com/ximion)** - Added support for installation with meson
|
||||
- **[@whiterabbit963](https://github.com/whiterabbit963)** - Fixed a bug with value_or conversions
|
||||
- **[@Tachi107](https://github.com/Tachi107)** - Made some tweaks to meson.build
|
||||
- **[@traversaro](https://github.com/traversaro)** - Added vcpkg support and reported a bunch of bugs
|
||||
- **[@whiterabbit963](https://github.com/whiterabbit963)** - Fixed a bug with value_or conversions
|
||||
- **[@ximion](https://github.com/ximion)** - Added support for installation with meson
|
||||
|
||||
<br>
|
||||
|
||||
@ -236,7 +244,7 @@ though you're welcome to reach out via other means. In order of likely response
|
||||
|
||||
[API documentation]: https://marzer.github.io/tomlplusplus/
|
||||
[homepage]: https://marzer.github.io/tomlplusplus/
|
||||
[unreleased TOML language features]: #-unreleased-language-features
|
||||
[unreleased TOML language features]: #unreleased-language-features
|
||||
[most recently-released 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
|
||||
@ -261,8 +269,7 @@ though you're welcome to reach out via other means. In order of likely response
|
||||
[#665]: https://github.com/toml-lang/toml/issues/665
|
||||
[#671]: https://github.com/toml-lang/toml/issues/671
|
||||
[#687]: https://github.com/toml-lang/toml/issues/687
|
||||
[#709]: https://github.com/toml-lang/toml/pull/709
|
||||
[#796]: https://github.com/toml-lang/toml/pull/796
|
||||
[#766]: https://github.com/toml-lang/toml/issues/766
|
||||
[LICENSE-utf8-decoder]: ./LICENSE-utf8-decoder
|
||||
[something better than std::optional]: https://github.com/TartanLlama/optional
|
||||
[m.css]: https://mcss.mosra.cz/documentation/doxygen
|
||||
|
43
cpp.hint
43
cpp.hint
@ -1,16 +1,37 @@
|
||||
#define TOML_ABI_NAMESPACE_BOOL(...) static_assert(true)
|
||||
#define TOML_ABI_NAMESPACE_END static_assert(true)
|
||||
#define TOML_ABSTRACT_BASE
|
||||
#define TOML_ALWAYS_INLINE inline
|
||||
#define TOML_ANON_NAMESPACE_END static_assert(true)
|
||||
#define TOML_ANON_NAMESPACE_START namespace
|
||||
#define TOML_API
|
||||
#define TOML_ATTR(...)
|
||||
#define TOML_ALWAYS_INLINE inline
|
||||
#define TOML_NEVER_INLINE
|
||||
#define TOML_TRIVIAL_ABI
|
||||
#define TOML_ABSTRACT_BASE
|
||||
#define TOML_CLOSED_ENUM
|
||||
#define TOML_CLOSED_FLAGS_ENUM
|
||||
#define TOML_CONST_GETTER
|
||||
#define TOML_CONST_INLINE_GETTER inline
|
||||
#define TOML_CONSTRAINED_TEMPLATE(cond, ...) template <__VA_ARGS__>
|
||||
#define TOML_EMPTY_BASES
|
||||
#define TOML_MAY_THROW
|
||||
#define TOML_CONSTEVAL constexpr
|
||||
#define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__>
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_EXTERN
|
||||
#define TOML_EXTERN_NOEXCEPT(...)
|
||||
#define TOML_EXTERNAL_LINKAGE
|
||||
#define TOML_FLAGS_ENUM
|
||||
#define TOML_HIDDEN_CONSTRAINT(cond, ...) template <__VA_ARGS__>
|
||||
#define TOML_IMPL_NAMESPACE_END static_assert(true)
|
||||
#define TOML_IMPL_NAMESPACE_START namespace toml::impl
|
||||
#define TOML_INTERNAL_LINKAGE static
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_NAMESPACE_END static_assert(true)
|
||||
#define TOML_NAMESPACE_START namespace toml
|
||||
#define TOML_NEVER_INLINE
|
||||
#define TOML_NODISCARD
|
||||
#define TOML_NODISCARD_CTOR
|
||||
#define TOML_EXTERNAL_LINKAGE
|
||||
#define TOML_INTERNAL_LINKAGE
|
||||
#define TOML_OPEN_ENUM
|
||||
#define TOML_OPEN_FLAGS_ENUM
|
||||
#define TOML_PURE_GETTER
|
||||
#define TOML_PURE_INLINE_GETTER inline
|
||||
#define TOML_RETURNS_BY_THROWING
|
||||
#define TOML_TRIVIAL_ABI
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_LIKELY_CASE
|
||||
#define TOML_UNLIKELY_CASE
|
||||
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Binary file not shown.
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@ -9,7 +9,7 @@
|
||||
\section mainpage-features Features
|
||||
- Supports the latest [TOML](https://toml.io/) release ([v1.0.0](https://toml.io/en/v1.0.0)), plus
|
||||
optional support for some unreleased TOML features
|
||||
- Supports serializing to JSON
|
||||
- Supports serializing to JSON and YAML
|
||||
- Proper UTF-8 handling (incl. BOM)
|
||||
- C++17 (plus some C++20 features where available, e.g. experimental support for char8_t strings)
|
||||
- Header-only (optional!)
|
||||
@ -130,7 +130,7 @@
|
||||
|
||||
\subsection mainpage-example-parsing-without-exceptions Handling errors without exceptions
|
||||
Can't (or won't) use exceptions? That's fine too. You can disable exceptions in your compiler flags and/or
|
||||
explicitly disable the library's use of them by setting the option \ref TOML_EXCEPTIONS to `0`. In either case,
|
||||
explicitly disable the library's use of them by setting the option #TOML_EXCEPTIONS to `0`. In either case,
|
||||
the parsing functions return a toml::parse_result instead of a toml::table:
|
||||
|
||||
\cpp
|
||||
@ -260,6 +260,10 @@
|
||||
std::cout << "cats: " << tbl["animals"]["cats"] << "\n";
|
||||
std::cout << "fish[1]: " << tbl["animals"]["fish"][1] << "\n";
|
||||
|
||||
// can also be retrieved via absolute path
|
||||
std::cout << "cats: " << tbl.at_path("animals.cats") << "\n";
|
||||
std::cout << "fish[1]: " << tbl.at_path("animals.fish[1]") << "\n";
|
||||
|
||||
// ...even if the element doesn't exist
|
||||
std::cout << "dinosaurs: " << tbl["animals"]["dinosaurs"] << "\n"; //no dinosaurs :(
|
||||
|
||||
@ -278,6 +282,8 @@
|
||||
numbers: [ 2, 3, 4, 'five', 6.0, 7, [ 8, 9 ] ]
|
||||
cats: [ 'tiger', 'lion', 'puma' ]
|
||||
fish[1]: 'trout'
|
||||
cats: [ 'tiger', 'lion', 'puma' ]
|
||||
fish[1]: 'trout'
|
||||
dinosaurs:
|
||||
\eout
|
||||
|
||||
@ -290,12 +296,12 @@
|
||||
|
||||
|
||||
|
||||
\subsection mainpage-example-serialization Serializing as TOML and JSON
|
||||
\subsection mainpage-example-serialization Serializing as TOML, JSON and YAML
|
||||
All toml++ data types have overloaded `operator<<` for ostreams, so 'serializing' a set of TOML data to actual
|
||||
TOML is done just by printing it to an ostream. Converting it to JSON is done in the same way,
|
||||
but via a toml::json_formatter.
|
||||
TOML is done just by printing it to an ostream. Converting it to JSON and YAML is done in much the same way,
|
||||
but via a toml::json_formatter and toml::yaml_formatter.
|
||||
|
||||
\godbolt{MMNoW4}
|
||||
\godbolt{srdfoWMq6}
|
||||
|
||||
\cpp
|
||||
#include <iostream>
|
||||
@ -303,18 +309,18 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tbl = toml::table{{
|
||||
auto tbl = toml::table{
|
||||
{ "lib", "toml++" },
|
||||
{ "cpp", toml::array{ 17, 20, "and beyond" } },
|
||||
{ "toml", toml::array{ "1.0.0", "and beyond" } },
|
||||
{ "repo", "https://github.com/marzer/tomlplusplus/" },
|
||||
{ "author", toml::table{{
|
||||
{ "author", toml::table{
|
||||
{ "name", "Mark Gillard" },
|
||||
{ "github", "https://github.com/marzer" },
|
||||
{ "twitter", "https://twitter.com/marzer8789" }
|
||||
}}
|
||||
}
|
||||
},
|
||||
}};
|
||||
};
|
||||
|
||||
// serializing as TOML
|
||||
std::cout << "###### TOML ######" << "\n\n";
|
||||
@ -323,6 +329,11 @@
|
||||
// serializing as JSON using toml::json_formatter:
|
||||
std::cout << "###### JSON ######" << "\n\n";
|
||||
std::cout << toml::json_formatter{ tbl } << "\n\n";
|
||||
|
||||
// serializing as YAML using toml::yaml_formatter:
|
||||
std::cout << "###### YAML ######" << "\n\n";
|
||||
std::cout << toml::yaml_formatter{ tbl } << "\n\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
\ecpp
|
||||
@ -360,10 +371,28 @@
|
||||
"and beyond"
|
||||
]
|
||||
}
|
||||
|
||||
###### YAML ######
|
||||
|
||||
author:
|
||||
github: 'https://github.com/marzer'
|
||||
name: 'Mark Gillard'
|
||||
twitter: 'https://twitter.com/marzer8789'
|
||||
cpp:
|
||||
- 17
|
||||
- 20
|
||||
- 'and beyond'
|
||||
lib: toml++
|
||||
repo: 'https://github.com/marzer/tomlplusplus/'
|
||||
toml:
|
||||
- '1.0.0'
|
||||
- 'and beyond'
|
||||
\eout
|
||||
|
||||
\see
|
||||
- toml::default_formatter
|
||||
- toml::toml_formatter
|
||||
- toml::json_formatter
|
||||
- toml::yaml_formatter
|
||||
|
||||
|
||||
|
||||
@ -373,7 +402,7 @@
|
||||
a large number of translation units. You can counter this by disabling header-only mode and explicitly controlling
|
||||
where the library's implementation is compiled.
|
||||
|
||||
<strong>Step 1: Set \ref TOML_HEADER_ONLY to [code]0[/code] before including toml++</strong>
|
||||
<strong>Step 1: Set #TOML_HEADER_ONLY to [code]0[/code] before including toml++</strong>
|
||||
|
||||
This must be the same everywhere, so either set it as a global `#define` in your build system, or
|
||||
do it manually before including toml++ in some global header that's used everywhere in your project:
|
||||
@ -384,7 +413,7 @@
|
||||
#include <toml.hpp>
|
||||
\ecpp
|
||||
|
||||
<strong>Step 2: Define \ref TOML_IMPLEMENTATION before including toml++ in one specific translation unit</strong>
|
||||
<strong>Step 2: Define #TOML_IMPLEMENTATION before including toml++ in one specific translation unit</strong>
|
||||
|
||||
\cpp
|
||||
// some_code_file.cpp
|
||||
@ -393,10 +422,11 @@
|
||||
#include "global_header_that_includes_toml++.h"
|
||||
\ecpp
|
||||
|
||||
<strong>Bonus Step: Disable the parser if you don't need it</strong>
|
||||
<strong>Bonus Step: Disable any library features you don't need</strong>
|
||||
|
||||
If all you need to do is serialize some code-generated TOML and don't actually need the parser at all you can
|
||||
set \ref TOML_PARSER to `0` to disable the parser altogether. This can yield fairly significant compilation
|
||||
Some library features can be disabled wholesale so you can avoid paying their the compilation cost if you don't need them.
|
||||
For example, if all you need to do is serialize some code-generated TOML and don't actually need the parser at all you, can
|
||||
set #TOML_ENABLE_PARSER to `0` to disable the parser altogether. This can yield fairly significant compilation
|
||||
speedups since the parser accounts for a good chunk of the library's code.
|
||||
|
||||
|
||||
@ -427,7 +457,7 @@
|
||||
|
||||
|
||||
\subsection mainpage-adding-lib-conan Conan
|
||||
Add `tomlplusplus/2.5.0` to your conanfile.
|
||||
Add `tomlplusplus/3.0.0` to your conanfile.
|
||||
|
||||
|
||||
|
||||
@ -435,7 +465,7 @@
|
||||
Add `tomlpp` to your `package.json5`, e.g.:
|
||||
\bash
|
||||
depends: [
|
||||
'tomlpp^2.5.0',
|
||||
'tomlpp^3.0.0',
|
||||
]
|
||||
\ebash
|
||||
|
||||
@ -467,7 +497,7 @@
|
||||
FetchContent_Declare(
|
||||
tomlplusplus
|
||||
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
|
||||
GIT_TAG v2.5.0
|
||||
GIT_TAG v3.0.0
|
||||
)
|
||||
FetchContent_MakeAvailable(tomlplusplus)
|
||||
\endcode
|
||||
@ -490,10 +520,12 @@
|
||||
|
||||
\out
|
||||
Parsing data.toml 5000 times:
|
||||
pytomlpp: 0.662 s
|
||||
toml: 5.277 s (7.9x slower)
|
||||
qtoml: 8.020 s (12.1x slower)
|
||||
tomlkit: 32.898 s (49.6x slower)
|
||||
pytomlpp: 0.694 s
|
||||
rtoml: 0.871 s ( 1.25x)
|
||||
tomli: 2.625 s ( 3.78x)
|
||||
toml: 5.642 s ( 8.12x)
|
||||
qtoml: 7.760 s (11.17x)
|
||||
tomlkit: 32.708 s (47.09x)
|
||||
\eout
|
||||
|
||||
Install it using `pip`:
|
||||
|
@ -80,10 +80,18 @@ string_literals = [ '_toml' ]
|
||||
|
||||
|
||||
[autolinks]
|
||||
'(?:toml::)?parse[_ ]results?' = 'classtoml_1_1parse__result.html'
|
||||
'(?:toml::)?parse[_ ]errors?' = 'classtoml_1_1parse__error.html'
|
||||
'(?:toml::)?node[_ ]views?' = 'classtoml_1_1node__view.html'
|
||||
'(?:toml::)?json[_ ]formatters?' = 'classtoml_1_1json__formatter.html'
|
||||
'(?:toml::)?date[_-]times?' = 'structtoml_1_1date__time.html'
|
||||
'(?:toml::)?default[_ ]formatters?' = 'classtoml_1_1default__formatter.html'
|
||||
'(?:toml::)?json[_ ]formatters?' = 'classtoml_1_1json__formatter.html'
|
||||
'(?:toml::)?node[_ ]views?' = 'classtoml_1_1node__view.html'
|
||||
'(?:toml::)?parse[_ ]errors?' = 'classtoml_1_1parse__error.html'
|
||||
'(?:toml::)?parse[_ ]results?' = 'classtoml_1_1parse__result.html'
|
||||
'(?:toml::)?source[_ ]positions?' = 'structtoml_1_1source__position.html'
|
||||
'(?:toml::)?source[_ ]regions?' = 'structtoml_1_1source__region.html'
|
||||
'(?:toml::)?time[_ ]offsets?' = 'structtoml_1_1time__offset.html'
|
||||
'(?:toml::)?toml[_ ]formatters?' = 'classtoml_1_1toml__formatter.html'
|
||||
'(?:toml::)?yaml[_ ]formatters?' = 'classtoml_1_1yaml__formatter.html'
|
||||
'toml::dates?' = 'structtoml_1_1date.html'
|
||||
'toml::keys?' = 'classtoml_1_1key.html'
|
||||
'toml::times?' = 'structtoml_1_1time.html'
|
||||
'toml::values?' = 'classtoml_1_1value.html'
|
||||
|
@ -20,6 +20,7 @@ function(add_example name)
|
||||
endfunction()
|
||||
|
||||
add_example(error_printer)
|
||||
add_example(parse_benchmark)
|
||||
add_example(simple_parser ARGS "${PROJECT_SOURCE_DIR}/example.toml")
|
||||
add_example(toml_generator ARGS 100)
|
||||
add_example(toml_to_json_transcoder ARGS "${PROJECT_SOURCE_DIR}/example.toml")
|
||||
|
94
examples/benchmark_data.toml
Normal file
94
examples/benchmark_data.toml
Normal file
@ -0,0 +1,94 @@
|
||||
addition-used = false
|
||||
afraid-boiling-draconian = 1916-12-15T11:26:42+11:26
|
||||
boiling-whip = 12:23:17.000000129
|
||||
charming = 16771
|
||||
close-unbecoming = 14:49:02
|
||||
contain-terrible-neck = 1928-11-07T06:30:56
|
||||
creature = 0.4857
|
||||
crowded-profuse-capable = 1932-05-28
|
||||
deserted-cross-creature = 1931-12-26T04:31:04
|
||||
deserted-heavy = [ 2014-02-08, 1984-03-16, 1910-08-05 ]
|
||||
fabulous = 0.3388
|
||||
ghost-birds-legal = 1989-09-02
|
||||
grandfather-weary = 10216
|
||||
haircut-dreary-broken = 'unadvised rejoice lewd crime grandfather rice imperfect'
|
||||
harm-snow = 0.6724
|
||||
leather-aromatic-rabbit = false
|
||||
license-harm = 1987-08-15T15:30:51+03:24
|
||||
naughty-self-close = 1916-09-21T01:53:27-02:59
|
||||
neck = 29653
|
||||
neck-crime-wistful = 1998-12-07
|
||||
rest-afraid = [
|
||||
1912-06-23T07:00:07-07:46,
|
||||
1910-11-17T13:10:34,
|
||||
2014-08-03T04:37:12-06:36,
|
||||
1966-11-22T18:08:23+06:10,
|
||||
1985-03-01T08:11:38,
|
||||
1976-09-04T20:46:46+00:29,
|
||||
1964-05-18T20:13:27-01:25,
|
||||
1961-10-14T11:03:51.000011555+06:23,
|
||||
2005-07-13T02:57:15-01:46,
|
||||
2007-02-01T17:09:54-08:45,
|
||||
1952-03-06T09:15:04+01:44,
|
||||
1962-12-25T23:00:11+04:28
|
||||
]
|
||||
rotten-best = 0.0325
|
||||
run-curious = true
|
||||
run-meaty = 04:40:20.000003312
|
||||
scintillating-cream = 0.2604
|
||||
sisters-playground = 'week spiritual pause insidious uptight'
|
||||
spiritual-borrow-messy = 16:49:32
|
||||
surprise-jail-babies = 2008-01-01
|
||||
title-unbiased = 1958-10-08
|
||||
unbecoming-scene-lewd = true
|
||||
worried-spicy = 23:03:54
|
||||
|
||||
[contain]
|
||||
ghost = 0.2471
|
||||
tank-lackadaisical = 1945-02-18T22:22:27+01:41
|
||||
|
||||
[contain.righteous-imperfect-remarkable]
|
||||
ticket = 0.2412
|
||||
voyage = 'prefer silky night draconian three dreary decisive'
|
||||
wilderness-draconian = 04:58:17
|
||||
|
||||
[contain.righteous-imperfect-remarkable.deeply-night-gold]
|
||||
legal = 1981-07-04
|
||||
righteous = [ false, true, false, false, true ]
|
||||
wilderness = 1900-12-24
|
||||
|
||||
[crime]
|
||||
boiling-excuse-incandescent = 31173
|
||||
flat-rejoice = 0.8682
|
||||
furtive = 6866
|
||||
heavy-memory = 5545
|
||||
lackadaisical-terrible-overjoyed = [ 'harm acceptable naughty pause', 'page anxious threatening lewd' ]
|
||||
reject-aromatic = [ false, true, true, true, false, true ]
|
||||
reject-naughty = 11229
|
||||
scintillating-bake-harm = 0.8258
|
||||
|
||||
[license-bat]
|
||||
adorable-blind-string = 1961-08-14
|
||||
bat = 1939-10-28
|
||||
blind-wilderness = 2004-07-14
|
||||
|
||||
[rapid]
|
||||
borrow = true
|
||||
jail-weary-furtive = 'room'
|
||||
protective-sulky = 4737
|
||||
room-decisive-unbiased = 1998-11-01T12:23:58
|
||||
soap = 1985-05-06
|
||||
sprout-rich = 0.6026
|
||||
|
||||
[rapid.clean-leather]
|
||||
blood-snow-mark = true
|
||||
equable = 0.2923
|
||||
fabulous = 1979-07-24T00:53:39+06:22
|
||||
glorious-threatening = true
|
||||
lewd-dull = 02:40:53.000027288
|
||||
|
||||
[run-overjoyed]
|
||||
creature-cheerful = 11071
|
||||
respect-history-anxious = 0.4637
|
||||
vessel = 'curious'
|
||||
|
@ -8,28 +8,30 @@
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
#define TOML_EXCEPTIONS 0
|
||||
#define TOML_UNRELEASED_FEATURES 0
|
||||
#define TOML_EXCEPTIONS 0
|
||||
#define TOML_ENABLE_UNRELEASED_FEATURES 0
|
||||
#include <toml++/toml.h>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
inline constexpr auto invalid_parses = std::array
|
||||
{
|
||||
"########## comments"sv,
|
||||
inline constexpr auto invalid_parses = std::array{
|
||||
"########## comments and whitespace"sv,
|
||||
"# bar\rkek"sv,
|
||||
"# bar\bkek"sv,
|
||||
"# \xf1\x63"sv,
|
||||
"# val1 = 1\fval2 = 2"sv,
|
||||
"foo = 1\n\u2000\nbar = 2"sv,
|
||||
|
||||
"########## inline tables"sv,
|
||||
"val = {,}"sv,
|
||||
"val = {a='b',}"sv, // allowed when TOML_UNRELEASED_FEATURES == 1
|
||||
"val = {a='b',}"sv, // allowed when TOML_ENABLE_UNRELEASED_FEATURES == 1
|
||||
"val = {a='b',,}"sv,
|
||||
"val = {a='b',"sv,
|
||||
"val = {a='b',\n c='d'}"sv, // allowed when TOML_UNRELEASED_FEATURES == 1
|
||||
"val = {a='b',\n c='d'}"sv, // allowed when TOML_ENABLE_UNRELEASED_FEATURES == 1
|
||||
"val = {?='b'}"sv,
|
||||
"foo = {} \n [foo.bar]"sv,
|
||||
|
||||
"########## tables"sv,
|
||||
"[]"sv,
|
||||
@ -69,7 +71,7 @@ namespace
|
||||
"val = \" \r \""sv,
|
||||
R"(val = ")"sv,
|
||||
R"(val = "\g")"sv,
|
||||
R"(val = "\x20")"sv, // allowed when TOML_UNRELEASED_FEATURES == 1
|
||||
R"(val = "\x20")"sv, // allowed when TOML_ENABLE_UNRELEASED_FEATURES == 1
|
||||
R"(val = "\uFFF")"sv,
|
||||
R"(val = "\uFFFG")"sv,
|
||||
R"(val = "\UFFFFFFF")"sv,
|
||||
@ -92,12 +94,14 @@ namespace
|
||||
R"(val = -+1)"sv,
|
||||
R"(val = 1_0_)"sv,
|
||||
R"(val = 1_0_ )"sv,
|
||||
R"(val = 999999999999999999999999999999999999 )"sv,
|
||||
R"(val = 9223372036854775808 )"sv,
|
||||
R"(val = 01 )"sv,
|
||||
R"(val = 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000 )"sv,
|
||||
R"(val = 0o1000000000000000000000 )"sv,
|
||||
R"(val = 9223372036854775808 )"sv,
|
||||
R"(val = 0x8000000000000000 )"sv,
|
||||
|
||||
"########## floats"sv,
|
||||
R"(val = 9999999999999999999999999999999999999999999999999999999999999995.0)"sv,
|
||||
R"(val = 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0)"sv,
|
||||
};
|
||||
|
||||
inline constexpr auto divider =
|
||||
@ -106,8 +110,6 @@ namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
examples::init();
|
||||
|
||||
for (auto str : invalid_parses)
|
||||
{
|
||||
if (str.empty())
|
||||
|
@ -19,13 +19,13 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
@ -6,14 +6,14 @@
|
||||
// this file is for boilerplate unrelated to the toml++ example learning outcomes.
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Weverything"
|
||||
#elif defined (__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Weverything"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(push, 0)
|
||||
#pragma warning(push, 0)
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
@ -24,29 +24,37 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#ifdef _MSC_VER
|
||||
extern "C" __declspec(dllimport) int __stdcall SetConsoleOutputCP(unsigned int);
|
||||
#pragma comment(lib, "Kernel32.lib")
|
||||
#else
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
namespace examples
|
||||
namespace
|
||||
{
|
||||
inline void init() noexcept
|
||||
static const auto initialize_environment_automagically = []() noexcept
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleOutputCP(65001); //CP_UTF8
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
SetConsoleOutputCP(65001); // CP_UTF8
|
||||
#endif
|
||||
|
||||
std::ios_base::sync_with_stdio(false);
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}();
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@ -1,22 +1,50 @@
|
||||
example_args = []
|
||||
example_args += additional_arguments
|
||||
example_overrides = []
|
||||
example_overrides += overrides
|
||||
if is_gcc or is_clang
|
||||
example_args += [ '-Wno-switch', '-Wno-switch-default', '-Wno-switch-enum' ]
|
||||
endif
|
||||
if is_clang and get_option('asan_examples')
|
||||
example_args += [ '-g3' ]
|
||||
example_overrides += 'b_sanitize=address'
|
||||
endif
|
||||
|
||||
examples = [
|
||||
'simple_parser',
|
||||
'toml_to_json_transcoder',
|
||||
'toml_generator',
|
||||
'error_printer'
|
||||
'error_printer',
|
||||
'parse_benchmark',
|
||||
]
|
||||
|
||||
example_executables = []
|
||||
foreach example : examples
|
||||
executable(
|
||||
example_executables += [[
|
||||
example,
|
||||
[ example+'.cpp' ],
|
||||
include_directories: include_dirs,
|
||||
cpp_args: example_args,
|
||||
override_options: overrides
|
||||
)
|
||||
executable(
|
||||
example,
|
||||
[ example+'.cpp' ],
|
||||
include_directories: include_dirs,
|
||||
cpp_args: example_args,
|
||||
override_options: example_overrides
|
||||
)
|
||||
]]
|
||||
endforeach
|
||||
|
||||
if is_clang and get_option('asan_examples')
|
||||
foreach executable : example_executables
|
||||
|
||||
# skip the transcoder (it waits on stdin) and the benchmark (might be slow and cause CI to fail)
|
||||
if executable[0].contains('transcoder') or executable[0].contains('benchmark')
|
||||
continue
|
||||
endif
|
||||
|
||||
test(
|
||||
executable[0], # name
|
||||
executable[1], # executable object
|
||||
workdir: meson.source_root()/'examples'
|
||||
)
|
||||
|
||||
endforeach
|
||||
endif
|
||||
|
81
examples/parse_benchmark.cpp
Normal file
81
examples/parse_benchmark.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// This example is just a short-n-shiny benchmark.
|
||||
|
||||
#include "examples.h"
|
||||
#include <toml++/toml.h>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
static constexpr size_t iterations = 10000;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const auto file_path = std::string(argc > 1 ? std::string_view{ argv[1] } : "benchmark_data.toml"sv);
|
||||
|
||||
// read the file into a string first to remove file I/O from the benchmark
|
||||
std::string file_content;
|
||||
{
|
||||
std::ifstream file(file_path, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
|
||||
if (!file)
|
||||
{
|
||||
std::cerr << "File '"sv << file_path << "'could not be opened for reading\n"sv;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto file_size = file.tellg();
|
||||
if (file_size == -1)
|
||||
{
|
||||
std::cerr << "File '"sv << file_path << "' could not be opened for reading\n"sv;
|
||||
return -1;
|
||||
}
|
||||
file.seekg(0, std::ifstream::beg);
|
||||
|
||||
file_content.resize(static_cast<size_t>(file_size));
|
||||
file.read(file_content.data(), static_cast<std::streamsize>(file_size));
|
||||
if (!file.eof() && !file)
|
||||
{
|
||||
std::cerr << "Failed to read contents of file '"sv << file_path << "'\n"sv;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// parse once to make sure it isn't garbage
|
||||
{
|
||||
#if TOML_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
const auto result = toml::parse(file_content, file_path);
|
||||
}
|
||||
catch (const toml::parse_error& err)
|
||||
{
|
||||
std::cerr << err << "\n";
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
const auto result = toml::parse(file_content, file_path);
|
||||
if (!result)
|
||||
{
|
||||
std::cerr << result.error() << "\n";
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// run the benchmark
|
||||
std::cout << "Parsing '"sv << file_path << "' "sv << iterations << " times...\n"sv;
|
||||
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
for (size_t i = 0; i < iterations; i++)
|
||||
std::ignore = toml::parse(file_content, file_path);
|
||||
const auto cumulative_sec =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - start).count();
|
||||
const auto mean_sec = cumulative_sec / static_cast<double>(iterations);
|
||||
std::cout << " total: "sv << cumulative_sec << " s\n"sv
|
||||
<< " mean: "sv << mean_sec << " s\n"sv;
|
||||
|
||||
return 0;
|
||||
}
|
62
examples/parse_benchmark.vcxproj
Normal file
62
examples/parse_benchmark.vcxproj
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="..\toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\examples</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="..\toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="parse_benchmark.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="benchmark_data.toml" />
|
||||
<None Include="meson.build" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="examples.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
@ -3,29 +3,36 @@
|
||||
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// This example demonstrates how to parse TOML from a file and re-serialize it (print it out) to stdout.
|
||||
// This example demonstrates how to parse TOML from a file or stdin and re-serialize it (print it out) to stdout.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
#define TOML_UNRELEASED_FEATURES 1
|
||||
#define TOML_ENABLE_UNRELEASED_FEATURES 1
|
||||
#include <toml++/toml.h>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
examples::init();
|
||||
|
||||
const auto path = argc > 1 ? std::string_view{ argv[1] } : "example.toml"sv;
|
||||
|
||||
toml::table tbl;
|
||||
try
|
||||
{
|
||||
const auto table = toml::parse_file(path);
|
||||
std::cout << table << "\n";
|
||||
// read directly from stdin
|
||||
if (path == "-"sv || path.empty())
|
||||
tbl = toml::parse(std::cin, "stdin"sv);
|
||||
|
||||
// read from a file
|
||||
else
|
||||
tbl = toml::parse_file(path);
|
||||
}
|
||||
catch (const toml::parse_error& err)
|
||||
{
|
||||
std::cerr << err << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << tbl << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,13 +19,13 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
@ -7,84 +7,75 @@
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
#define TOML_PARSER 0
|
||||
#define TOML_ENABLE_PARSER 0
|
||||
#include <toml++/toml.h>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
inline constexpr auto words = std::array
|
||||
{
|
||||
"acceptable"sv, "contain"sv, "ghost"sv, "mark"sv, "respect"sv, "taboo"sv,
|
||||
"actually"sv, "cream"sv, "gleaming"sv, "meaty"sv, "rest"sv, "tacky"sv,
|
||||
"addition"sv, "creature"sv, "glorious"sv, "memory"sv, "rice"sv, "tank"sv,
|
||||
"adhesive"sv, "crime"sv, "gold"sv, "messy"sv, "rich"sv, "tent"sv,
|
||||
"adorable"sv, "cross"sv, "grandfather"sv, "miss"sv, "righteous"sv, "terrible"sv,
|
||||
"advise"sv, "crowded"sv, "gusty"sv, "modern"sv, "room"sv, "threatening"sv,
|
||||
"afraid"sv, "crown"sv, "haircut"sv, "morning"sv, "rotten"sv, "three"sv,
|
||||
"ancient"sv, "cure"sv, "hard-to-find"sv, "naughty"sv, "royal"sv, "ticket"sv,
|
||||
"anxious"sv, "curious"sv, "harm"sv, "neck"sv, "run"sv, "title"sv,
|
||||
"aromatic"sv, "curtain"sv, "heavy"sv, "night"sv, "satisfy"sv, "torpid"sv,
|
||||
"attempt"sv, "cycle"sv, "helpless"sv, "nondescript"sv, "scary"sv, "train"sv,
|
||||
"babies"sv, "deadpan"sv, "high-pitched"sv, "overjoyed"sv, "scatter"sv, "umbrella"sv,
|
||||
"bake"sv, "decisive"sv, "hilarious"sv, "page"sv, "scene"sv, "unadvised"sv,
|
||||
"ball"sv, "deeply"sv, "history"sv, "partner"sv, "scintillating"sv, "unbecoming"sv,
|
||||
"bat"sv, "delightful"sv, "hook"sv, "party"sv, "self"sv, "unbiased"sv,
|
||||
"behave"sv, "deserted"sv, "ignore"sv, "pause"sv, "selfish"sv, "unite"sv,
|
||||
"best"sv, "draconian"sv, "imperfect"sv, "pear"sv, "silky"sv, "uptight"sv,
|
||||
"birds"sv, "dreary"sv, "impossible"sv, "picture"sv, "sisters"sv, "used"sv,
|
||||
"blind"sv, "dull"sv, "incandescent"sv, "place"sv, "ski"sv, "vengeful"sv,
|
||||
"blood"sv, "enthusiastic"sv, "influence"sv, "playground"sv, "skip"sv, "versed"sv,
|
||||
"blue-eyed"sv, "equable"sv, "innocent"sv, "popcorn"sv, "snow"sv, "vessel"sv,
|
||||
"boiling"sv, "excuse"sv, "insidious"sv, "prefer"sv, "soap"sv, "view"sv,
|
||||
"bore"sv, "experience"sv, "itch"sv, "productive"sv, "spare"sv, "voyage"sv,
|
||||
"borrow"sv, "fabulous"sv, "jail"sv, "profuse"sv, "spicy"sv, "wall"sv,
|
||||
"broken"sv, "familiar"sv, "kindhearted"sv, "protective"sv, "spiritual"sv, "want"sv,
|
||||
"capable"sv, "finger"sv, "lackadaisical"sv, "pumped"sv, "sprout"sv, "weary"sv,
|
||||
"charming"sv, "finicky"sv, "laughable"sv, "rabbit"sv, "squirrel"sv, "week"sv,
|
||||
"cheerful"sv, "fix"sv, "leather"sv, "rapid"sv, "stale"sv, "whip"sv,
|
||||
"chubby"sv, "flagrant"sv, "legal"sv, "regret"sv, "step"sv, "wilderness"sv,
|
||||
"clean"sv, "flat"sv, "lewd"sv, "reject"sv, "stingy"sv, "wistful"sv,
|
||||
"close"sv, "flimsy"sv, "license"sv, "rejoice"sv, "string"sv, "worried"sv,
|
||||
"cobweb"sv, "fuel"sv, "light"sv, "relation"sv, "sulky"sv, "wretched"sv,
|
||||
"complex"sv, "furtive"sv, "march"sv, "remarkable"sv, "surprise"sv, "zealous"sv,
|
||||
"consist"sv, "geese"sv
|
||||
inline constexpr auto words = std::array{
|
||||
"acceptable"sv, "contain"sv, "ghost"sv, "mark"sv, "respect"sv, "taboo"sv,
|
||||
"actually"sv, "cream"sv, "gleaming"sv, "meaty"sv, "rest"sv, "tacky"sv,
|
||||
"addition"sv, "creature"sv, "glorious"sv, "memory"sv, "rice"sv, "tank"sv,
|
||||
"adhesive"sv, "crime"sv, "gold"sv, "messy"sv, "rich"sv, "tent"sv,
|
||||
"adorable"sv, "cross"sv, "grandfather"sv, "miss"sv, "righteous"sv, "terrible"sv,
|
||||
"advise"sv, "crowded"sv, "gusty"sv, "modern"sv, "room"sv, "threatening"sv,
|
||||
"afraid"sv, "crown"sv, "haircut"sv, "morning"sv, "rotten"sv, "three"sv,
|
||||
"ancient"sv, "cure"sv, "hard-to-find"sv, "naughty"sv, "royal"sv, "ticket"sv,
|
||||
"anxious"sv, "curious"sv, "harm"sv, "neck"sv, "run"sv, "title"sv,
|
||||
"aromatic"sv, "curtain"sv, "heavy"sv, "night"sv, "satisfy"sv, "torpid"sv,
|
||||
"attempt"sv, "cycle"sv, "helpless"sv, "nondescript"sv, "scary"sv, "train"sv,
|
||||
"babies"sv, "deadpan"sv, "high-pitched"sv, "overjoyed"sv, "scatter"sv, "umbrella"sv,
|
||||
"bake"sv, "decisive"sv, "hilarious"sv, "page"sv, "scene"sv, "unadvised"sv,
|
||||
"ball"sv, "deeply"sv, "history"sv, "partner"sv, "scintillating"sv, "unbecoming"sv,
|
||||
"bat"sv, "delightful"sv, "hook"sv, "party"sv, "self"sv, "unbiased"sv,
|
||||
"behave"sv, "deserted"sv, "ignore"sv, "pause"sv, "selfish"sv, "unite"sv,
|
||||
"best"sv, "draconian"sv, "imperfect"sv, "pear"sv, "silky"sv, "uptight"sv,
|
||||
"birds"sv, "dreary"sv, "impossible"sv, "picture"sv, "sisters"sv, "used"sv,
|
||||
"blind"sv, "dull"sv, "incandescent"sv, "place"sv, "ski"sv, "vengeful"sv,
|
||||
"blood"sv, "enthusiastic"sv, "influence"sv, "playground"sv, "skip"sv, "versed"sv,
|
||||
"blue-eyed"sv, "equable"sv, "innocent"sv, "popcorn"sv, "snow"sv, "vessel"sv,
|
||||
"boiling"sv, "excuse"sv, "insidious"sv, "prefer"sv, "soap"sv, "view"sv,
|
||||
"bore"sv, "experience"sv, "itch"sv, "productive"sv, "spare"sv, "voyage"sv,
|
||||
"borrow"sv, "fabulous"sv, "jail"sv, "profuse"sv, "spicy"sv, "wall"sv,
|
||||
"broken"sv, "familiar"sv, "kindhearted"sv, "protective"sv, "spiritual"sv, "want"sv,
|
||||
"capable"sv, "finger"sv, "lackadaisical"sv, "pumped"sv, "sprout"sv, "weary"sv,
|
||||
"charming"sv, "finicky"sv, "laughable"sv, "rabbit"sv, "squirrel"sv, "week"sv,
|
||||
"cheerful"sv, "fix"sv, "leather"sv, "rapid"sv, "stale"sv, "whip"sv,
|
||||
"chubby"sv, "flagrant"sv, "legal"sv, "regret"sv, "step"sv, "wilderness"sv,
|
||||
"clean"sv, "flat"sv, "lewd"sv, "reject"sv, "stingy"sv, "wistful"sv,
|
||||
"close"sv, "flimsy"sv, "license"sv, "rejoice"sv, "string"sv, "worried"sv,
|
||||
"cobweb"sv, "fuel"sv, "light"sv, "relation"sv, "sulky"sv, "wretched"sv,
|
||||
"complex"sv, "furtive"sv, "march"sv, "remarkable"sv, "surprise"sv, "zealous"sv,
|
||||
"consist"sv, "geese"sv
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
static T rand(T excl_max) noexcept
|
||||
[[nodiscard]] static T rand(T excl_max) noexcept
|
||||
{
|
||||
return static_cast<T>(static_cast<T>(std::rand()) % excl_max);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
static T rand(T incl_min, T excl_max) noexcept
|
||||
[[nodiscard]] static T rand(T incl_min, T excl_max) noexcept
|
||||
{
|
||||
return static_cast<T>(incl_min + rand(excl_max - incl_min));
|
||||
}
|
||||
|
||||
static auto rand_date() noexcept
|
||||
{
|
||||
return toml::date
|
||||
{
|
||||
rand(uint16_t{ 1900 }, uint16_t{ 2021 }),
|
||||
rand(uint8_t{ 1 }, uint8_t{ 13 }),
|
||||
rand(uint8_t{ 1 }, uint8_t{ 29 })
|
||||
};
|
||||
return toml::date{ rand(uint16_t{ 1900 }, uint16_t{ 2021 }),
|
||||
rand(uint8_t{ 1 }, uint8_t{ 13 }),
|
||||
rand(uint8_t{ 1 }, uint8_t{ 29 }) };
|
||||
}
|
||||
|
||||
static auto rand_time() noexcept
|
||||
{
|
||||
return toml::time
|
||||
{
|
||||
rand(uint8_t{ 24 }),
|
||||
rand(uint8_t{ 60 }),
|
||||
rand(uint8_t{ 60 }),
|
||||
rand(100) > 80 ? rand(1000000000u) : 0u
|
||||
};
|
||||
return toml::time{ rand(uint8_t{ 24 }),
|
||||
rand(uint8_t{ 60 }),
|
||||
rand(uint8_t{ 60 }),
|
||||
rand(100) > 80 ? rand(1000000000u) : 0u };
|
||||
}
|
||||
|
||||
static auto rand_string(size_t word_count, char sep = ' ') noexcept
|
||||
@ -102,8 +93,6 @@ namespace
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
examples::init();
|
||||
|
||||
int node_budget{};
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
@ -119,14 +108,14 @@ int main(int argc, char** argv)
|
||||
std::vector<toml::node*> tree;
|
||||
tree.push_back(&root);
|
||||
constexpr size_t max_depth = 10u;
|
||||
int container_min_values = 10;
|
||||
bool in_arr = false;
|
||||
int container_min_values = 10;
|
||||
bool in_arr = false;
|
||||
|
||||
const auto add = [&](auto&& val) noexcept -> auto&
|
||||
{
|
||||
using value_ref = decltype(val);
|
||||
using value_ref = decltype(val);
|
||||
using value_type = std::remove_reference_t<value_ref>;
|
||||
using node_type = toml::inserted_type_of<value_type>;
|
||||
using node_type = toml::inserted_type_of<value_type>;
|
||||
|
||||
toml::node* new_node{};
|
||||
|
||||
@ -142,10 +131,8 @@ int main(int argc, char** argv)
|
||||
{
|
||||
auto& table = tree.back()->ref<toml::table>();
|
||||
|
||||
const auto it = table.insert_or_assign(
|
||||
rand_string(rand<size_t>(1u, 4u), '-'),
|
||||
std::forward<value_ref>(val)
|
||||
);
|
||||
const auto it =
|
||||
table.insert_or_assign(rand_string(rand<size_t>(1u, 4u), '-'), std::forward<value_ref>(val));
|
||||
|
||||
new_node = &it.first->second;
|
||||
}
|
||||
@ -155,7 +142,7 @@ int main(int argc, char** argv)
|
||||
{
|
||||
tree.push_back(new_node);
|
||||
container_min_values = rand(1, 4);
|
||||
in_arr = toml::is_array<value_type>;
|
||||
in_arr = toml::is_array<value_type>;
|
||||
if constexpr (toml::is_array<value_type>)
|
||||
tree.back()->as_array()->reserve(static_cast<size_t>(container_min_values));
|
||||
}
|
||||
@ -183,41 +170,30 @@ int main(int argc, char** argv)
|
||||
|
||||
switch (new_node_type)
|
||||
{
|
||||
case toml::node_type::array:
|
||||
if (container_min_values <= 0 && tree.size() < max_depth)
|
||||
add(toml::array{});
|
||||
break;
|
||||
case toml::node_type::array:
|
||||
if (container_min_values <= 0 && tree.size() < max_depth)
|
||||
add(toml::array{});
|
||||
break;
|
||||
|
||||
case toml::node_type::string:
|
||||
add(rand_string(rand<size_t>(8u)));
|
||||
break;
|
||||
case toml::node_type::string: add(rand_string(rand<size_t>(8u))); break;
|
||||
|
||||
case toml::node_type::integer:
|
||||
add(rand());
|
||||
break;
|
||||
case toml::node_type::integer: add(rand()); break;
|
||||
|
||||
case toml::node_type::floating_point:
|
||||
add(rand(10001u) / 10000.0);
|
||||
break;
|
||||
case toml::node_type::floating_point: add(rand(10001u) / 10000.0); break;
|
||||
|
||||
case toml::node_type::boolean:
|
||||
add(!rand(2u));
|
||||
break;
|
||||
case toml::node_type::boolean: add(!rand(2u)); break;
|
||||
|
||||
case toml::node_type::date:
|
||||
add(rand_date());
|
||||
break;
|
||||
case toml::node_type::date: add(rand_date()); break;
|
||||
|
||||
case toml::node_type::time:
|
||||
add(rand_time());
|
||||
break;
|
||||
case toml::node_type::time: add(rand_time()); break;
|
||||
|
||||
case toml::node_type::date_time:
|
||||
add(rand(100) >= 75
|
||||
? toml::date_time{ rand_date(), rand_time() }
|
||||
: toml::date_time{ rand_date(), rand_time(), toml::time_offset{ rand<int8_t>(-11, 12), rand<int8_t>(-45, +46) } }
|
||||
);
|
||||
break;
|
||||
case toml::node_type::date_time:
|
||||
add(rand(100) >= 75
|
||||
? toml::date_time{ rand_date(), rand_time() }
|
||||
: toml::date_time{ rand_date(),
|
||||
rand_time(),
|
||||
toml::time_offset{ rand<int8_t>(-11, 12), rand<int8_t>(-45, +46) } });
|
||||
break;
|
||||
}
|
||||
if (container_min_values <= 0 && tree.size() >= 2u && rand(100) >= 85)
|
||||
{
|
||||
|
@ -20,13 +20,13 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
@ -7,28 +7,25 @@
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
#define TOML_UNRELEASED_FEATURES 1
|
||||
#define TOML_ENABLE_UNRELEASED_FEATURES 1
|
||||
#include <toml++/toml.h>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
examples::init();
|
||||
const auto path = argc > 1 ? std::string_view{ argv[1] } : ""sv;
|
||||
|
||||
toml::table table;
|
||||
try
|
||||
{
|
||||
|
||||
// read from a file if a path argument is given
|
||||
if (argc > 1)
|
||||
table = toml::parse_file(argv[1]);
|
||||
|
||||
// otherwise read directly from stdin
|
||||
else
|
||||
// read directly from stdin
|
||||
if (path == "-"sv || path.empty())
|
||||
table = toml::parse(std::cin, "stdin"sv);
|
||||
|
||||
std::cout << toml::json_formatter{ table } << "\n";
|
||||
// read from a file
|
||||
else
|
||||
table = toml::parse_file(argv[1]);
|
||||
}
|
||||
catch (const toml::parse_error& err)
|
||||
{
|
||||
|
@ -20,13 +20,13 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
1
external/json
vendored
Submodule
1
external/json
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit cc59ab122f75448c17ac623d10306cbe19cde970
|
2
external/toml-test
vendored
2
external/toml-test
vendored
@ -1 +1 @@
|
||||
Subproject commit f2f2280c83f74212860fe0f12ee84581836c066c
|
||||
Subproject commit 442dea55c5173bc89c2afa1b023ecbf0e042ceac
|
File diff suppressed because it is too large
Load Diff
362
include/toml++/impl/array.inl
Normal file
362
include/toml++/impl/array.inl
Normal file
@ -0,0 +1,362 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "array.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(const impl::array_init_elem* b, const impl::array_init_elem* e)
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#endif
|
||||
|
||||
TOML_ASSERT_ASSUME(b);
|
||||
TOML_ASSERT_ASSUME(e);
|
||||
TOML_ASSERT_ASSUME(b <= e);
|
||||
|
||||
if TOML_UNLIKELY(b == e)
|
||||
return;
|
||||
|
||||
size_t cap{};
|
||||
for (auto it = b; it != e; it++)
|
||||
{
|
||||
if (it->value)
|
||||
cap++;
|
||||
}
|
||||
if TOML_UNLIKELY(!cap)
|
||||
return;
|
||||
|
||||
elems_.reserve(cap);
|
||||
for (; b != e; b++)
|
||||
{
|
||||
if (b->value)
|
||||
elems_.push_back(std::move(b->value));
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(const array& other) //
|
||||
: node(other)
|
||||
{
|
||||
elems_.reserve(other.elems_.size());
|
||||
for (const auto& elem : other)
|
||||
elems_.emplace_back(impl::make_node(elem));
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array && other) noexcept //
|
||||
: node(std::move(other)),
|
||||
elems_(std::move(other.elems_))
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator=(const array& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(rhs);
|
||||
elems_.clear();
|
||||
elems_.reserve(rhs.elems_.size());
|
||||
for (const auto& elem : rhs)
|
||||
elems_.emplace_back(impl::make_node(elem));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator=(array&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
elems_ = std::move(rhs.elems_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::preinsertion_resize(size_t idx, size_t count)
|
||||
{
|
||||
TOML_ASSERT(idx <= elems_.size());
|
||||
TOML_ASSERT_ASSUME(count >= 1u);
|
||||
const auto old_size = elems_.size();
|
||||
const auto new_size = old_size + count;
|
||||
const auto inserting_at_end = idx == old_size;
|
||||
elems_.resize(new_size);
|
||||
if (!inserting_at_end)
|
||||
{
|
||||
for (size_t left = old_size, right = new_size - 1u; left-- > idx; right--)
|
||||
elems_[right] = std::move(elems_[left]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::insert_at_back(impl::node_ptr && elem)
|
||||
{
|
||||
elems_.push_back(std::move(elem));
|
||||
}
|
||||
|
||||
TOML_API
|
||||
array::vector_iterator array::insert_at(const_vector_iterator pos, impl::node_ptr && elem)
|
||||
{
|
||||
return elems_.insert(pos, std::move(elem));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type ntype) const noexcept
|
||||
{
|
||||
if (elems_.empty())
|
||||
return false;
|
||||
|
||||
if (ntype == node_type::none)
|
||||
ntype = elems_[0]->type();
|
||||
|
||||
for (const auto& val : elems_)
|
||||
if (val->type() != ntype)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type ntype, node * &first_nonmatch) noexcept
|
||||
{
|
||||
if (elems_.empty())
|
||||
{
|
||||
first_nonmatch = {};
|
||||
return false;
|
||||
}
|
||||
if (ntype == node_type::none)
|
||||
ntype = elems_[0]->type();
|
||||
for (const auto& val : elems_)
|
||||
{
|
||||
if (val->type() != ntype)
|
||||
{
|
||||
first_nonmatch = val.get();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept
|
||||
{
|
||||
node* fnm = nullptr;
|
||||
const auto result = const_cast<array&>(*this).is_homogeneous(ntype, fnm);
|
||||
first_nonmatch = fnm;
|
||||
return result;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node& array::at(size_t index)
|
||||
{
|
||||
#if TOML_COMPILER_EXCEPTIONS
|
||||
|
||||
return *elems_.at(index);
|
||||
|
||||
#else
|
||||
|
||||
auto n = get(index);
|
||||
TOML_ASSERT_ASSUME(n && "element index not found in array!");
|
||||
return *n;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::reserve(size_t new_capacity)
|
||||
{
|
||||
elems_.reserve(new_capacity);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::shrink_to_fit()
|
||||
{
|
||||
elems_.shrink_to_fit();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::truncate(size_t new_size)
|
||||
{
|
||||
if (new_size < elems_.size())
|
||||
elems_.resize(new_size);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator pos) noexcept
|
||||
{
|
||||
return iterator{ elems_.erase(const_vector_iterator{ pos }) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return iterator{ elems_.erase(const_vector_iterator{ first }, const_vector_iterator{ last }) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
size_t array::total_leaf_count() const noexcept
|
||||
{
|
||||
size_t leaves{};
|
||||
for (size_t i = 0, e = elems_.size(); i < e; i++)
|
||||
{
|
||||
auto arr = elems_[i]->as_array();
|
||||
leaves += arr ? arr->total_leaf_count() : size_t{ 1 };
|
||||
}
|
||||
return leaves;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::flatten_child(array && child, size_t & dest_index) noexcept
|
||||
{
|
||||
for (size_t i = 0, e = child.size(); i < e; i++)
|
||||
{
|
||||
auto type = child.elems_[i]->type();
|
||||
if (type == node_type::array)
|
||||
{
|
||||
array& arr = *reinterpret_cast<array*>(child.elems_[i].get());
|
||||
if (!arr.empty())
|
||||
flatten_child(std::move(arr), dest_index);
|
||||
}
|
||||
else
|
||||
elems_[dest_index++] = std::move(child.elems_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::flatten()&
|
||||
{
|
||||
if (elems_.empty())
|
||||
return *this;
|
||||
|
||||
bool requires_flattening = false;
|
||||
size_t size_after_flattening = elems_.size();
|
||||
for (size_t i = elems_.size(); i-- > 0u;)
|
||||
{
|
||||
auto arr = elems_[i]->as_array();
|
||||
if (!arr)
|
||||
continue;
|
||||
size_after_flattening--; // discount the array itself
|
||||
const auto leaf_count = arr->total_leaf_count();
|
||||
if (leaf_count > 0u)
|
||||
{
|
||||
requires_flattening = true;
|
||||
size_after_flattening += leaf_count;
|
||||
}
|
||||
else
|
||||
elems_.erase(elems_.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
}
|
||||
|
||||
if (!requires_flattening)
|
||||
return *this;
|
||||
|
||||
elems_.reserve(size_after_flattening);
|
||||
|
||||
size_t i = 0;
|
||||
while (i < elems_.size())
|
||||
{
|
||||
auto arr = elems_[i]->as_array();
|
||||
if (!arr)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
impl::node_ptr arr_storage = std::move(elems_[i]);
|
||||
const auto leaf_count = arr->total_leaf_count();
|
||||
if (leaf_count > 1u)
|
||||
preinsertion_resize(i + 1u, leaf_count - 1u);
|
||||
flatten_child(std::move(*arr), i); // increments i
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::prune(bool recursive)& noexcept
|
||||
{
|
||||
if (elems_.empty())
|
||||
return *this;
|
||||
|
||||
for (size_t i = elems_.size(); i-- > 0u;)
|
||||
{
|
||||
if (auto arr = elems_[i]->as_array())
|
||||
{
|
||||
if (recursive)
|
||||
arr->prune(true);
|
||||
if (arr->empty())
|
||||
elems_.erase(elems_.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
}
|
||||
else if (auto tbl = elems_[i]->as_table())
|
||||
{
|
||||
if (recursive)
|
||||
tbl->prune(true);
|
||||
if (tbl->empty())
|
||||
elems_.erase(elems_.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::pop_back() noexcept
|
||||
{
|
||||
elems_.pop_back();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::clear() noexcept
|
||||
{
|
||||
elems_.clear();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::equal(const array& lhs, const array& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.elems_.size() != rhs.elems_.size())
|
||||
return false;
|
||||
for (size_t i = 0, e = lhs.elems_.size(); i < e; i++)
|
||||
{
|
||||
const auto lhs_type = lhs.elems_[i]->type();
|
||||
const node& rhs_ = *rhs.elems_[i];
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = lhs.elems_[i]->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
@ -1,283 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "array.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array() noexcept
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(const array& other) noexcept //
|
||||
: node(other)
|
||||
{
|
||||
elements.reserve(other.elements.size());
|
||||
for (const auto& elem : other)
|
||||
elements.emplace_back(impl::make_node(elem));
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array && other) noexcept //
|
||||
: node(std::move(other)),
|
||||
elements{ std::move(other.elements) }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator=(const array& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(rhs);
|
||||
elements.clear();
|
||||
elements.reserve(rhs.elements.size());
|
||||
for (const auto& elem : rhs)
|
||||
elements.emplace_back(impl::make_node(elem));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator=(array&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
elements = std::move(rhs.elements);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::preinsertion_resize(size_t idx, size_t count) noexcept
|
||||
{
|
||||
TOML_ASSERT(idx <= elements.size());
|
||||
TOML_ASSERT(count >= 1_sz);
|
||||
const auto old_size = elements.size();
|
||||
const auto new_size = old_size + count;
|
||||
const auto inserting_at_end = idx == old_size;
|
||||
elements.resize(new_size);
|
||||
if (!inserting_at_end)
|
||||
{
|
||||
for (size_t left = old_size, right = new_size - 1_sz; left-- > idx; right--)
|
||||
elements[right] = std::move(elements[left]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
const node& array::operator[](size_t index) const noexcept
|
||||
{
|
||||
return *elements[index];
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
node& array::operator[](size_t index) noexcept
|
||||
{
|
||||
return *elements[index];
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type ntype) const noexcept
|
||||
{
|
||||
if (elements.empty())
|
||||
return false;
|
||||
|
||||
if (ntype == node_type::none)
|
||||
ntype = elements[0]->type();
|
||||
|
||||
for (const auto& val : elements)
|
||||
if (val->type() != ntype)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template <typename T, typename U>
|
||||
TOML_INTERNAL_LINKAGE
|
||||
bool array_is_homogeneous(T& elements, node_type ntype, U& first_nonmatch) noexcept
|
||||
{
|
||||
if (elements.empty())
|
||||
{
|
||||
first_nonmatch = {};
|
||||
return false;
|
||||
}
|
||||
if (ntype == node_type::none)
|
||||
ntype = elements[0]->type();
|
||||
for (const auto& val : elements)
|
||||
{
|
||||
if (val->type() != ntype)
|
||||
{
|
||||
first_nonmatch = val.get();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type ntype, toml::node * &first_nonmatch) noexcept
|
||||
{
|
||||
return impl::array_is_homogeneous(elements, ntype, first_nonmatch);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type ntype, const toml::node*& first_nonmatch) const noexcept
|
||||
{
|
||||
return impl::array_is_homogeneous(elements, ntype, first_nonmatch);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
node* array::get(size_t index) noexcept
|
||||
{
|
||||
return index < elements.size() ? elements[index].get() : nullptr;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
const node* array::get(size_t index) const noexcept
|
||||
{
|
||||
return index < elements.size() ? elements[index].get() : nullptr;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator==(const array& lhs, const array& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.elements.size() != rhs.elements.size())
|
||||
return false;
|
||||
for (size_t i = 0, e = lhs.elements.size(); i < e; i++)
|
||||
{
|
||||
const auto lhs_type = lhs.elements[i]->type();
|
||||
const node& rhs_ = *rhs.elements[i];
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = lhs.elements[i]->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator!=(const array& lhs, const array& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
size_t array::total_leaf_count() const noexcept
|
||||
{
|
||||
size_t leaves{};
|
||||
for (size_t i = 0, e = elements.size(); i < e; i++)
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
leaves += arr ? arr->total_leaf_count() : 1_sz;
|
||||
}
|
||||
return leaves;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::flatten_child(array && child, size_t & dest_index) noexcept
|
||||
{
|
||||
for (size_t i = 0, e = child.size(); i < e; i++)
|
||||
{
|
||||
auto type = child.elements[i]->type();
|
||||
if (type == node_type::array)
|
||||
{
|
||||
array& arr = *reinterpret_cast<array*>(child.elements[i].get());
|
||||
if (!arr.empty())
|
||||
flatten_child(std::move(arr), dest_index);
|
||||
}
|
||||
else
|
||||
elements[dest_index++] = std::move(child.elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::flatten()&
|
||||
{
|
||||
if (elements.empty())
|
||||
return *this;
|
||||
|
||||
bool requires_flattening = false;
|
||||
size_t size_after_flattening = elements.size();
|
||||
for (size_t i = elements.size(); i-- > 0_sz;)
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
continue;
|
||||
size_after_flattening--; // discount the array itself
|
||||
const auto leaf_count = arr->total_leaf_count();
|
||||
if (leaf_count > 0_sz)
|
||||
{
|
||||
requires_flattening = true;
|
||||
size_after_flattening += leaf_count;
|
||||
}
|
||||
else
|
||||
elements.erase(elements.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
}
|
||||
|
||||
if (!requires_flattening)
|
||||
return *this;
|
||||
|
||||
elements.reserve(size_after_flattening);
|
||||
|
||||
size_t i = 0;
|
||||
while (i < elements.size())
|
||||
{
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<node> arr_storage = std::move(elements[i]);
|
||||
const auto leaf_count = arr->total_leaf_count();
|
||||
if (leaf_count > 1_sz)
|
||||
preinsertion_resize(i + 1_sz, leaf_count - 1_sz);
|
||||
flatten_child(std::move(*arr), i); // increments i
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
/// \endcond
|
82
include/toml++/impl/at_path.h
Normal file
82
include/toml++/impl/at_path.h
Normal file
@ -0,0 +1,82 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "forward_declarations.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief Returns a view of the node matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto config = R"(
|
||||
///
|
||||
/// [foo]
|
||||
/// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ]
|
||||
///
|
||||
/// )"_toml;
|
||||
///
|
||||
/// std::cout << toml::at_path(config, "foo.bar[2]") << "\n";
|
||||
/// std::cout << toml::at_path(config, "foo.bar[3][0]") << "\n";
|
||||
/// std::cout << toml::at_path(config, "foo.bar[4].kek") << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 2
|
||||
/// 3
|
||||
/// 4
|
||||
/// \eout
|
||||
///
|
||||
///
|
||||
/// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters:
|
||||
/// \cpp
|
||||
/// toml::at_path(config, "foo.bar") // same as config["foo"]["bar"]
|
||||
/// toml::at_path(config, "foo. bar") // same as config["foo"][" bar"]
|
||||
/// toml::at_path(config, "foo..bar") // same as config["foo"][""]["bar"]
|
||||
/// toml::at_path(config, ".foo.bar") // same as config[""]["foo"]["bar"]
|
||||
/// \ecpp
|
||||
/// <br>
|
||||
/// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings.
|
||||
/// This function makes no allowance for this, instead treating all period characters as sub-table delimiters.
|
||||
/// If you have periods in your table keys, first consider:
|
||||
/// 1. Not doing that
|
||||
/// 2. Using node_view::operator[] instead.
|
||||
///
|
||||
/// \param root The root node from which the path will be traversed.
|
||||
/// \param path The "TOML path" to traverse.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<node> at_path(node & root, std::string_view path) noexcept;
|
||||
|
||||
/// \brief Returns a const view of the node matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<const node> at_path(const node& root, std::string_view path) noexcept;
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns a view of the node matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<node> at_path(node & root, std::wstring_view path);
|
||||
|
||||
/// \brief Returns a const view of the node matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<const node> at_path(const node& root, std::wstring_view path);
|
||||
|
||||
#endif
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
228
include/toml++/impl/at_path.inl
Normal file
228
include/toml++/impl/at_path.inl
Normal file
@ -0,0 +1,228 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "at_path.h"
|
||||
#include "array.h"
|
||||
#include "table.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#if TOML_INT_CHARCONV
|
||||
#include <charconv>
|
||||
#else
|
||||
#include <sstream>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_ANON_NAMESPACE_START
|
||||
{
|
||||
TOML_INTERNAL_LINKAGE
|
||||
node* get_at_path(node & root, std::string_view path) noexcept
|
||||
{
|
||||
if (root.is_value()) // values don't have child nodes
|
||||
return nullptr;
|
||||
|
||||
size_t pos = 0;
|
||||
const auto end = path.length();
|
||||
node* current = &root;
|
||||
bool prev_was_array_indexer = false;
|
||||
bool prev_was_dot = root.is_table(); // implicit '.' at the start for tables
|
||||
|
||||
do
|
||||
{
|
||||
// start of an array indexer
|
||||
if (path[pos] == '[')
|
||||
{
|
||||
const auto current_array = current->as<array>();
|
||||
if (!current_array)
|
||||
return nullptr;
|
||||
|
||||
// get array index substring
|
||||
const auto index_start = pos + 1u; // first position after '['
|
||||
const auto index_end = path.find(']', index_start); // position of ']'
|
||||
if (index_end == std::string_view::npos || index_end == index_start)
|
||||
return nullptr;
|
||||
auto index_str = path.substr(index_start, index_end - index_start);
|
||||
|
||||
// trim whitespace from either side of the index
|
||||
const auto first_non_ws = index_str.find_first_not_of(" \t"sv);
|
||||
const auto last_non_ws = index_str.find_last_not_of(" \t"sv);
|
||||
if (first_non_ws == std::string_view::npos)
|
||||
return nullptr;
|
||||
TOML_ASSERT_ASSUME(last_non_ws != std::string_view::npos);
|
||||
index_str = index_str.substr(first_non_ws, (last_non_ws - first_non_ws) + 1u);
|
||||
|
||||
// parse the actual array index
|
||||
size_t index;
|
||||
if (index_str.length() == 1u && index_str[0] >= '0' && index_str[0] <= '9')
|
||||
index = static_cast<size_t>(index_str[0] - '0');
|
||||
else
|
||||
{
|
||||
#if TOML_INT_CHARCONV
|
||||
|
||||
auto fc_result = std::from_chars(index_str.data(), index_str.data() + index_str.length(), index);
|
||||
if (fc_result.ec != std::errc{})
|
||||
return nullptr;
|
||||
|
||||
#else
|
||||
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss.write(index_str.data(), static_cast<std::streamsize>(index_str.length()));
|
||||
if (!(ss >> index))
|
||||
return nullptr;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
current = current_array->get(index);
|
||||
pos = index_end + 1u;
|
||||
prev_was_dot = false;
|
||||
prev_was_array_indexer = true;
|
||||
}
|
||||
|
||||
// start of a new table child
|
||||
else if (path[pos] == '.')
|
||||
{
|
||||
const auto current_table = current->as<table>();
|
||||
if (!current_table)
|
||||
return nullptr;
|
||||
|
||||
// a dot immediately following another dot (or at the beginning of the string) is as if we'd asked
|
||||
// for an empty child in between, e.g.
|
||||
//
|
||||
// foo..bar
|
||||
//
|
||||
// is equivalent to
|
||||
//
|
||||
// "foo".""."bar"
|
||||
//
|
||||
if (prev_was_dot)
|
||||
current = current_table->get(""sv);
|
||||
|
||||
pos++;
|
||||
prev_was_dot = true;
|
||||
prev_was_array_indexer = false;
|
||||
}
|
||||
|
||||
// some regular subkey
|
||||
else
|
||||
{
|
||||
// get subkey text
|
||||
const auto subkey_start = pos;
|
||||
const auto subkey_len =
|
||||
impl::min(path.find_first_of(".["sv, subkey_start + 1u), path.length()) - subkey_start;
|
||||
const auto subkey = path.substr(subkey_start, subkey_len);
|
||||
|
||||
// a regular subkey segment immediately after an array indexer is OK if it was all whitespace, e.g.:
|
||||
//
|
||||
// "foo[0] .bar"
|
||||
// ^^ skip this
|
||||
//
|
||||
// otherwise its an error (since it would have to be preceeded by a dot)
|
||||
if (prev_was_array_indexer)
|
||||
{
|
||||
auto non_ws = subkey.find_first_not_of(" \t");
|
||||
if (non_ws == std::string_view::npos)
|
||||
{
|
||||
pos += subkey_len;
|
||||
prev_was_dot = false;
|
||||
prev_was_array_indexer = false;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto current_table = current->as<table>();
|
||||
if (!current_table)
|
||||
return nullptr;
|
||||
|
||||
current = current_table->get(subkey);
|
||||
pos += subkey_len;
|
||||
prev_was_dot = false;
|
||||
prev_was_array_indexer = false;
|
||||
}
|
||||
}
|
||||
while (pos < end && current);
|
||||
|
||||
// a dot at the end is as if we'd asked for an empty child at the end, e.g.
|
||||
//
|
||||
// foo.bar.
|
||||
//
|
||||
// is equivalent to
|
||||
//
|
||||
// "foo"."bar".""
|
||||
//
|
||||
if (current && prev_was_dot)
|
||||
{
|
||||
const auto current_table = current->as<table>();
|
||||
if (!current_table)
|
||||
return nullptr;
|
||||
|
||||
current = current_table->get(""sv);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_INTERNAL_LINKAGE
|
||||
node* get_at_path(node & root, std::wstring_view path) noexcept
|
||||
{
|
||||
if (auto tbl = root.as_table(); tbl && tbl->empty())
|
||||
return {};
|
||||
if (auto arr = root.as_array(); arr && arr->empty())
|
||||
return {};
|
||||
|
||||
return get_at_path(root, impl::narrow(path));
|
||||
}
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
}
|
||||
|
||||
TOML_ANON_NAMESPACE_END;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<node> at_path(node & root, std::string_view path) noexcept
|
||||
{
|
||||
return node_view<node>{ TOML_ANON_NAMESPACE::get_at_path(root, path) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<const node> at_path(const node& root, std::string_view path) noexcept
|
||||
{
|
||||
return node_view<const node>{ TOML_ANON_NAMESPACE::get_at_path(const_cast<node&>(root), path) };
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<node> at_path(node & root, std::wstring_view path)
|
||||
{
|
||||
return node_view<node>{ TOML_ANON_NAMESPACE::get_at_path(root, path) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<const node> at_path(const node& root, std::wstring_view path)
|
||||
{
|
||||
return node_view<const node>{ TOML_ANON_NAMESPACE::get_at_path(const_cast<node&>(root), path) };
|
||||
}
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
@ -2,9 +2,11 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
#include "forward_declarations.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
@ -13,98 +15,132 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief The year component.
|
||||
uint16_t year;
|
||||
|
||||
/// \brief The month component, from 1 - 12.
|
||||
uint8_t month;
|
||||
|
||||
/// \brief The day component, from 1 - 31.
|
||||
uint8_t day;
|
||||
|
||||
/// \brief Default constructor. Does not initialize the members.
|
||||
TOML_NODISCARD_CTOR
|
||||
date() noexcept = default;
|
||||
|
||||
/// \brief Constructs a date from individual date component values.
|
||||
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<Y, M, D>), typename Y, typename M, typename D)
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr date(Y y, M m, D d) noexcept //
|
||||
: year{ static_cast<uint16_t>(y) },
|
||||
month{ static_cast<uint8_t>(m) },
|
||||
day{ static_cast<uint8_t>(d) }
|
||||
{}
|
||||
|
||||
/// \brief Equality operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator==(date lhs, date rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator==(const date& lhs, const date& rhs) noexcept
|
||||
{
|
||||
return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day;
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator!=(date lhs, date rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator!=(const date& lhs, const date& rhs) noexcept
|
||||
{
|
||||
return lhs.year != rhs.year || lhs.month != rhs.month || lhs.day != rhs.day;
|
||||
}
|
||||
|
||||
private:
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
/// \cond
|
||||
|
||||
TOML_PURE_GETTER
|
||||
static constexpr uint32_t pack(const date& d) noexcept
|
||||
{
|
||||
return (static_cast<uint32_t>(d.year) << 16) | (static_cast<uint32_t>(d.month) << 8)
|
||||
| static_cast<uint32_t>(d.day);
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief Less-than operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<(date lhs, date rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator<(const date& lhs, const date& rhs) noexcept
|
||||
{
|
||||
return pack(lhs) < pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<=(date lhs, date rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator<=(const date& lhs, const date& rhs) noexcept
|
||||
{
|
||||
return pack(lhs) <= pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>(date lhs, date rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator>(const date& lhs, const date& rhs) noexcept
|
||||
{
|
||||
return pack(lhs) > pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>=(date lhs, date rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator>=(const date& lhs, const date& rhs) noexcept
|
||||
{
|
||||
return pack(lhs) >= pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Prints a date out to a stream as `YYYY-MM-DD` (per RFC 3339).
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::date{ 1987, 3, 16 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 1987-03-16
|
||||
/// \eout
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const date& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Prints a date out to a stream as `YYYY-MM-DD` (per RFC 3339).
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::date{ 1987, 3, 16 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 1987-03-16
|
||||
/// \eout
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const date& rhs)
|
||||
{
|
||||
impl::print_to_stream(rhs, lhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const date&);
|
||||
#endif
|
||||
|
||||
/// \brief A local time-of-day.
|
||||
struct TOML_TRIVIAL_ABI time
|
||||
{
|
||||
/// \brief The hour component, from 0 - 23.
|
||||
uint8_t hour;
|
||||
|
||||
/// \brief The minute component, from 0 - 59.
|
||||
uint8_t minute;
|
||||
|
||||
/// \brief The second component, from 0 - 59.
|
||||
uint8_t second;
|
||||
|
||||
/// \brief The fractional nanoseconds component, from 0 - 999999999.
|
||||
uint32_t nanosecond;
|
||||
|
||||
/// \brief Default constructor. Does not initialize the members.
|
||||
TOML_NODISCARD_CTOR
|
||||
time() noexcept = default;
|
||||
|
||||
/// \brief Constructs a time from individual time component values.
|
||||
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M, S, NS>),
|
||||
typename H,
|
||||
typename M,
|
||||
typename S = uint8_t,
|
||||
typename NS = uint32_t)
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr time(H h, M m, S s = S{}, NS ns = NS{}) noexcept //
|
||||
: hour{ static_cast<uint8_t>(h) },
|
||||
minute{ static_cast<uint8_t>(m) },
|
||||
second{ static_cast<uint8_t>(s) },
|
||||
nanosecond{ static_cast<uint32_t>(ns) }
|
||||
{}
|
||||
|
||||
/// \brief Equality operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator==(const time& lhs, const time& rhs) noexcept
|
||||
{
|
||||
return lhs.hour == rhs.hour && lhs.minute == rhs.minute && lhs.second == rhs.second
|
||||
@ -112,93 +148,87 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator!=(const time& lhs, const time& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
static constexpr uint64_t pack(time t) noexcept
|
||||
/// \cond
|
||||
|
||||
TOML_PURE_GETTER
|
||||
static constexpr uint64_t pack(const time& t) noexcept
|
||||
{
|
||||
return static_cast<uint64_t>(t.hour) << 48 | static_cast<uint64_t>(t.minute) << 40
|
||||
| static_cast<uint64_t>(t.second) << 32 | static_cast<uint64_t>(t.nanosecond);
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief Less-than operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<(time lhs, time rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator<(const time& lhs, const time& rhs) noexcept
|
||||
{
|
||||
return pack(lhs) < pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<=(time lhs, time rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator<=(const time& lhs, const time& rhs) noexcept
|
||||
{
|
||||
return pack(lhs) <= pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>(time lhs, time rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator>(const time& lhs, const time& rhs) noexcept
|
||||
{
|
||||
return pack(lhs) > pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator>=(time lhs, time rhs) noexcept
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator>=(const time& lhs, const time& rhs) noexcept
|
||||
{
|
||||
return pack(lhs) >= pack(rhs);
|
||||
}
|
||||
|
||||
/// \brief Prints a time out to a stream as `HH:MM:SS.FFFFFF` (per RFC 3339).
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::time{ 10, 20, 34 } << "\n";
|
||||
/// std::cout << toml::time{ 10, 20, 34, 500000000 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 10:20:34
|
||||
/// 10:20:34.5
|
||||
/// \eout
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const time& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Prints a time out to a stream as `HH:MM:SS.FFFFFF` (per RFC 3339).
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::time{ 10, 20, 34 } << "\n";
|
||||
/// std::cout << toml::time{ 10, 20, 34, 500000000 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 10:20:34
|
||||
/// 10:20:34.5
|
||||
/// \eout
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const time& rhs)
|
||||
{
|
||||
impl::print_to_stream(rhs, lhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const time&);
|
||||
#endif
|
||||
|
||||
/// \brief A timezone offset.
|
||||
struct TOML_TRIVIAL_ABI time_offset
|
||||
{
|
||||
/// \brief Offset from UTC+0, in minutes.
|
||||
int16_t minutes;
|
||||
|
||||
/// \brief Default-constructs a zero time-offset.
|
||||
/// \brief Default constructor. Does not initialize the members.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr time_offset() noexcept //
|
||||
: minutes{}
|
||||
{}
|
||||
time_offset() noexcept = default;
|
||||
|
||||
/// \brief Constructs a timezone offset from separate hour and minute totals.
|
||||
/// \brief Constructs a timezone offset from individual hour and minute totals.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::time_offset{ 2, 30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ -2, 30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ -2, -30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ 0, 0 } << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -208,84 +238,84 @@ TOML_NAMESPACE_START
|
||||
/// Z
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam H An integral type.
|
||||
/// \tparam M An integral type.
|
||||
///
|
||||
/// \param h The total hours.
|
||||
/// \param m The total minutes.
|
||||
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M>), typename H, typename M)
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr time_offset(int8_t h, int8_t m) noexcept //
|
||||
: minutes{ static_cast<int16_t>(h * 60 + m) }
|
||||
constexpr time_offset(H h, M m) noexcept //
|
||||
: minutes{ static_cast<int16_t>(static_cast<impl::common_signed_type<H, M>>(h)
|
||||
* impl::common_signed_type<H, M>{ 60 }
|
||||
+ static_cast<impl::common_signed_type<H, M>>(m)) }
|
||||
{}
|
||||
|
||||
/// \brief Equality operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator==(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes == rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator!=(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes != rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Less-than operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator<(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes < rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator<=(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes <= rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator>(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes > rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator>=(time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.minutes >= rhs.minutes;
|
||||
}
|
||||
|
||||
/// \brief Prints a time_offset out to a stream as `+-HH:MM or Z` (per RFC 3339).
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::time_offset{ 2, 30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ 2, -30 } << "\n";
|
||||
/// std::cout << toml::time_offset{} << "\n";
|
||||
/// std::cout << toml::time_offset{ -2, 30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ -2, -30 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// +02:30
|
||||
/// +01:30
|
||||
/// Z
|
||||
/// -01:30
|
||||
/// -02:30
|
||||
/// \eout
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const time_offset& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Prints a time_offset out to a stream as `+-HH:MM or Z` (per RFC 3339).
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::time_offset{ 2, 30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ 2, -30 } << "\n";
|
||||
/// std::cout << toml::time_offset{} << "\n";
|
||||
/// std::cout << toml::time_offset{ -2, 30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ -2, -30 } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// +02:30
|
||||
/// +01:30
|
||||
/// Z
|
||||
/// -01:30
|
||||
/// -02:30
|
||||
/// \eout
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const time_offset& rhs)
|
||||
{
|
||||
impl::print_to_stream(rhs, lhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const time_offset&);
|
||||
#endif
|
||||
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt);
|
||||
|
||||
/// \brief A date-time.
|
||||
@ -293,67 +323,85 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief The date component.
|
||||
toml::date date;
|
||||
|
||||
/// \brief The time component.
|
||||
toml::time time;
|
||||
|
||||
/// \brief The timezone offset component.
|
||||
///
|
||||
/// \remarks The date_time is said to be 'local' if the offset is empty.
|
||||
optional<toml::time_offset> offset;
|
||||
|
||||
/// \brief Default-constructs a zero date-time.
|
||||
/// \brief Default constructor. Does not initialize the members.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr date_time() noexcept //
|
||||
: date{},
|
||||
time{},
|
||||
offset{} // TINAE - icc bugfix
|
||||
{}
|
||||
date_time() noexcept = default;
|
||||
|
||||
/// \brief Constructs a local date-time.
|
||||
///
|
||||
/// \param d The date component.
|
||||
/// \param t The time component.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr date_time(toml::date d, toml::time t) noexcept //
|
||||
constexpr date_time(const toml::date& d, const toml::time& t) noexcept //
|
||||
: date{ d },
|
||||
time{ t },
|
||||
offset{} // TINAE - icc bugfix
|
||||
{}
|
||||
|
||||
/// \brief Constructs a local date-time.
|
||||
///
|
||||
/// \param d The date component.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit constexpr date_time(const toml::date& d) noexcept //
|
||||
: date{ d },
|
||||
time{},
|
||||
offset{} // TINAE - icc bugfix
|
||||
{}
|
||||
|
||||
/// \brief Constructs a local date-time.
|
||||
///
|
||||
/// \param t The time component.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit constexpr date_time(const toml::time& t) noexcept //
|
||||
: date{},
|
||||
time{ t },
|
||||
offset{} // TINAE - icc bugfix
|
||||
{}
|
||||
|
||||
/// \brief Constructs an offset date-time.
|
||||
///
|
||||
/// \param d The date component.
|
||||
/// \param t The time component.
|
||||
/// \param off The timezone offset.
|
||||
TOML_NODISCARD_CTOR
|
||||
constexpr date_time(toml::date d, toml::time t, toml::time_offset off) noexcept
|
||||
constexpr date_time(const toml::date& d, const toml::time& t, const toml::time_offset& off) noexcept
|
||||
: date{ d },
|
||||
time{ t },
|
||||
offset{ off }
|
||||
{}
|
||||
|
||||
/// \brief Returns true if this date_time does not contain timezone offset information.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
constexpr bool is_local() const noexcept
|
||||
{
|
||||
return !offset.has_value();
|
||||
}
|
||||
|
||||
/// \brief Equality operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator==(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return lhs.date == rhs.date && lhs.time == rhs.time && lhs.offset == rhs.offset;
|
||||
}
|
||||
|
||||
/// \brief Inequality operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator!=(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// \brief Less-than operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator<(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
if (lhs.date != rhs.date)
|
||||
@ -364,7 +412,7 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
/// \brief Less-than-or-equal-to operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator<=(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
if (lhs.date != rhs.date)
|
||||
@ -375,44 +423,40 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
/// \brief Greater-than operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator>(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return !(lhs <= rhs);
|
||||
}
|
||||
|
||||
/// \brief Greater-than-or-equal-to operator.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
friend constexpr bool operator>=(const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
/// \brief Prints a date_time out to a stream in RFC 3339 format.
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 } } << "\n";
|
||||
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, { -2, -30 } } << "\n";
|
||||
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, {} } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 1987-03-16T10:20:34
|
||||
/// 1987-03-16T10:20:34-02:30
|
||||
/// 1987-03-16T10:20:34Z
|
||||
/// \eout
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const date_time& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_HAS_CUSTOM_OPTIONAL_TYPE
|
||||
|
||||
/// \brief Prints a date_time out to a stream in RFC 3339 format.
|
||||
/// \detail \cpp
|
||||
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 } } << "\n";
|
||||
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, { -2, -30 } } << "\n";
|
||||
/// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, {} } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 1987-03-16T10:20:34
|
||||
/// 1987-03-16T10:20:34-02:30
|
||||
/// 1987-03-16T10:20:34Z
|
||||
/// \eout
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const date_time& rhs)
|
||||
{
|
||||
impl::print_to_stream(rhs, lhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const date_time&);
|
||||
#endif
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
|
@ -1,459 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "formatter.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "utf8.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
std::string default_formatter_make_key_segment(const std::string&) noexcept;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
size_t default_formatter_inline_columns(const node&) noexcept;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
bool default_formatter_forces_multiline(const node&, size_t = 0) noexcept;
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted TOML.
|
||||
///
|
||||
/// \remarks You generally don't need to create an instance of this class explicitly; the stream
|
||||
/// operators of the TOML node types already print themselves out using this formatter.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::table{{
|
||||
/// { "description", "This is some TOML, yo." },
|
||||
/// { "fruit", toml::array{ "apple", "orange", "pear" } },
|
||||
/// { "numbers", toml::array{ 1, 2, 3, 4, 5 } },
|
||||
/// { "table", toml::table{{ { "foo", "bar" } }} }
|
||||
/// }};
|
||||
///
|
||||
/// // these two lines are equivalent:
|
||||
/// std::cout << toml::default_formatter{ tbl } << "\n";
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// description = "This is some TOML, yo."
|
||||
/// fruit = ["apple", "orange", "pear"]
|
||||
/// numbers = [1, 2, 3, 4, 5]
|
||||
///
|
||||
/// [table]
|
||||
/// foo = "bar"
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The underlying character type of the output stream. Must be 1 byte in size.
|
||||
template <typename Char = char>
|
||||
class TOML_API default_formatter final : impl::formatter<Char>
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter<Char>;
|
||||
std::vector<std::string> key_path;
|
||||
bool pending_table_separator_ = false;
|
||||
|
||||
void print_pending_table_separator()
|
||||
{
|
||||
if (pending_table_separator_)
|
||||
{
|
||||
base::print_newline(true);
|
||||
base::print_newline(true);
|
||||
pending_table_separator_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void print_key_segment(const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
impl::print_to_stream("''"sv, base::stream());
|
||||
else
|
||||
{
|
||||
bool requiresQuotes = false;
|
||||
{
|
||||
impl::utf8_decoder decoder;
|
||||
for (size_t i = 0; i < str.length() && !requiresQuotes; i++)
|
||||
{
|
||||
decoder(static_cast<uint8_t>(str[i]));
|
||||
if (decoder.error())
|
||||
requiresQuotes = true;
|
||||
else if (decoder.has_code_point())
|
||||
requiresQuotes = !impl::is_bare_key_character(decoder.codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (requiresQuotes)
|
||||
{
|
||||
impl::print_to_stream('"', base::stream());
|
||||
impl::print_to_stream_with_escapes(str, base::stream());
|
||||
impl::print_to_stream('"', base::stream());
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(str, base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print_key_path()
|
||||
{
|
||||
for (const auto& segment : key_path)
|
||||
{
|
||||
if (std::addressof(segment) > key_path.data())
|
||||
impl::print_to_stream('.', base::stream());
|
||||
impl::print_to_stream(segment, base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print_inline(const table& /*tbl*/);
|
||||
|
||||
void print(const array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
impl::print_to_stream("[]"sv, base::stream());
|
||||
else
|
||||
{
|
||||
const auto original_indent = base::indent();
|
||||
const auto multiline = impl::default_formatter_forces_multiline(
|
||||
arr,
|
||||
base::indent_columns * static_cast<size_t>(original_indent < 0 ? 0 : original_indent));
|
||||
impl::print_to_stream("["sv, base::stream());
|
||||
if (multiline)
|
||||
{
|
||||
if (original_indent < 0)
|
||||
base::indent(0);
|
||||
base::increase_indent();
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0_sz)
|
||||
{
|
||||
impl::print_to_stream(',', base::stream());
|
||||
if (!multiline)
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
}
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
if (multiline)
|
||||
{
|
||||
base::indent(original_indent);
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
}
|
||||
else
|
||||
impl::print_to_stream(' ', base::stream());
|
||||
impl::print_to_stream("]"sv, base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
|
||||
void print(const table& tbl)
|
||||
{
|
||||
static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept
|
||||
{
|
||||
auto arr = nde.as_array();
|
||||
return arr && arr->is_array_of_tables() && !arr->template get_as<table>(0_sz)->is_inline();
|
||||
};
|
||||
|
||||
// values, arrays, and inline tables/table arrays
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
const auto type = v.type();
|
||||
if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline())
|
||||
|| (type == node_type::array && is_non_inline_array_of_tables(v)))
|
||||
continue;
|
||||
|
||||
pending_table_separator_ = true;
|
||||
base::print_newline();
|
||||
base::print_indent();
|
||||
print_key_segment(k);
|
||||
impl::print_to_stream(" = "sv, base::stream());
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
// non-inline tables
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
const auto type = v.type();
|
||||
if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline())
|
||||
continue;
|
||||
auto& child_tbl = *reinterpret_cast<const table*>(&v);
|
||||
|
||||
// we can skip indenting and emitting the headers for tables that only contain other tables
|
||||
// (so we don't over-nest)
|
||||
size_t child_value_count{}; // includes inline tables and non-table arrays
|
||||
size_t child_table_count{};
|
||||
size_t child_table_array_count{};
|
||||
for (auto&& [child_k, child_v] : child_tbl)
|
||||
{
|
||||
(void)child_k;
|
||||
const auto child_type = child_v.type();
|
||||
TOML_ASSUME(child_type != node_type::none);
|
||||
switch (child_type)
|
||||
{
|
||||
case node_type::table:
|
||||
if (reinterpret_cast<const table*>(&child_v)->is_inline())
|
||||
child_value_count++;
|
||||
else
|
||||
child_table_count++;
|
||||
break;
|
||||
|
||||
case node_type::array:
|
||||
if (is_non_inline_array_of_tables(child_v))
|
||||
child_table_array_count++;
|
||||
else
|
||||
child_value_count++;
|
||||
break;
|
||||
|
||||
default: child_value_count++;
|
||||
}
|
||||
}
|
||||
bool skip_self = false;
|
||||
if (child_value_count == 0_sz && (child_table_count > 0_sz || child_table_array_count > 0_sz))
|
||||
skip_self = true;
|
||||
|
||||
key_path.push_back(impl::default_formatter_make_key_segment(k));
|
||||
|
||||
if (!skip_self)
|
||||
{
|
||||
print_pending_table_separator();
|
||||
base::increase_indent();
|
||||
base::print_indent();
|
||||
impl::print_to_stream("["sv, base::stream());
|
||||
print_key_path();
|
||||
impl::print_to_stream("]"sv, base::stream());
|
||||
pending_table_separator_ = true;
|
||||
}
|
||||
|
||||
print(child_tbl);
|
||||
|
||||
key_path.pop_back();
|
||||
if (!skip_self)
|
||||
base::decrease_indent();
|
||||
}
|
||||
|
||||
// table arrays
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (!is_non_inline_array_of_tables(v))
|
||||
continue;
|
||||
auto& arr = *reinterpret_cast<const array*>(&v);
|
||||
|
||||
base::increase_indent();
|
||||
key_path.push_back(impl::default_formatter_make_key_segment(k));
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
print_pending_table_separator();
|
||||
base::print_indent();
|
||||
impl::print_to_stream("[["sv, base::stream());
|
||||
print_key_path();
|
||||
impl::print_to_stream("]]"sv, base::stream());
|
||||
pending_table_separator_ = true;
|
||||
print(*reinterpret_cast<const table*>(&arr[i]));
|
||||
}
|
||||
|
||||
key_path.pop_back();
|
||||
base::decrease_indent();
|
||||
}
|
||||
}
|
||||
|
||||
void print()
|
||||
{
|
||||
if (base::dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
switch (auto source_type = base::source().type())
|
||||
{
|
||||
case node_type::table:
|
||||
{
|
||||
auto& tbl = *reinterpret_cast<const table*>(&base::source());
|
||||
if (tbl.is_inline())
|
||||
print_inline(tbl);
|
||||
else
|
||||
{
|
||||
base::decrease_indent(); // so root kvps and tables have the same indent
|
||||
print(tbl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
|
||||
|
||||
default: base::print_value(base::source(), source_type);
|
||||
}
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief The default flags for a default_formatter.
|
||||
static constexpr format_flags default_flags = format_flags::allow_literal_strings
|
||||
| format_flags::allow_multi_line_strings
|
||||
| format_flags::allow_value_format_flags;
|
||||
|
||||
/// \brief Constructs a default formatter and binds it to a TOML object.
|
||||
///
|
||||
/// \param source The source TOML object.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit default_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
|
||||
: base{ source, flags }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a default TOML formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
/// \availability This constructor is only available when exceptions are disabled.
|
||||
///
|
||||
/// \attention Formatting a failed parse result will simply dump the error message out as-is.
|
||||
/// This will not be valid TOML, but at least gives you something to log or show up in diagnostics:
|
||||
/// \cpp
|
||||
/// std::cout << toml::default_formatter{ toml::parse("a = 'b'"sv) } // ok
|
||||
/// << "\n\n"
|
||||
/// << toml::default_formatter{ toml::parse("a = "sv) } // malformed
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// a = 'b'
|
||||
///
|
||||
/// Error while parsing key-value pair: encountered end-of-file
|
||||
/// (error occurred at line 1, column 5)
|
||||
/// \eout
|
||||
/// Use the library with exceptions if you want to avoid this scenario.
|
||||
///
|
||||
/// \param result The parse result.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit default_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ result, flags }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>&, default_formatter<U>&);
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>&, default_formatter<U>&&);
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API default_formatter<char>;
|
||||
#endif
|
||||
|
||||
default_formatter(const table&)->default_formatter<char>;
|
||||
default_formatter(const array&)->default_formatter<char>;
|
||||
template <typename T>
|
||||
default_formatter(const value<T>&) -> default_formatter<char>;
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as formatted TOML.
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, default_formatter<U>& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.key_path.clear();
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload).
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, default_formatter<U>&& rhs)
|
||||
{
|
||||
return lhs << rhs; // as lvalue
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
#if !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, default_formatter<char>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, default_formatter<char>&&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const table&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const array&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const value<std::string>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const value<int64_t>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const value<double>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const value<bool>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const value<toml::date>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const value<toml::time>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const value<toml::date_time>&);
|
||||
#endif
|
||||
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const table& rhs)
|
||||
{
|
||||
return lhs << default_formatter<Char>{ rhs };
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const array& rhs)
|
||||
{
|
||||
return lhs << default_formatter<Char>{ rhs };
|
||||
}
|
||||
|
||||
template <typename Char, typename T>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const value<T>& rhs)
|
||||
{
|
||||
return lhs << default_formatter<Char>{ rhs };
|
||||
}
|
||||
|
||||
#endif // !DOXYGEN
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
@ -1,287 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "default_formatter.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
inline constexpr size_t default_formatter_line_wrap = 120_sz;
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::string default_formatter_make_key_segment(const std::string& str) noexcept
|
||||
{
|
||||
if (str.empty())
|
||||
return "''"s;
|
||||
else
|
||||
{
|
||||
bool requires_quotes = false;
|
||||
{
|
||||
utf8_decoder decoder;
|
||||
for (size_t i = 0; i < str.length() && !requires_quotes; i++)
|
||||
{
|
||||
decoder(static_cast<uint8_t>(str[i]));
|
||||
if (decoder.error())
|
||||
requires_quotes = true;
|
||||
else if (decoder.has_code_point())
|
||||
requires_quotes = !is_bare_key_character(decoder.codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (requires_quotes)
|
||||
{
|
||||
std::string s;
|
||||
s.reserve(str.length() + 2_sz);
|
||||
s += '"';
|
||||
for (auto c : str)
|
||||
{
|
||||
if TOML_UNLIKELY(c >= '\x00' && c <= '\x1F')
|
||||
s.append(low_character_escape_table[c]);
|
||||
else if TOML_UNLIKELY(c == '\x7F')
|
||||
s.append("\\u007F"sv);
|
||||
else if TOML_UNLIKELY(c == '"')
|
||||
s.append("\\\""sv);
|
||||
else
|
||||
s += c;
|
||||
}
|
||||
s += '"';
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
size_t default_formatter_inline_columns(const node& node) noexcept
|
||||
{
|
||||
switch (node.type())
|
||||
{
|
||||
case node_type::table:
|
||||
{
|
||||
auto& n = *reinterpret_cast<const table*>(&node);
|
||||
if (n.empty())
|
||||
return 2_sz; // "{}"
|
||||
size_t weight = 3_sz; // "{ }"
|
||||
for (auto&& [k, v] : n)
|
||||
{
|
||||
weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", "
|
||||
if (weight >= default_formatter_line_wrap)
|
||||
break;
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
case node_type::array:
|
||||
{
|
||||
auto& n = *reinterpret_cast<const array*>(&node);
|
||||
if (n.empty())
|
||||
return 2_sz; // "[]"
|
||||
size_t weight = 3_sz; // "[ ]"
|
||||
for (auto& elem : n)
|
||||
{
|
||||
weight += default_formatter_inline_columns(elem) + 2_sz; // + ", "
|
||||
if (weight >= default_formatter_line_wrap)
|
||||
break;
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
case node_type::string:
|
||||
{
|
||||
auto& n = *reinterpret_cast<const value<std::string>*>(&node);
|
||||
return n.get().length() + 2_sz; // + ""
|
||||
}
|
||||
|
||||
case node_type::integer:
|
||||
{
|
||||
auto& n = *reinterpret_cast<const value<int64_t>*>(&node);
|
||||
auto v = n.get();
|
||||
if (!v)
|
||||
return 1_sz;
|
||||
size_t weight = {};
|
||||
if (v < 0)
|
||||
{
|
||||
weight += 1;
|
||||
v *= -1;
|
||||
}
|
||||
return weight + static_cast<size_t>(log10(static_cast<double>(v))) + 1_sz;
|
||||
}
|
||||
|
||||
case node_type::floating_point:
|
||||
{
|
||||
auto& n = *reinterpret_cast<const value<double>*>(&node);
|
||||
auto v = n.get();
|
||||
if (v == 0.0)
|
||||
return 3_sz; // "0.0"
|
||||
size_t weight = 2_sz; // ".0"
|
||||
if (v < 0.0)
|
||||
{
|
||||
weight += 1;
|
||||
v *= -1.0;
|
||||
}
|
||||
return weight + static_cast<size_t>(log10(v)) + 1_sz;
|
||||
break;
|
||||
}
|
||||
|
||||
case node_type::boolean: return 5_sz;
|
||||
case node_type::date: [[fallthrough]];
|
||||
case node_type::time: return 10_sz;
|
||||
case node_type::date_time: return 30_sz;
|
||||
case node_type::none: TOML_UNREACHABLE;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool default_formatter_forces_multiline(const node& node, size_t starting_column_bias) noexcept
|
||||
{
|
||||
return (default_formatter_inline_columns(node) + starting_column_bias) >= default_formatter_line_wrap;
|
||||
}
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
template <typename Char>
|
||||
inline void default_formatter<Char>::print_inline(const toml::table& tbl)
|
||||
{
|
||||
if (tbl.empty())
|
||||
impl::print_to_stream("{}"sv, base::stream());
|
||||
else
|
||||
{
|
||||
impl::print_to_stream("{ "sv, base::stream());
|
||||
|
||||
bool first = false;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (first)
|
||||
impl::print_to_stream(", "sv, base::stream());
|
||||
first = true;
|
||||
|
||||
print_key_segment(k);
|
||||
impl::print_to_stream(" = "sv, base::stream());
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
impl::print_to_stream(" }"sv, base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
// implementations of windows wide string nonsense
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
#ifndef _WINDOWS_
|
||||
#if TOML_INCLUDE_WINDOWS_H
|
||||
#include <Windows.h>
|
||||
#else
|
||||
extern "C" {
|
||||
__declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int CodePage,
|
||||
unsigned long dwFlags,
|
||||
const wchar_t* lpWideCharStr,
|
||||
int cchWideChar,
|
||||
char* lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
const char* lpDefaultChar,
|
||||
int* lpUsedDefaultChar);
|
||||
|
||||
__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage,
|
||||
unsigned long dwFlags,
|
||||
const char* lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
wchar_t* lpWideCharStr,
|
||||
int cchWideChar);
|
||||
}
|
||||
#endif
|
||||
#endif // _WINDOWS_
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::string narrow(std::wstring_view str) noexcept
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
|
||||
std::string s;
|
||||
const auto len =
|
||||
::WideCharToMultiByte(65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0, nullptr, nullptr);
|
||||
if (len)
|
||||
{
|
||||
s.resize(static_cast<size_t>(len));
|
||||
::WideCharToMultiByte(65001,
|
||||
0,
|
||||
str.data(),
|
||||
static_cast<int>(str.length()),
|
||||
s.data(),
|
||||
len,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::wstring widen(std::string_view str) noexcept
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
|
||||
std::wstring s;
|
||||
const auto len = ::MultiByteToWideChar(65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0);
|
||||
if (len)
|
||||
{
|
||||
s.resize(static_cast<size_t>(len));
|
||||
::MultiByteToWideChar(65001, 0, str.data(), static_cast<int>(str.length()), s.data(), len);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::wstring widen(std::u8string_view str) noexcept
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
|
||||
return widen(std::string_view{ reinterpret_cast<const char*>(str.data()), str.length() });
|
||||
}
|
||||
|
||||
#endif // TOML_HAS_CHAR8
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
/// \endcond
|
@ -2,48 +2,66 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
/// \cond
|
||||
|
||||
#pragma once
|
||||
#include "print_to_stream.h"
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
#include "parse_result.h"
|
||||
#endif
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "forward_declarations.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "header_start.h"
|
||||
/// \cond
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
template <typename Char = char>
|
||||
class TOML_API formatter
|
||||
struct formatter_constants
|
||||
{
|
||||
format_flags mandatory_flags;
|
||||
format_flags ignored_flags;
|
||||
|
||||
std::string_view float_pos_inf;
|
||||
std::string_view float_neg_inf;
|
||||
std::string_view float_nan;
|
||||
|
||||
std::string_view bool_true;
|
||||
std::string_view bool_false;
|
||||
};
|
||||
|
||||
struct formatter_config
|
||||
{
|
||||
format_flags flags;
|
||||
std::string_view indent;
|
||||
};
|
||||
|
||||
class formatter
|
||||
{
|
||||
private:
|
||||
const toml::node* source_;
|
||||
std::basic_ostream<Char>* stream_ = {};
|
||||
format_flags flags_;
|
||||
int indent_;
|
||||
bool naked_newline_;
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
const parse_result* result_ = {};
|
||||
const node* source_;
|
||||
#if TOML_ENABLE_PARSER && !TOML_EXCEPTIONS
|
||||
const parse_result* result_;
|
||||
#endif
|
||||
const formatter_constants* constants_;
|
||||
formatter_config config_;
|
||||
size_t indent_columns_;
|
||||
format_flags int_format_mask_;
|
||||
std::ostream* stream_; //
|
||||
int indent_; // these are set in attach()
|
||||
bool naked_newline_; //
|
||||
|
||||
protected:
|
||||
TOML_NODISCARD
|
||||
const toml::node& source() const noexcept
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const node& source() const noexcept
|
||||
{
|
||||
return *source_;
|
||||
}
|
||||
TOML_NODISCARD
|
||||
std::basic_ostream<Char>& stream() const noexcept
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
std::ostream& stream() const noexcept
|
||||
{
|
||||
return *stream_;
|
||||
}
|
||||
|
||||
static constexpr size_t indent_columns = 4;
|
||||
static constexpr std::string_view indent_string = " "sv;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
int indent() const noexcept
|
||||
{
|
||||
return indent_;
|
||||
@ -64,232 +82,104 @@ TOML_IMPL_NAMESPACE_START
|
||||
indent_--;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool quote_dates_and_times() const noexcept
|
||||
TOML_PURE_INLINE_GETTER
|
||||
size_t indent_columns() const noexcept
|
||||
{
|
||||
return (flags_ & format_flags::quote_dates_and_times) != format_flags::none;
|
||||
return indent_columns_;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool indent_array_elements() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::indent_array_elements);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool indent_sub_tables() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::indent_sub_tables);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool literal_strings_allowed() const noexcept
|
||||
{
|
||||
return (flags_ & format_flags::allow_literal_strings) != format_flags::none;
|
||||
return !!(config_.flags & format_flags::allow_literal_strings);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool multi_line_strings_allowed() const noexcept
|
||||
{
|
||||
return (flags_ & format_flags::allow_multi_line_strings) != format_flags::none;
|
||||
return !!(config_.flags & format_flags::allow_multi_line_strings);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool real_tabs_in_strings_allowed() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::allow_real_tabs_in_strings);
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool unicode_strings_allowed() const noexcept
|
||||
{
|
||||
return !!(config_.flags & format_flags::allow_unicode_strings);
|
||||
}
|
||||
|
||||
TOML_API
|
||||
void attach(std::ostream& stream) noexcept;
|
||||
|
||||
TOML_API
|
||||
void detach() noexcept;
|
||||
|
||||
TOML_API
|
||||
void print_newline(bool force = false);
|
||||
|
||||
TOML_API
|
||||
void print_indent();
|
||||
|
||||
TOML_API
|
||||
void print_unformatted(char);
|
||||
|
||||
TOML_API
|
||||
void print_unformatted(std::string_view);
|
||||
|
||||
TOML_API
|
||||
void print_string(std::string_view str, bool allow_multi_line = true, bool allow_bare = false);
|
||||
|
||||
TOML_API
|
||||
void print(const value<std::string>&);
|
||||
|
||||
TOML_API
|
||||
void print(const value<int64_t>&);
|
||||
|
||||
TOML_API
|
||||
void print(const value<double>&);
|
||||
|
||||
TOML_API
|
||||
void print(const value<bool>&);
|
||||
|
||||
TOML_API
|
||||
void print(const value<date>&);
|
||||
|
||||
TOML_API
|
||||
void print(const value<time>&);
|
||||
|
||||
TOML_API
|
||||
void print(const value<date_time>&);
|
||||
|
||||
TOML_API
|
||||
void print_value(const node&, node_type);
|
||||
|
||||
TOML_NODISCARD
|
||||
bool value_format_flags_allowed() const noexcept
|
||||
{
|
||||
return (flags_ & format_flags::allow_value_format_flags) != format_flags::none;
|
||||
}
|
||||
TOML_API
|
||||
bool dump_failed_parse_result();
|
||||
|
||||
TOML_NODISCARD
|
||||
bool naked_newline() const noexcept
|
||||
{
|
||||
return naked_newline_;
|
||||
}
|
||||
|
||||
void clear_naked_newline() noexcept
|
||||
{
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
void attach(std::basic_ostream<Char>& stream) noexcept
|
||||
{
|
||||
indent_ = {};
|
||||
naked_newline_ = true;
|
||||
stream_ = &stream;
|
||||
}
|
||||
|
||||
void detach() noexcept
|
||||
{
|
||||
stream_ = nullptr;
|
||||
}
|
||||
|
||||
void print_newline(bool force = false)
|
||||
{
|
||||
if (!naked_newline_ || force)
|
||||
{
|
||||
print_to_stream('\n', *stream_);
|
||||
naked_newline_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void print_indent()
|
||||
{
|
||||
for (int i = 0; i < indent_; i++)
|
||||
{
|
||||
print_to_stream(indent_string, *stream_);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void print_quoted_string(std::string_view str, bool allow_multi_line = true)
|
||||
{
|
||||
auto literals = literal_strings_allowed();
|
||||
if (str.empty())
|
||||
{
|
||||
print_to_stream(literals ? "''"sv : "\"\""sv, *stream_);
|
||||
clear_naked_newline();
|
||||
return;
|
||||
}
|
||||
|
||||
auto multi_line = allow_multi_line && multi_line_strings_allowed();
|
||||
if (multi_line || literals)
|
||||
{
|
||||
utf8_decoder decoder;
|
||||
bool has_line_breaks = false;
|
||||
bool has_control_chars = false;
|
||||
bool has_single_quotes = false;
|
||||
for (size_t i = 0; i < str.length() && !(has_line_breaks && has_control_chars && has_single_quotes);
|
||||
i++)
|
||||
{
|
||||
decoder(static_cast<uint8_t>(str[i]));
|
||||
if (decoder.error())
|
||||
{
|
||||
has_line_breaks = false;
|
||||
has_control_chars = true; // force ""
|
||||
has_single_quotes = true;
|
||||
break;
|
||||
}
|
||||
else if (decoder.has_code_point())
|
||||
{
|
||||
if (is_line_break(decoder.codepoint))
|
||||
has_line_breaks = true;
|
||||
else if (is_nontab_control_character(decoder.codepoint))
|
||||
has_control_chars = true;
|
||||
else if (decoder.codepoint == U'\'')
|
||||
has_single_quotes = true;
|
||||
}
|
||||
}
|
||||
multi_line = multi_line && has_line_breaks;
|
||||
literals = literals && !has_control_chars && !(!multi_line && has_single_quotes);
|
||||
}
|
||||
|
||||
if (literals)
|
||||
{
|
||||
const auto quot = multi_line ? "'''"sv : "'"sv;
|
||||
print_to_stream(quot, *stream_);
|
||||
print_to_stream(str, *stream_);
|
||||
print_to_stream(quot, *stream_);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto quot = multi_line ? R"(""")"sv : R"(")"sv;
|
||||
print_to_stream(quot, *stream_);
|
||||
print_to_stream_with_escapes(str, *stream_);
|
||||
print_to_stream(quot, *stream_);
|
||||
}
|
||||
clear_naked_newline();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void print(const value<T>& val)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, std::string>)
|
||||
{
|
||||
print_quoted_string(val.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (is_one_of<T, date, time, date_time>)
|
||||
{
|
||||
if (quote_dates_and_times())
|
||||
{
|
||||
const auto quot = literal_strings_allowed() ? '\'' : '"';
|
||||
print_to_stream(quot, *stream_);
|
||||
print_to_stream(*val, *stream_);
|
||||
print_to_stream(quot, *stream_);
|
||||
}
|
||||
else
|
||||
print_to_stream(*val, *stream_);
|
||||
}
|
||||
else if constexpr (is_one_of<T, int64_t /*, double*/>)
|
||||
{
|
||||
if (value_format_flags_allowed() && *val >= 0)
|
||||
{
|
||||
const auto fmt = val.flags() & value_flags::format_as_hexadecimal;
|
||||
if (fmt != value_flags::none)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case value_flags::format_as_binary: print_to_stream("0b"sv, *stream_); break;
|
||||
case value_flags::format_as_octal: print_to_stream("0o"sv, *stream_); break;
|
||||
case value_flags::format_as_hexadecimal: print_to_stream("0x"sv, *stream_); break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
print_to_stream(*val, *stream_, fmt);
|
||||
}
|
||||
else
|
||||
print_to_stream(*val, *stream_);
|
||||
}
|
||||
else
|
||||
print_to_stream(*val, *stream_);
|
||||
}
|
||||
else
|
||||
print_to_stream(*val, *stream_);
|
||||
|
||||
naked_newline_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void print_value(const node& val_node, node_type type)
|
||||
{
|
||||
TOML_ASSUME(type > node_type::array);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::string: print(*reinterpret_cast<const value<std::string>*>(&val_node)); break;
|
||||
case node_type::integer: print(*reinterpret_cast<const value<int64_t>*>(&val_node)); break;
|
||||
case node_type::floating_point: print(*reinterpret_cast<const value<double>*>(&val_node)); break;
|
||||
case node_type::boolean: print(*reinterpret_cast<const value<bool>*>(&val_node)); break;
|
||||
case node_type::date: print(*reinterpret_cast<const value<date>*>(&val_node)); break;
|
||||
case node_type::time: print(*reinterpret_cast<const value<time>*>(&val_node)); break;
|
||||
case node_type::date_time: print(*reinterpret_cast<const value<date_time>*>(&val_node)); break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool dump_failed_parse_result()
|
||||
{
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
if (result_ && !(*result_))
|
||||
{
|
||||
stream() << result_->error();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
formatter(const toml::node& source, format_flags flags) noexcept //
|
||||
: source_{ &source },
|
||||
flags_{ flags }
|
||||
{}
|
||||
|
||||
#if TOML_PARSER && !TOML_EXCEPTIONS
|
||||
|
||||
formatter(const parse_result& result, format_flags flags) noexcept //
|
||||
: source_{ result ? &result.table() : nullptr },
|
||||
flags_{ flags },
|
||||
result_{ &result }
|
||||
{}
|
||||
|
||||
#endif
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_API
|
||||
formatter(const node*, const parse_result*, const formatter_constants&, const formatter_config&) noexcept;
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API formatter<char>;
|
||||
#endif
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
||||
|
||||
/// \endcond
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
||||
|
513
include/toml++/impl/formatter.inl
Normal file
513
include/toml++/impl/formatter.inl
Normal file
@ -0,0 +1,513 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
//# {{
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "formatter.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "value.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "unicode.h"
|
||||
#include "parse_result.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
enum class TOML_CLOSED_FLAGS_ENUM formatted_string_traits : unsigned
|
||||
{
|
||||
none,
|
||||
line_breaks = 1u << 0, // \n
|
||||
tabs = 1u << 1, // \t
|
||||
control_chars = 1u << 2, // also includes non-ascii vertical whitespace
|
||||
single_quotes = 1u << 3,
|
||||
non_bare = 1u << 4, // anything not satisfying "is bare key character"
|
||||
non_ascii = 1u << 5, // any codepoint >= 128
|
||||
|
||||
all = (non_ascii << 1u) - 1u
|
||||
};
|
||||
TOML_MAKE_FLAGS(formatted_string_traits);
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
formatter::formatter(const node* source_node,
|
||||
const parse_result* source_pr,
|
||||
const formatter_constants& constants,
|
||||
const formatter_config& config) noexcept //
|
||||
#if TOML_ENABLE_PARSER && !TOML_EXCEPTIONS
|
||||
: source_{ source_pr && *source_pr ? &source_pr->table() : source_node },
|
||||
result_{ source_pr },
|
||||
#else
|
||||
: source_{ source_pr ? source_pr : source_node },
|
||||
#endif
|
||||
constants_{ &constants },
|
||||
config_{ config }
|
||||
{
|
||||
TOML_ASSERT_ASSUME(source_);
|
||||
|
||||
config_.flags = (config_.flags | constants_->mandatory_flags) & ~constants_->ignored_flags;
|
||||
|
||||
indent_columns_ = {};
|
||||
for (auto c : config_.indent)
|
||||
indent_columns_ += c == '\t' ? 4u : 1u;
|
||||
|
||||
int_format_mask_ = config_.flags
|
||||
& (format_flags::allow_binary_integers | format_flags::allow_octal_integers
|
||||
| format_flags::allow_hexadecimal_integers);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::attach(std::ostream & stream) noexcept
|
||||
{
|
||||
indent_ = {};
|
||||
naked_newline_ = true;
|
||||
stream_ = &stream;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::detach() noexcept
|
||||
{
|
||||
stream_ = nullptr;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_newline(bool force)
|
||||
{
|
||||
if (!naked_newline_ || force)
|
||||
{
|
||||
print_to_stream(*stream_, '\n');
|
||||
naked_newline_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_indent()
|
||||
{
|
||||
for (int i = 0; i < indent_; i++)
|
||||
{
|
||||
print_to_stream(*stream_, config_.indent);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_unformatted(char c)
|
||||
{
|
||||
print_to_stream(*stream_, c);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_unformatted(std::string_view str)
|
||||
{
|
||||
print_to_stream(*stream_, str);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_string(std::string_view str, bool allow_multi_line, bool allow_bare)
|
||||
{
|
||||
if (str.empty())
|
||||
{
|
||||
print_unformatted(literal_strings_allowed() ? "''"sv : "\"\""sv);
|
||||
return;
|
||||
}
|
||||
|
||||
// pre-scan the string to determine how we should output it
|
||||
formatted_string_traits traits = {};
|
||||
|
||||
if (!allow_bare)
|
||||
traits |= formatted_string_traits::non_bare;
|
||||
bool unicode_allowed = unicode_strings_allowed();
|
||||
|
||||
// ascii fast path
|
||||
if (is_ascii(str.data(), str.length()))
|
||||
{
|
||||
for (auto c : str)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\n': traits |= formatted_string_traits::line_breaks; break;
|
||||
case '\t': traits |= formatted_string_traits::tabs; break;
|
||||
case '\'': traits |= formatted_string_traits::single_quotes; break;
|
||||
default:
|
||||
{
|
||||
if TOML_UNLIKELY(is_control_character(c))
|
||||
traits |= formatted_string_traits::control_chars;
|
||||
|
||||
if (!is_ascii_bare_key_character(static_cast<char32_t>(c)))
|
||||
traits |= formatted_string_traits::non_bare;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto all_ascii_traits =
|
||||
formatted_string_traits::all & ~formatted_string_traits::non_ascii;
|
||||
if (traits == all_ascii_traits)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// unicode slow path
|
||||
else
|
||||
{
|
||||
traits |= formatted_string_traits::non_ascii;
|
||||
utf8_decoder decoder;
|
||||
|
||||
// if the unicode is malformed just treat the string as a single-line non-literal and
|
||||
// escape all non-ascii characters (to ensure round-tripping and help with diagnostics)
|
||||
const auto bad_unicode = [&]() noexcept
|
||||
{
|
||||
traits &= ~formatted_string_traits::line_breaks;
|
||||
traits |= formatted_string_traits::control_chars | formatted_string_traits::non_bare;
|
||||
unicode_allowed = false;
|
||||
};
|
||||
|
||||
for (auto c : str)
|
||||
{
|
||||
decoder(c);
|
||||
|
||||
if TOML_UNLIKELY(decoder.error())
|
||||
{
|
||||
bad_unicode();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!decoder.has_code_point())
|
||||
continue;
|
||||
|
||||
switch (decoder.codepoint)
|
||||
{
|
||||
case U'\n': traits |= formatted_string_traits::line_breaks; break;
|
||||
case U'\t': traits |= formatted_string_traits::tabs; break;
|
||||
case U'\'': traits |= formatted_string_traits::single_quotes; break;
|
||||
default:
|
||||
{
|
||||
if TOML_UNLIKELY(is_control_character(decoder.codepoint)
|
||||
|| is_non_ascii_vertical_whitespace(decoder.codepoint))
|
||||
traits |= formatted_string_traits::control_chars;
|
||||
|
||||
if (!is_bare_key_character(decoder.codepoint))
|
||||
traits |= formatted_string_traits::non_bare;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (decoder.needs_more_input())
|
||||
bad_unicode();
|
||||
}
|
||||
|
||||
// if the string meets the requirements of being 'bare' we can emit a bare string
|
||||
// (bare strings are composed of letters and numbers; no whitespace, control chars, quotes, etc)
|
||||
if (!(traits & formatted_string_traits::non_bare)
|
||||
&& (!(traits & formatted_string_traits::non_ascii) || unicode_allowed))
|
||||
{
|
||||
print_unformatted(str);
|
||||
return;
|
||||
}
|
||||
|
||||
// determine if this should be a multi-line string (triple-quotes)
|
||||
const auto multi_line = allow_multi_line //
|
||||
&& multi_line_strings_allowed() //
|
||||
&& !!(traits & formatted_string_traits::line_breaks);
|
||||
|
||||
// determine if this should be a literal string (single-quotes with no escaping)
|
||||
const auto literal = literal_strings_allowed() //
|
||||
&& !(traits & formatted_string_traits::control_chars) //
|
||||
&& (!(traits & formatted_string_traits::single_quotes) || multi_line) //
|
||||
&& (!(traits & formatted_string_traits::tabs) || real_tabs_in_strings_allowed()) //
|
||||
&& (!(traits & formatted_string_traits::non_ascii) || unicode_allowed);
|
||||
|
||||
// literal strings (single quotes, no escape codes)
|
||||
if (literal)
|
||||
{
|
||||
const auto quot = multi_line ? R"(''')"sv : R"(')"sv;
|
||||
print_unformatted(quot);
|
||||
print_unformatted(str);
|
||||
print_unformatted(quot);
|
||||
return;
|
||||
}
|
||||
|
||||
// anything from here down is a non-literal string, so requires iteration and escaping.
|
||||
print_unformatted(multi_line ? R"(""")"sv : R"(")"sv);
|
||||
|
||||
const auto real_tabs_allowed = real_tabs_in_strings_allowed();
|
||||
|
||||
// ascii fast path
|
||||
if (!(traits & formatted_string_traits::non_ascii))
|
||||
{
|
||||
for (auto c : str)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '"': print_to_stream(*stream_, R"(\")"sv); break;
|
||||
case '\\': print_to_stream(*stream_, R"(\\)"sv); break;
|
||||
case '\x7F': print_to_stream(*stream_, R"(\u007F)"sv); break;
|
||||
case '\t': print_to_stream(*stream_, real_tabs_allowed ? "\t"sv : R"(\t)"sv); break;
|
||||
case '\n': print_to_stream(*stream_, multi_line ? "\n"sv : R"(\n)"sv); break;
|
||||
default:
|
||||
{
|
||||
// control characters from lookup table
|
||||
if TOML_UNLIKELY(c >= '\x00' && c <= '\x1F')
|
||||
print_to_stream(*stream_, control_char_escapes[c]);
|
||||
|
||||
// regular characters
|
||||
else
|
||||
print_to_stream(*stream_, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unicode slow path
|
||||
else
|
||||
{
|
||||
utf8_decoder decoder;
|
||||
const char* cp_start = str.data();
|
||||
const char* cp_end = cp_start;
|
||||
for (auto c : str)
|
||||
{
|
||||
decoder(c);
|
||||
cp_end++;
|
||||
|
||||
// if the decoder encounters malformed unicode just emit raw bytes and
|
||||
if (decoder.error())
|
||||
{
|
||||
while (cp_start != cp_end)
|
||||
{
|
||||
print_to_stream(*stream_, R"(\u00)"sv);
|
||||
print_to_stream(*stream_,
|
||||
static_cast<uint8_t>(*cp_start),
|
||||
value_flags::format_as_hexadecimal,
|
||||
2);
|
||||
cp_start++;
|
||||
}
|
||||
decoder.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!decoder.has_code_point())
|
||||
continue;
|
||||
|
||||
switch (decoder.codepoint)
|
||||
{
|
||||
case U'"': print_to_stream(*stream_, R"(\")"sv); break;
|
||||
case U'\\': print_to_stream(*stream_, R"(\\)"sv); break;
|
||||
case U'\x7F': print_to_stream(*stream_, R"(\u007F)"sv); break;
|
||||
case U'\t': print_to_stream(*stream_, real_tabs_allowed ? "\t"sv : R"(\t)"sv); break;
|
||||
case U'\n': print_to_stream(*stream_, multi_line ? "\n"sv : R"(\n)"sv); break;
|
||||
default:
|
||||
{
|
||||
// control characters from lookup table
|
||||
if TOML_UNLIKELY(decoder.codepoint <= U'\x1F')
|
||||
print_to_stream(*stream_,
|
||||
control_char_escapes[static_cast<uint_least32_t>(decoder.codepoint)]);
|
||||
|
||||
// escaped unicode characters
|
||||
else if (decoder.codepoint > U'\x7F'
|
||||
&& (!unicode_allowed || is_non_ascii_vertical_whitespace(decoder.codepoint)))
|
||||
{
|
||||
if (static_cast<uint_least32_t>(decoder.codepoint) > 0xFFFFu)
|
||||
{
|
||||
print_to_stream(*stream_, R"(\U)"sv);
|
||||
print_to_stream(*stream_,
|
||||
static_cast<uint_least32_t>(decoder.codepoint),
|
||||
value_flags::format_as_hexadecimal,
|
||||
8);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_to_stream(*stream_, R"(\u)"sv);
|
||||
print_to_stream(*stream_,
|
||||
static_cast<uint_least32_t>(decoder.codepoint),
|
||||
value_flags::format_as_hexadecimal,
|
||||
4);
|
||||
}
|
||||
}
|
||||
|
||||
// regular characters
|
||||
else
|
||||
print_to_stream(*stream_, cp_start, static_cast<size_t>(cp_end - cp_start));
|
||||
}
|
||||
}
|
||||
|
||||
cp_start = cp_end;
|
||||
}
|
||||
}
|
||||
|
||||
print_unformatted(multi_line ? R"(""")"sv : R"(")"sv);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<std::string>& val)
|
||||
{
|
||||
print_string(val.get());
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<int64_t>& val)
|
||||
{
|
||||
naked_newline_ = false;
|
||||
|
||||
if (*val >= 0 && !!int_format_mask_)
|
||||
{
|
||||
static constexpr auto value_flags_mask =
|
||||
value_flags::format_as_binary | value_flags::format_as_octal | value_flags::format_as_hexadecimal;
|
||||
|
||||
const auto fmt = val.flags() & value_flags_mask;
|
||||
switch (fmt)
|
||||
{
|
||||
case value_flags::format_as_binary:
|
||||
if (!!(int_format_mask_ & format_flags::allow_binary_integers))
|
||||
{
|
||||
print_to_stream(*stream_, "0b"sv);
|
||||
print_to_stream(*stream_, *val, fmt);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case value_flags::format_as_octal:
|
||||
if (!!(int_format_mask_ & format_flags::allow_octal_integers))
|
||||
{
|
||||
print_to_stream(*stream_, "0o"sv);
|
||||
print_to_stream(*stream_, *val, fmt);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case value_flags::format_as_hexadecimal:
|
||||
if (!!(int_format_mask_ & format_flags::allow_hexadecimal_integers))
|
||||
{
|
||||
print_to_stream(*stream_, "0x"sv);
|
||||
print_to_stream(*stream_, *val, fmt);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to decimal
|
||||
print_to_stream(*stream_, *val);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<double>& val)
|
||||
{
|
||||
const std::string_view* inf_nan = nullptr;
|
||||
switch (fpclassify(*val))
|
||||
{
|
||||
case fp_class::neg_inf: inf_nan = &constants_->float_neg_inf; break;
|
||||
case fp_class::pos_inf: inf_nan = &constants_->float_pos_inf; break;
|
||||
case fp_class::nan: inf_nan = &constants_->float_nan; break;
|
||||
case fp_class::ok:
|
||||
print_to_stream(*stream_,
|
||||
*val,
|
||||
value_flags::none,
|
||||
!!(config_.flags & format_flags::relaxed_float_precision));
|
||||
break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
if (inf_nan)
|
||||
{
|
||||
if (!!(config_.flags & format_flags::quote_infinities_and_nans))
|
||||
print_to_stream_bookended(*stream_, *inf_nan, '"');
|
||||
else
|
||||
print_to_stream(*stream_, *inf_nan);
|
||||
}
|
||||
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<bool>& val)
|
||||
{
|
||||
print_unformatted(*val ? constants_->bool_true : constants_->bool_false);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<date>& val)
|
||||
{
|
||||
if (!!(config_.flags & format_flags::quote_dates_and_times))
|
||||
print_to_stream_bookended(*stream_, *val, literal_strings_allowed() ? '\'' : '"');
|
||||
else
|
||||
print_to_stream(*stream_, *val);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<time>& val)
|
||||
{
|
||||
if (!!(config_.flags & format_flags::quote_dates_and_times))
|
||||
print_to_stream_bookended(*stream_, *val, literal_strings_allowed() ? '\'' : '"');
|
||||
else
|
||||
print_to_stream(*stream_, *val);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print(const value<date_time>& val)
|
||||
{
|
||||
if (!!(config_.flags & format_flags::quote_dates_and_times))
|
||||
print_to_stream_bookended(*stream_, *val, literal_strings_allowed() ? '\'' : '"');
|
||||
else
|
||||
print_to_stream(*stream_, *val);
|
||||
naked_newline_ = false;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void formatter::print_value(const node& val_node, node_type type)
|
||||
{
|
||||
TOML_ASSUME(type > node_type::array);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::string: print(*reinterpret_cast<const value<std::string>*>(&val_node)); break;
|
||||
case node_type::integer: print(*reinterpret_cast<const value<int64_t>*>(&val_node)); break;
|
||||
case node_type::floating_point: print(*reinterpret_cast<const value<double>*>(&val_node)); break;
|
||||
case node_type::boolean: print(*reinterpret_cast<const value<bool>*>(&val_node)); break;
|
||||
case node_type::date: print(*reinterpret_cast<const value<date>*>(&val_node)); break;
|
||||
case node_type::time: print(*reinterpret_cast<const value<time>*>(&val_node)); break;
|
||||
case node_type::date_time: print(*reinterpret_cast<const value<date_time>*>(&val_node)); break;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_PARSER && !TOML_EXCEPTIONS
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool formatter::dump_failed_parse_result()
|
||||
{
|
||||
if (result_ && !(*result_))
|
||||
{
|
||||
stream() << result_->error();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(const)
|
||||
bool formatter::dump_failed_parse_result()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
File diff suppressed because it is too large
Load Diff
10
include/toml++/impl/header_end.h
Normal file
10
include/toml++/impl/header_end.h
Normal file
@ -0,0 +1,10 @@
|
||||
//# {{
|
||||
#ifdef __INTELLISENSE__
|
||||
#include "preprocessor.h"
|
||||
#endif
|
||||
//# }}
|
||||
#ifdef _MSC_VER
|
||||
#pragma pop_macro("min")
|
||||
#pragma pop_macro("max")
|
||||
#endif
|
||||
TOML_POP_WARNINGS;
|
12
include/toml++/impl/header_start.h
Normal file
12
include/toml++/impl/header_start.h
Normal file
@ -0,0 +1,12 @@
|
||||
//# {{
|
||||
#ifdef __INTELLISENSE__
|
||||
#include "preprocessor.h"
|
||||
#endif
|
||||
//# }}
|
||||
TOML_PUSH_WARNINGS;
|
||||
#ifdef _MSC_VER
|
||||
#pragma push_macro("min")
|
||||
#pragma push_macro("max")
|
||||
#undef min
|
||||
#undef max
|
||||
#endif
|
@ -2,19 +2,20 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "formatter.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "formatter.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted JSON.
|
||||
///
|
||||
/// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto some_toml = toml::parse(R"(
|
||||
/// [fruit]
|
||||
@ -25,7 +26,6 @@ TOML_NAMESPACE_START
|
||||
/// smooth = true
|
||||
/// )"sv);
|
||||
/// std::cout << toml::json_formatter{ some_toml } << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -43,71 +43,40 @@ TOML_NAMESPACE_START
|
||||
/// }
|
||||
/// }
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The underlying character type of the output stream. Must be 1 byte in size.
|
||||
template <typename Char = char>
|
||||
class TOML_API json_formatter final : impl::formatter<Char>
|
||||
class json_formatter : impl::formatter
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter<Char>;
|
||||
using base = impl::formatter;
|
||||
|
||||
void print(const toml::table& tbl);
|
||||
TOML_API
|
||||
void print(const toml::table&);
|
||||
|
||||
void print(const array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
impl::print_to_stream("[]"sv, base::stream());
|
||||
else
|
||||
{
|
||||
impl::print_to_stream('[', base::stream());
|
||||
base::increase_indent();
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0_sz)
|
||||
impl::print_to_stream(',', base::stream());
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
TOML_API
|
||||
void print(const toml::array&);
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
base::decrease_indent();
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
impl::print_to_stream(']', base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
TOML_API
|
||||
void print();
|
||||
|
||||
void print()
|
||||
{
|
||||
if (base::dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
switch (auto source_type = base::source().type())
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&base::source())); break;
|
||||
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&base::source())); break;
|
||||
|
||||
default: base::print_value(base::source(), source_type);
|
||||
}
|
||||
}
|
||||
static constexpr impl::formatter_constants constants = {
|
||||
format_flags::quote_dates_and_times, // mandatory
|
||||
format_flags::allow_literal_strings | format_flags::allow_multi_line_strings, // ignored
|
||||
"Infinity"sv,
|
||||
"-Infinity"sv,
|
||||
"NaN"sv,
|
||||
"true"sv,
|
||||
"false"sv
|
||||
};
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief The default flags for a json_formatter.
|
||||
static constexpr format_flags default_flags = format_flags::quote_dates_and_times;
|
||||
static constexpr format_flags default_flags = constants.mandatory_flags //
|
||||
| format_flags::quote_infinities_and_nans //
|
||||
| format_flags::allow_unicode_strings //
|
||||
| format_flags::indentation;
|
||||
|
||||
/// \brief Constructs a JSON formatter and binds it to a TOML object.
|
||||
///
|
||||
@ -115,10 +84,10 @@ TOML_NAMESPACE_START
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit json_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
|
||||
: base{ source, flags }
|
||||
: base{ &source, nullptr, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
|
||||
#if defined(DOXYGEN) || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a JSON formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
@ -146,50 +115,28 @@ TOML_NAMESPACE_START
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit json_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ result, flags }
|
||||
: base{ nullptr, &result, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>&, json_formatter<U>&);
|
||||
template <typename T, typename U>
|
||||
friend std::basic_ostream<T>& operator<<(std::basic_ostream<T>&, json_formatter<U>&&);
|
||||
/// \brief Prints the bound TOML object out to the stream as JSON.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, json_formatter& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload).
|
||||
friend std::ostream& operator<<(std::ostream& lhs, json_formatter&& rhs)
|
||||
{
|
||||
return lhs << rhs; // as lvalue
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template class TOML_API json_formatter<char>;
|
||||
#endif
|
||||
|
||||
json_formatter(const table&)->json_formatter<char>;
|
||||
json_formatter(const array&)->json_formatter<char>;
|
||||
template <typename T>
|
||||
json_formatter(const value<T>&) -> json_formatter<char>;
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as JSON.
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, json_formatter<U>& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload).
|
||||
template <typename T, typename U>
|
||||
inline std::basic_ostream<T>& operator<<(std::basic_ostream<T>& lhs, json_formatter<U>&& rhs)
|
||||
{
|
||||
return lhs << rhs; // as lvalue
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, json_formatter<char>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, json_formatter<char>&&);
|
||||
#endif
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
||||
|
118
include/toml++/impl/json_formatter.inl
Normal file
118
include/toml++/impl/json_formatter.inl
Normal file
@ -0,0 +1,118 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
//# {{
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "json_formatter.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void json_formatter::print(const toml::table& tbl)
|
||||
{
|
||||
if (tbl.empty())
|
||||
{
|
||||
print_unformatted("{}"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
print_unformatted('{');
|
||||
|
||||
if (indent_sub_tables())
|
||||
increase_indent();
|
||||
bool first = false;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (first)
|
||||
print_unformatted(',');
|
||||
first = true;
|
||||
print_newline(true);
|
||||
print_indent();
|
||||
|
||||
print_string(k.str(), false);
|
||||
print_unformatted(" : "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: print_value(v, type);
|
||||
}
|
||||
}
|
||||
if (indent_sub_tables())
|
||||
decrease_indent();
|
||||
print_newline(true);
|
||||
print_indent();
|
||||
|
||||
print_unformatted('}');
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void json_formatter::print(const toml::array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
{
|
||||
print_unformatted("[]"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
print_unformatted('[');
|
||||
if (indent_array_elements())
|
||||
increase_indent();
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0u)
|
||||
print_unformatted(',');
|
||||
print_newline(true);
|
||||
print_indent();
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: print_value(v, type);
|
||||
}
|
||||
}
|
||||
if (indent_array_elements())
|
||||
decrease_indent();
|
||||
print_newline(true);
|
||||
print_indent();
|
||||
print_unformatted(']');
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void json_formatter::print()
|
||||
{
|
||||
if (dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
switch (auto source_type = source().type())
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&source())); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&source())); break;
|
||||
default: print_value(source(), source_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
@ -1,65 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "json_formatter.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
template <typename Char>
|
||||
inline void json_formatter<Char>::print(const toml::table& tbl)
|
||||
{
|
||||
if (tbl.empty())
|
||||
impl::print_to_stream("{}"sv, base::stream());
|
||||
else
|
||||
{
|
||||
impl::print_to_stream('{', base::stream());
|
||||
base::increase_indent();
|
||||
bool first = false;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (first)
|
||||
impl::print_to_stream(", "sv, base::stream());
|
||||
first = true;
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
|
||||
base::print_quoted_string(k, false);
|
||||
impl::print_to_stream(" : "sv, base::stream());
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: base::print_value(v, type);
|
||||
}
|
||||
}
|
||||
base::decrease_indent();
|
||||
base::print_newline(true);
|
||||
base::print_indent();
|
||||
impl::print_to_stream('}', base::stream());
|
||||
}
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
/// \endcond
|
335
include/toml++/impl/key.h
Normal file
335
include/toml++/impl/key.h
Normal file
@ -0,0 +1,335 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "source_region.h"
|
||||
#include "std_utility.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A key parsed from a TOML document.
|
||||
///
|
||||
/// \detail These are used as the internal keys for a toml::table: \cpp
|
||||
/// const toml::table tbl = R"(
|
||||
/// a = 1
|
||||
/// b = 2
|
||||
/// c = 3
|
||||
/// )"_toml;
|
||||
///
|
||||
/// for (auto&& [k, v] : tbl)
|
||||
/// std::cout << "key '"sv << k << "' defined at "sv << k.source() << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// key 'a' defined at line 2, column 5
|
||||
/// key 'b' defined at line 3, column 7
|
||||
/// key 'c' defined at line 4, column 9
|
||||
/// \eout
|
||||
class key
|
||||
{
|
||||
private:
|
||||
std::string key_;
|
||||
source_region source_;
|
||||
|
||||
public:
|
||||
/// A const iterator for iterating over the characters in the key.
|
||||
using const_iterator = const char*;
|
||||
|
||||
/// A const iterator for iterating over the characters in the key.
|
||||
using iterator = const_iterator;
|
||||
|
||||
/// \brief Default constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
key() noexcept = default;
|
||||
|
||||
/// \brief Constructs a key from a string view and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::string_view k, source_region&& src = {}) //
|
||||
: key_{ k },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a string view and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::string_view k, const source_region& src) //
|
||||
: key_{ k },
|
||||
source_{ src }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a string and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::string&& k, source_region&& src = {}) noexcept //
|
||||
: key_{ std::move(k) },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a string and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::string&& k, const source_region& src) noexcept //
|
||||
: key_{ std::move(k) },
|
||||
source_{ src }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a c-string and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(const char* k, source_region&& src = {}) //
|
||||
: key_{ k },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a c-string view and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(const char* k, const source_region& src) //
|
||||
: key_{ k },
|
||||
source_{ src }
|
||||
{}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Constructs a key from a wide string view and source region.
|
||||
///
|
||||
/// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::wstring_view k, source_region&& src = {}) //
|
||||
: key_{ impl::narrow(k) },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a wide string and source region.
|
||||
///
|
||||
/// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::wstring_view k, const source_region& src) //
|
||||
: key_{ impl::narrow(k) },
|
||||
source_{ src }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
/// \name String operations
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a view of the key's underlying string.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
std::string_view str() const noexcept
|
||||
{
|
||||
return std::string_view{ key_ };
|
||||
}
|
||||
|
||||
/// \brief Returns a view of the key's underlying string.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
/*implicit*/ operator std::string_view() const noexcept
|
||||
{
|
||||
return str();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the key's underlying string is empty.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return key_.empty();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the start of the key's underlying string.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const char* data() const noexcept
|
||||
{
|
||||
return key_.data();
|
||||
}
|
||||
|
||||
/// \brief Returns the length of the key's underlying string.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
size_t length() const noexcept
|
||||
{
|
||||
return key_.length();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Metadata
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the source region responsible for specifying this key during parsing.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Equality and Comparison
|
||||
/// \attention These operations only compare the underlying strings; source regions are ignored for the purposes of all comparison!
|
||||
/// @{
|
||||
|
||||
/// \brief Returns true if `lhs.str() == rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator==(const key& lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs.key_ == rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() != rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator!=(const key& lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs.key_ != rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() < rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator<(const key& lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs.key_ < rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() <= rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator<=(const key& lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs.key_ <= rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() > rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator>(const key& lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs.key_ > rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() >= rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator>=(const key& lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs.key_ >= rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() == rhs`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator==(const key& lhs, std::string_view rhs) noexcept
|
||||
{
|
||||
return lhs.key_ == rhs;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() != rhs`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator!=(const key& lhs, std::string_view rhs) noexcept
|
||||
{
|
||||
return lhs.key_ != rhs;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() < rhs`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator<(const key& lhs, std::string_view rhs) noexcept
|
||||
{
|
||||
return lhs.key_ < rhs;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() <= rhs`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator<=(const key& lhs, std::string_view rhs) noexcept
|
||||
{
|
||||
return lhs.key_ <= rhs;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() > rhs`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator>(const key& lhs, std::string_view rhs) noexcept
|
||||
{
|
||||
return lhs.key_ > rhs;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs.str() >= rhs`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator>=(const key& lhs, std::string_view rhs) noexcept
|
||||
{
|
||||
return lhs.key_ >= rhs;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs == rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator==(std::string_view lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs == rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs != rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator!=(std::string_view lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs != rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs < rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator<(std::string_view lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs < rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs <= rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator<=(std::string_view lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs <= rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs > rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator>(std::string_view lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs > rhs.key_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if `lhs >= rhs.str()`.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend bool operator>=(std::string_view lhs, const key& rhs) noexcept
|
||||
{
|
||||
return lhs >= rhs.key_;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Iterators
|
||||
/// @{
|
||||
|
||||
/// \brief Returns an iterator to the first character in the key's backing string.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return key_.data();
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last character in the key's backing string.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return key_.data() + key_.length();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \brief Prints the key's underlying string out to the stream.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const key& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs.key_);
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Metafunction for determining if a type is, or is a reference to, a toml::key.
|
||||
template <typename T>
|
||||
inline constexpr bool is_key = std::is_same_v<impl::remove_cvref<T>, toml::key>;
|
||||
|
||||
/// \brief Metafunction for determining if a type is, or is a reference to, a toml::key,
|
||||
/// or is implicitly or explicitly convertible to one.
|
||||
template <typename T>
|
||||
inline constexpr bool is_key_or_convertible =
|
||||
is_key<T> || std::is_constructible_v<toml::key, T> || std::is_convertible_v<T, toml::key>;
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
159
include/toml++/impl/make_node.h
Normal file
159
include/toml++/impl/make_node.h
Normal file
@ -0,0 +1,159 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "forward_declarations.h"
|
||||
#include "header_start.h"
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(returns_nonnull)
|
||||
auto* make_node_impl_specialized(T && val, [[maybe_unused]] value_flags flags)
|
||||
{
|
||||
using unwrapped_type = unwrap_node<remove_cvref<T>>;
|
||||
static_assert(!std::is_same_v<unwrapped_type, node>);
|
||||
static_assert(!is_node_view<unwrapped_type>);
|
||||
|
||||
// arrays + tables - invoke copy/move ctor
|
||||
if constexpr (is_one_of<unwrapped_type, array, table>)
|
||||
{
|
||||
return new unwrapped_type(static_cast<T&&>(val));
|
||||
}
|
||||
|
||||
// values
|
||||
else
|
||||
{
|
||||
using native_type = native_type_of<unwrapped_type>;
|
||||
using value_type = value<native_type>;
|
||||
|
||||
value_type* out;
|
||||
|
||||
// copy/move ctor
|
||||
if constexpr (std::is_same_v<remove_cvref<T>, value_type>)
|
||||
{
|
||||
out = new value_type{ static_cast<T&&>(val) };
|
||||
}
|
||||
|
||||
// creating from raw value
|
||||
else
|
||||
{
|
||||
static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
|
||||
"Instantiating values from wide-character strings is only "
|
||||
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
|
||||
|
||||
if constexpr (!is_losslessly_convertible_to_native<unwrapped_type>)
|
||||
{
|
||||
if constexpr (std::is_same_v<native_type, int64_t>)
|
||||
static_assert(dependent_false<T>,
|
||||
"Integral value initializers must be losslessly convertible to int64_t");
|
||||
else if constexpr (std::is_same_v<native_type, double>)
|
||||
static_assert(dependent_false<T>,
|
||||
"Floating-point value initializers must be losslessly convertible to double");
|
||||
else
|
||||
static_assert(
|
||||
dependent_false<T>,
|
||||
"Value initializers must be losslessly convertible to one of the TOML value types");
|
||||
}
|
||||
|
||||
if constexpr (is_wide_string<T>)
|
||||
{
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
out = new value_type{ narrow(static_cast<T&&>(val)) };
|
||||
#else
|
||||
static_assert(dependent_false<T>, "Evaluated unreachable branch!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
out = new value_type{ static_cast<T&&>(val) };
|
||||
}
|
||||
|
||||
if (flags != preserve_source_value_flags)
|
||||
out->flags(flags);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
auto* make_node_impl(T && val, value_flags flags = preserve_source_value_flags)
|
||||
{
|
||||
using unwrapped_type = unwrap_node<remove_cvref<T>>;
|
||||
if constexpr (std::is_same_v<unwrapped_type, node> || is_node_view<unwrapped_type>)
|
||||
{
|
||||
if constexpr (is_node_view<unwrapped_type>)
|
||||
{
|
||||
if (!val)
|
||||
return static_cast<toml::node*>(nullptr);
|
||||
}
|
||||
|
||||
return static_cast<T&&>(val).visit(
|
||||
[flags](auto&& concrete) {
|
||||
return static_cast<toml::node*>(
|
||||
make_node_impl_specialized(static_cast<decltype(concrete)&&>(concrete), flags));
|
||||
});
|
||||
}
|
||||
else
|
||||
return make_node_impl_specialized(static_cast<T&&>(val), flags);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
auto* make_node_impl(inserter<T> && val, value_flags flags = preserve_source_value_flags)
|
||||
{
|
||||
return make_node_impl(static_cast<T&&>(val.value), flags);
|
||||
}
|
||||
|
||||
template <typename T, bool = (is_node<T> || is_node_view<T> || is_value<T> || can_partially_represent_native<T>)>
|
||||
struct inserted_type_of_
|
||||
{
|
||||
using type = std::remove_pointer_t<decltype(make_node_impl(std::declval<T>()))>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct inserted_type_of_<inserter<T>, false>
|
||||
{
|
||||
using type = typename inserted_type_of_<T>::type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct inserted_type_of_<T, false>
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
node_ptr make_node(T && val, value_flags flags = preserve_source_value_flags)
|
||||
{
|
||||
return node_ptr{ make_node_impl(static_cast<T&&>(val), flags) };
|
||||
}
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief Metafunction for determining which node type would be constructed
|
||||
/// if an object of this type was inserted into a toml::table or toml::array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// static_assert(std::is_same_v<toml::inserted_type_of<const char*>, toml::value<std::string>);
|
||||
/// static_assert(std::is_same_v<toml::inserted_type_of<int>, toml::value<int64_t>);
|
||||
/// static_assert(std::is_same_v<toml::inserted_type_of<float>, toml::value<double>);
|
||||
/// static_assert(std::is_same_v<toml::inserted_type_of<bool>, toml::value<bool>);
|
||||
/// \ecpp
|
||||
///
|
||||
/// \note This will return toml::node for nodes and node_views, even though a more specific node subclass
|
||||
/// would actually be inserted. There is no way around this in a compile-time metafunction.
|
||||
template <typename T>
|
||||
using inserted_type_of = POXY_IMPLEMENTATION_DETAIL(typename impl::inserted_type_of_<impl::remove_cvref<T>>::type);
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
@ -2,9 +2,12 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
#include "std_utility.h"
|
||||
#include "forward_declarations.h"
|
||||
#include "source_region.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
@ -12,209 +15,129 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \detail A parsed TOML document forms a tree made up of tables, arrays and values.
|
||||
/// This type is the base of each of those, providing a lot of the polymorphic plumbing.
|
||||
class TOML_ABSTRACT_BASE TOML_API node
|
||||
class TOML_ABSTRACT_BASE node
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
source_region source_{};
|
||||
|
||||
/// \cond
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
decltype(auto) get_value_exact() const noexcept;
|
||||
decltype(auto) get_value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>);
|
||||
|
||||
template <typename T, typename N>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
static decltype(auto) do_ref(N&& n) noexcept
|
||||
using ref_type_ = std::conditional_t< //
|
||||
std::is_reference_v<T>, //
|
||||
impl::copy_ref<impl::copy_cv<impl::unwrap_node<T>, std::remove_reference_t<N>>, T>, //
|
||||
impl::copy_cvref<impl::unwrap_node<T>, N> //
|
||||
>;
|
||||
|
||||
template <typename T, typename N>
|
||||
using ref_type = std::conditional_t< //
|
||||
std::is_reference_v<N>, //
|
||||
ref_type_<T, N>, //
|
||||
ref_type_<T, std::add_lvalue_reference_t<N>> //
|
||||
>;
|
||||
|
||||
template <typename T, typename N>
|
||||
TOML_PURE_GETTER
|
||||
static ref_type<T, N&&> do_ref(N&& n) noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
|
||||
using unwrapped_type = impl::unwrap_node<T>;
|
||||
static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
|
||||
"The template type argument of node::ref() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
TOML_ASSERT(
|
||||
n.template is<T>()
|
||||
&& "template type argument T provided to toml::node::ref() didn't match the node's actual type");
|
||||
if constexpr (impl::is_native<type>)
|
||||
return static_cast<N&&>(n).template ref_cast<type>().get();
|
||||
|
||||
TOML_ASSERT_ASSUME(
|
||||
n.template is<unwrapped_type>()
|
||||
&& "template type argument provided to toml::node::ref() didn't match the node's actual type");
|
||||
|
||||
using node_ref = std::remove_volatile_t<std::remove_reference_t<N>>&;
|
||||
using val_type = std::remove_volatile_t<unwrapped_type>;
|
||||
using out_ref = ref_type<T, N&&>;
|
||||
static_assert(std::is_reference_v<out_ref>);
|
||||
|
||||
if constexpr (toml::is_value<unwrapped_type>)
|
||||
return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>().get());
|
||||
else
|
||||
return static_cast<N&&>(n).template ref_cast<type>();
|
||||
return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>());
|
||||
}
|
||||
|
||||
protected:
|
||||
node() noexcept = default;
|
||||
|
||||
TOML_API
|
||||
node(const node&) noexcept;
|
||||
|
||||
TOML_API
|
||||
node(node&&) noexcept;
|
||||
|
||||
TOML_API
|
||||
node& operator=(const node&) noexcept;
|
||||
|
||||
TOML_API
|
||||
node& operator=(node&&) noexcept;
|
||||
|
||||
template <typename T, typename N>
|
||||
using ref_cast_type_ = std::conditional_t< //
|
||||
std::is_reference_v<T>, //
|
||||
impl::copy_ref<impl::copy_cv<impl::wrap_node<T>, std::remove_reference_t<N>>, T>, //
|
||||
impl::copy_cvref<impl::wrap_node<T>, N> //
|
||||
>;
|
||||
|
||||
template <typename T, typename N>
|
||||
using ref_cast_type = std::conditional_t< //
|
||||
std::is_reference_v<N>, //
|
||||
ref_cast_type_<T, N>, //
|
||||
ref_cast_type_<T, std::add_lvalue_reference_t<N>> //
|
||||
>;
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
ref_cast_type<T, node&> ref_cast() & noexcept
|
||||
{
|
||||
using out_ref = ref_cast_type<T, node&>;
|
||||
using out_type = std::remove_reference_t<out_ref>;
|
||||
return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
ref_cast_type<T, node&&> ref_cast() && noexcept
|
||||
{
|
||||
using out_ref = ref_cast_type<T, node&&>;
|
||||
using out_type = std::remove_reference_t<out_ref>;
|
||||
return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
ref_cast_type<T, const node&> ref_cast() const& noexcept
|
||||
{
|
||||
using out_ref = ref_cast_type<T, const node&>;
|
||||
using out_type = std::remove_reference_t<out_ref>;
|
||||
return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
ref_cast_type<T, const node&&> ref_cast() const&& noexcept
|
||||
{
|
||||
using out_ref = ref_cast_type<T, const node&&>;
|
||||
using out_type = std::remove_reference_t<out_ref>;
|
||||
return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
protected:
|
||||
node() noexcept = default;
|
||||
node(const node&) noexcept;
|
||||
node(node&&) noexcept;
|
||||
node& operator=(const node&) noexcept;
|
||||
node& operator=(node&&) noexcept;
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(pure)
|
||||
impl::wrap_node<T>& ref_cast() & noexcept
|
||||
{
|
||||
return *reinterpret_cast<impl::wrap_node<T>*>(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(pure)
|
||||
impl::wrap_node<T>&& ref_cast() && noexcept
|
||||
{
|
||||
return std::move(*reinterpret_cast<impl::wrap_node<T>*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(pure)
|
||||
const impl::wrap_node<T>& ref_cast() const& noexcept
|
||||
{
|
||||
return *reinterpret_cast<const impl::wrap_node<T>*>(this);
|
||||
}
|
||||
|
||||
template <typename N, typename T>
|
||||
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
|
||||
|
||||
public:
|
||||
virtual ~node() noexcept = default;
|
||||
TOML_API
|
||||
virtual ~node() noexcept;
|
||||
|
||||
/// \name Type checks
|
||||
/// @{
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_ICC || TOML_ICC_CL
|
||||
|
||||
/// \brief Returns the node's type identifier.
|
||||
TOML_NODISCARD
|
||||
virtual node_type type() const noexcept = 0;
|
||||
|
||||
#else
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual node_type type() const noexcept
|
||||
{
|
||||
// Q: "what the fuck?"
|
||||
// A: https://github.com/marzer/tomlplusplus/issues/83
|
||||
// tl,dr: go home ICC, you're drunk.
|
||||
|
||||
return type();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Returns true if this node is a table.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_table() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is an array.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_array() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_value() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a string value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_string() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is an integer value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_integer() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is an floating-point value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_floating_point() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is an integer or floating-point value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_number() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is a boolean value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_boolean() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is a local date value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_date() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is a local time value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_time() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is a date-time value.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_date_time() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns true if this node is an array containing only tables.
|
||||
TOML_NODISCARD
|
||||
virtual bool is_array_of_tables() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Checks if a node is a specific type.
|
||||
///
|
||||
/// \tparam T A TOML node or value type.
|
||||
///
|
||||
/// \returns Returns true if this node is an instance of the specified type.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
bool is() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
|
||||
"The template type argument of node::is() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
if constexpr (std::is_same_v<type, table>)
|
||||
return is_table();
|
||||
else if constexpr (std::is_same_v<type, array>)
|
||||
return is_array();
|
||||
else if constexpr (std::is_same_v<type, std::string>)
|
||||
return is_string();
|
||||
else if constexpr (std::is_same_v<type, int64_t>)
|
||||
return is_integer();
|
||||
else if constexpr (std::is_same_v<type, double>)
|
||||
return is_floating_point();
|
||||
else if constexpr (std::is_same_v<type, bool>)
|
||||
return is_boolean();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
return is_date();
|
||||
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();
|
||||
}
|
||||
|
||||
/// \brief Checks if a node contains values/elements of only one type.
|
||||
///
|
||||
/// \detail \cpp
|
||||
@ -246,11 +169,11 @@ TOML_NAMESPACE_START
|
||||
/// \returns True if the node was homogeneous.
|
||||
///
|
||||
/// \remarks Always returns `false` for empty tables and arrays.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept = 0;
|
||||
|
||||
/// \brief Checks if a node contains values/elements of only one type (const overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept = 0;
|
||||
|
||||
/// \brief Checks if the node contains values/elements of only one type.
|
||||
@ -261,7 +184,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "all floats: "sv << arr.is_homogeneous(toml::node_type::floating_point) << "\n";
|
||||
/// std::cout << "all arrays: "sv << arr.is_homogeneous(toml::node_type::array) << "\n";
|
||||
/// std::cout << "all ints: "sv << arr.is_homogeneous(toml::node_type::integer) << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -280,7 +202,7 @@ TOML_NAMESPACE_START
|
||||
/// \returns True if the node was homogeneous.
|
||||
///
|
||||
/// \remarks Always returns `false` for empty tables and arrays.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_homogeneous(node_type ntype) const noexcept = 0;
|
||||
|
||||
/// \brief Checks if the node contains values/elements of only one type.
|
||||
@ -291,7 +213,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "all doubles: "sv << arr.is_homogeneous<double>() << "\n";
|
||||
/// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << "\n";
|
||||
/// std::cout << "all integers: "sv << arr.is_homogeneous<int64_t>() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -311,17 +232,101 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \remarks Always returns `false` for empty tables and arrays.
|
||||
template <typename ElemType = void>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
std::is_void_v<
|
||||
type> || ((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>),
|
||||
"The template type argument of node::is_homogeneous() must be void or one "
|
||||
"of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
return is_homogeneous(impl::node_type_of<type>);
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<ElemType>>;
|
||||
static_assert(std::is_void_v<unwrapped_type> //
|
||||
|| (toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>),
|
||||
"The template type argument of node::is_homogeneous() must be void or one "
|
||||
"of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
return is_homogeneous(impl::node_type_of<unwrapped_type>);
|
||||
}
|
||||
|
||||
/// \brief Returns the node's type identifier.
|
||||
TOML_PURE_GETTER
|
||||
virtual node_type type() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a table.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_table() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is an array.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_array() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is an array containing only tables.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_array_of_tables() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_value() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a string value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_string() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is an integer value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_integer() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is an floating-point value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_floating_point() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is an integer or floating-point value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_number() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a boolean value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_boolean() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a local date value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_date() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a local time value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_time() const noexcept = 0;
|
||||
|
||||
/// \brief Returns true if this node is a date-time value.
|
||||
TOML_PURE_GETTER
|
||||
virtual bool is_date_time() const noexcept = 0;
|
||||
|
||||
/// \brief Checks if a node is a specific type.
|
||||
///
|
||||
/// \tparam T A TOML node or value type.
|
||||
///
|
||||
/// \returns Returns true if this node is an instance of the specified type.
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool is() const noexcept
|
||||
{
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
|
||||
static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
|
||||
"The template type argument of node::is() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
if constexpr (std::is_same_v<unwrapped_type, table>)
|
||||
return is_table();
|
||||
else if constexpr (std::is_same_v<unwrapped_type, array>)
|
||||
return is_array();
|
||||
else if constexpr (std::is_same_v<unwrapped_type, std::string>)
|
||||
return is_string();
|
||||
else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
|
||||
return is_integer();
|
||||
else if constexpr (std::is_same_v<unwrapped_type, double>)
|
||||
return is_floating_point();
|
||||
else if constexpr (std::is_same_v<unwrapped_type, bool>)
|
||||
return is_boolean();
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date>)
|
||||
return is_date();
|
||||
else if constexpr (std::is_same_v<unwrapped_type, time>)
|
||||
return is_time();
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date_time>)
|
||||
return is_date_time();
|
||||
}
|
||||
|
||||
/// @}
|
||||
@ -330,121 +335,76 @@ TOML_NAMESPACE_START
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::table, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual table* as_table() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
TOML_PURE_GETTER
|
||||
virtual table* as_table() noexcept = 0;
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::array, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual array* as_array() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
TOML_PURE_GETTER
|
||||
virtual array* as_array() noexcept = 0;
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<string>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<std::string>* as_string() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a pointer to the node as a toml::value<std::string>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual toml::value<std::string>* as_string() noexcept = 0;
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<int64_t>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<int64_t>* as_integer() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
TOML_PURE_GETTER
|
||||
virtual toml::value<int64_t>* as_integer() noexcept = 0;
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<double>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<double>* as_floating_point() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
TOML_PURE_GETTER
|
||||
virtual toml::value<double>* as_floating_point() noexcept = 0;
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<bool>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<bool>* as_boolean() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
TOML_PURE_GETTER
|
||||
virtual toml::value<bool>* as_boolean() noexcept = 0;
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<date>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<date>* as_date() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a pointer to the node as a toml::value<toml::date>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual toml::value<date>* as_date() noexcept = 0;
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<time>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<time>* as_time() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a pointer to the node as a toml::value<toml::time>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual toml::value<time>* as_time() noexcept = 0;
|
||||
|
||||
/// \brief Returns a pointer to the node as a toml::value<date_time>, if it is one.
|
||||
TOML_NODISCARD
|
||||
virtual toml::value<date_time>* as_date_time() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a pointer to the node as a toml::value<toml::date_time>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual toml::value<date_time>* as_date_time() noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const table* as_table() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::table, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const table* as_table() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const array* as_array() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::array, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const array* as_array() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<std::string>* as_string() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::value<std::string>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const toml::value<std::string>* as_string() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<int64_t>* as_integer() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::value<int64_t>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const toml::value<int64_t>* as_integer() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<double>* as_floating_point() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::value<double>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const toml::value<double>* as_floating_point() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<bool>* as_boolean() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::value<bool>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const toml::value<bool>* as_boolean() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<date>* as_date() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::value<toml::date>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const toml::value<date>* as_date() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<time>* as_time() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::value<toml::time>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const toml::value<time>* as_time() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const toml::value<date_time>* as_date_time() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// \brief Returns a const-qualified pointer to the node as a toml::value<toml::date_time>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
virtual const toml::value<date_time>* as_date_time() const noexcept = 0;
|
||||
|
||||
/// \brief Gets a pointer to the node as a more specific node type.
|
||||
///
|
||||
@ -461,68 +421,65 @@ TOML_NAMESPACE_START
|
||||
/// toml::value<int64_t>* int_value2 = node->as<toml::value<int64_t>>();
|
||||
/// if (int_value2)
|
||||
/// std::cout << "Node is a value<int64_t>\n";
|
||||
///
|
||||
/// \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>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
TOML_PURE_INLINE_GETTER
|
||||
impl::wrap_node<T>* as() noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
|
||||
static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
|
||||
"The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
if constexpr (std::is_same_v<type, table>)
|
||||
if constexpr (std::is_same_v<unwrapped_type, table>)
|
||||
return as_table();
|
||||
else if constexpr (std::is_same_v<type, array>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, array>)
|
||||
return as_array();
|
||||
else if constexpr (std::is_same_v<type, std::string>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, std::string>)
|
||||
return as_string();
|
||||
else if constexpr (std::is_same_v<type, int64_t>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
|
||||
return as_integer();
|
||||
else if constexpr (std::is_same_v<type, double>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, double>)
|
||||
return as_floating_point();
|
||||
else if constexpr (std::is_same_v<type, bool>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, bool>)
|
||||
return as_boolean();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date>)
|
||||
return as_date();
|
||||
else if constexpr (std::is_same_v<type, time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, time>)
|
||||
return as_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_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>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const impl::wrap_node<T>* as() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
|
||||
static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
|
||||
"The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
if constexpr (std::is_same_v<type, table>)
|
||||
if constexpr (std::is_same_v<unwrapped_type, table>)
|
||||
return as_table();
|
||||
else if constexpr (std::is_same_v<type, array>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, array>)
|
||||
return as_array();
|
||||
else if constexpr (std::is_same_v<type, std::string>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, std::string>)
|
||||
return as_string();
|
||||
else if constexpr (std::is_same_v<type, int64_t>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
|
||||
return as_integer();
|
||||
else if constexpr (std::is_same_v<type, double>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, double>)
|
||||
return as_floating_point();
|
||||
else if constexpr (std::is_same_v<type, bool>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, bool>)
|
||||
return as_boolean();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date>)
|
||||
return as_date();
|
||||
else if constexpr (std::is_same_v<type, time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, time>)
|
||||
return as_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date_time>)
|
||||
return as_date_time();
|
||||
}
|
||||
|
||||
@ -545,7 +502,7 @@ TOML_NAMESPACE_START
|
||||
/// \see node::value()
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
optional<T> value_exact() const noexcept;
|
||||
optional<T> value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>);
|
||||
|
||||
/// \brief Gets the value contained by this node.
|
||||
///
|
||||
@ -675,7 +632,7 @@ TOML_NAMESPACE_START
|
||||
/// \see node::value_exact()
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
optional<T> value() const noexcept;
|
||||
optional<T> value() const noexcept(impl::value_retrieval_is_nothrow<T>);
|
||||
|
||||
/// \brief Gets the raw value contained by this node, or a default.
|
||||
///
|
||||
@ -696,17 +653,9 @@ TOML_NAMESPACE_START
|
||||
/// - node::value_exact()
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
auto value_or(T&& default_value) const noexcept;
|
||||
auto value_or(T&& default_value) const noexcept(impl::value_retrieval_is_nothrow<T>);
|
||||
|
||||
// template <typename T>
|
||||
// TOML_NODISCARD
|
||||
// std::vector<T> select_exact() const noexcept;
|
||||
|
||||
// template <typename T>
|
||||
// TOML_NODISCARD
|
||||
// std::vector<T> select() const noexcept;
|
||||
|
||||
/// \brief Gets a raw reference to a value node's underlying data.
|
||||
/// \brief Gets a raw reference to a node's underlying data.
|
||||
///
|
||||
/// \warning This function is dangerous if used carelessly and **WILL** break your code if the
|
||||
/// chosen value type doesn't match the node's actual type. In debug builds an assertion
|
||||
@ -717,47 +666,61 @@ TOML_NAMESPACE_START
|
||||
/// max = 45
|
||||
/// )"sv);
|
||||
///
|
||||
/// int64_t& min_ref = tbl.get("min")->ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl.get("max")->ref<double>(); // mismatched type, hits assert()
|
||||
///
|
||||
/// int64_t& min_ref = tbl.at("min").ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl.at("max").ref<double>(); // mismatched type, hits assert()
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam T One of the TOML value types.
|
||||
/// \note Specifying explicit ref qualifiers acts as an explicit ref-category cast,
|
||||
/// whereas specifying explicit cv-ref qualifiers merges them with whatever
|
||||
/// the cv qualification of the node is (to ensure cv-correctness is propagated), e.g.:
|
||||
/// | node | T | return type |
|
||||
/// |-------------|------------------------|------------------------------|
|
||||
/// | node& | std::string | std::string& |
|
||||
/// | node& | std::string&& | std::string&& |
|
||||
/// | const node& | volatile std::string | const volatile std::string& |
|
||||
/// | const node& | volatile std::string&& | const volatile std::string&& |
|
||||
///
|
||||
/// \tparam T toml::table, toml::array, or one of the TOML value types.
|
||||
///
|
||||
/// \returns A reference to the underlying data.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
impl::unwrap_node<T>& ref() & noexcept
|
||||
TOML_PURE_GETTER
|
||||
decltype(auto) ref() & noexcept
|
||||
{
|
||||
return do_ref<T>(*this);
|
||||
}
|
||||
|
||||
/// \brief Gets a raw reference to a value node's underlying data (rvalue overload).
|
||||
/// \brief Gets a raw reference to a node's underlying data (rvalue overload).
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
impl::unwrap_node<T>&& ref() && noexcept
|
||||
TOML_PURE_GETTER
|
||||
decltype(auto) ref() && noexcept
|
||||
{
|
||||
return do_ref<T>(std::move(*this));
|
||||
}
|
||||
|
||||
/// \brief Gets a raw reference to a value node's underlying data (const lvalue overload).
|
||||
/// \brief Gets a raw reference to a node's underlying data (const lvalue overload).
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
const impl::unwrap_node<T>& ref() const& noexcept
|
||||
TOML_PURE_GETTER
|
||||
decltype(auto) ref() const& noexcept
|
||||
{
|
||||
return do_ref<T>(*this);
|
||||
}
|
||||
|
||||
/// \brief Gets a raw reference to a node's underlying data (const rvalue overload).
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
decltype(auto) ref() const&& noexcept
|
||||
{
|
||||
return do_ref<T>(std::move(*this));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Metadata
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the source region responsible for generating this node during parsing.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
@ -771,7 +734,7 @@ TOML_NAMESPACE_START
|
||||
// clang-format off
|
||||
|
||||
template <typename Func, typename N, typename T>
|
||||
static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<N, T>>;
|
||||
static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<T, N>>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
static constexpr bool can_visit_any =
|
||||
@ -800,7 +763,7 @@ TOML_NAMESPACE_START
|
||||
template <typename Func, typename N, typename T>
|
||||
static constexpr bool visit_is_nothrow_one =
|
||||
!can_visit<Func, N, T>
|
||||
|| std::is_nothrow_invocable_v<Func, ref_cast_type<N, T>>;
|
||||
|| std::is_nothrow_invocable_v<Func, ref_cast_type<T, N>>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
static constexpr bool visit_is_nothrow =
|
||||
@ -819,7 +782,7 @@ TOML_NAMESPACE_START
|
||||
template <typename Func, typename N, typename T, bool = can_visit<Func, N, T>>
|
||||
struct visit_return_type_
|
||||
{
|
||||
using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<N, T>>()));
|
||||
using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<T, N>>()));
|
||||
};
|
||||
template <typename Func, typename N, typename T>
|
||||
struct visit_return_type_<Func, N, T, false>
|
||||
@ -946,7 +909,6 @@ TOML_NAMESPACE_START
|
||||
/// else
|
||||
/// throw std::exception{ "Expected string or integer" };
|
||||
/// });
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam Func A callable type invocable with one or more of the
|
||||
@ -978,6 +940,13 @@ TOML_NAMESPACE_START
|
||||
return do_visit(*this, static_cast<Func&&>(visitor));
|
||||
}
|
||||
|
||||
/// \brief Invokes a visitor on the node based on the node's concrete type (const rvalue overload).
|
||||
template <typename Func>
|
||||
decltype(auto) visit(Func&& visitor) const&& noexcept(visit_is_nothrow<Func&&, const node&&>)
|
||||
{
|
||||
return do_visit(static_cast<const node&&>(*this), static_cast<Func&&>(visitor));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Node views
|
||||
@ -991,7 +960,55 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
explicit operator node_view<const node>() const noexcept;
|
||||
|
||||
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<node> at_path(std::string_view path) noexcept;
|
||||
|
||||
/// \brief Returns a const view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<const node> at_path(std::string_view path) const noexcept;
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<node> at_path(std::wstring_view path);
|
||||
|
||||
/// \brief Returns a const view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<const node> at_path(std::wstring_view path) const;
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// @}
|
||||
};
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_PURE_GETTER
|
||||
TOML_API
|
||||
bool node_deep_equality(const node*, const node*) noexcept;
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
#include "header_end.h"
|
||||
|
116
include/toml++/impl/node.inl
Normal file
116
include/toml++/impl/node.inl
Normal file
@ -0,0 +1,116 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "node.h"
|
||||
#include "node_view.h"
|
||||
#include "at_path.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "value.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node::node(node && other) noexcept //
|
||||
: source_{ std::exchange(other.source_, {}) }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node::node(const node& /*other*/) noexcept
|
||||
{
|
||||
// does not copy source information - this is not an error
|
||||
//
|
||||
// see https://github.com/marzer/tomlplusplus/issues/49#issuecomment-665089577
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node& node::operator=(const node& /*rhs*/) noexcept
|
||||
{
|
||||
// does not copy source information - this is not an error
|
||||
//
|
||||
// see https://github.com/marzer/tomlplusplus/issues/49#issuecomment-665089577
|
||||
|
||||
source_ = {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node& node::operator=(node&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
source_ = std::exchange(rhs.source_, {});
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node::~node() noexcept = default;
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<node> node::at_path(std::string_view path) noexcept
|
||||
{
|
||||
return toml::at_path(*this, path);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<const node> node::at_path(std::string_view path) const noexcept
|
||||
{
|
||||
return toml::at_path(*this, path);
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<node> node::at_path(std::wstring_view path)
|
||||
{
|
||||
return toml::at_path(*this, path);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<const node> node::at_path(std::wstring_view path) const
|
||||
{
|
||||
return toml::at_path(*this, path);
|
||||
}
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool node_deep_equality(const node* lhs, const node* rhs) noexcept
|
||||
{
|
||||
// both same or both null
|
||||
if (lhs == rhs)
|
||||
return true;
|
||||
|
||||
// lhs null != rhs null or different types
|
||||
if ((!lhs != !rhs) || lhs->type() != rhs->type())
|
||||
return false;
|
||||
|
||||
bool same;
|
||||
lhs->visit(
|
||||
[=, &same](auto& l) noexcept
|
||||
{
|
||||
using concrete_type = remove_cvref<decltype(l)>;
|
||||
|
||||
same = (l == *(rhs->as<concrete_type>()));
|
||||
});
|
||||
|
||||
return same;
|
||||
}
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
@ -1,62 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "node.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node::node(node && other) noexcept //
|
||||
: source_{ std::exchange(other.source_, {}) }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node::node(const node& /*other*/) noexcept
|
||||
{
|
||||
// does not copy source information - this is not an error
|
||||
//
|
||||
// see https://github.com/marzer/tomlplusplus/issues/49#issuecomment-665089577
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node& node::operator=(const node& /*rhs*/) noexcept
|
||||
{
|
||||
// does not copy source information - this is not an error
|
||||
//
|
||||
// see https://github.com/marzer/tomlplusplus/issues/49#issuecomment-665089577
|
||||
|
||||
source_ = {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node& node::operator=(node&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
source_ = std::exchange(rhs.source_, {});
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node::operator node_view<node>() noexcept
|
||||
{
|
||||
return node_view<node>(this);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node::operator node_view<const node>() const noexcept
|
||||
{
|
||||
return node_view<const node>(this);
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
@ -2,13 +2,13 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "value.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
#include "std_vector.h"
|
||||
#include "std_initializer_list.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "node.h"
|
||||
#include "header_start.h"
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
@ -57,17 +57,18 @@ TOML_NAMESPACE_START
|
||||
/// product[2]:
|
||||
/// \eout
|
||||
template <typename ViewedType>
|
||||
class TOML_API TOML_TRIVIAL_ABI node_view
|
||||
class TOML_TRIVIAL_ABI node_view
|
||||
{
|
||||
static_assert(impl::is_one_of<ViewedType, toml::node, const toml::node>,
|
||||
"A toml::node_view<> must wrap toml::node or const toml::node.");
|
||||
|
||||
public:
|
||||
/// \brief The node type being viewed - either `node` or `const node`.
|
||||
using viewed_type = ViewedType;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class TOML_NAMESPACE::node_view;
|
||||
friend class node_view;
|
||||
|
||||
mutable viewed_type* node_ = nullptr;
|
||||
|
||||
@ -95,25 +96,25 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD_CTOR
|
||||
node_view(const node_view&) noexcept = default;
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
node_view& operator=(const node_view&) & noexcept = default;
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
node_view(node_view&&) noexcept = default;
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
node_view& operator=(const node_view&) & noexcept = default;
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
node_view& operator=(node_view&&) & noexcept = default;
|
||||
|
||||
/// \brief Returns true if the view references a node.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return node_ != nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns the node that's being referenced by the view.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
viewed_type* node() const noexcept
|
||||
{
|
||||
return node_;
|
||||
@ -123,91 +124,91 @@ TOML_NAMESPACE_START
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the type identifier for the viewed node.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
node_type type() const noexcept
|
||||
{
|
||||
return node_ ? node_->type() : node_type::none;
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::table.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_table() const noexcept
|
||||
{
|
||||
return node_ && node_->is_table();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::array.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_array() const noexcept
|
||||
{
|
||||
return node_ && node_->is_array();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_value() const noexcept
|
||||
{
|
||||
return node_ && node_->is_value();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<string>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_string() const noexcept
|
||||
{
|
||||
return node_ && node_->is_string();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<int64_t>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_integer() const noexcept
|
||||
{
|
||||
return node_ && node_->is_integer();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<double>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_floating_point() const noexcept
|
||||
{
|
||||
return node_ && node_->is_floating_point();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<int64_t> or toml::value<double>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_number() const noexcept
|
||||
{
|
||||
return node_ && node_->is_number();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<bool>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_boolean() const noexcept
|
||||
{
|
||||
return node_ && node_->is_boolean();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<date>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_date() const noexcept
|
||||
{
|
||||
return node_ && node_->is_date();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<time>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_time() const noexcept
|
||||
{
|
||||
return node_ && node_->is_time();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::value<date_time>.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_date_time() const noexcept
|
||||
{
|
||||
return node_ && node_->is_date_time();
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::array that contains only tables.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_array_of_tables() const noexcept
|
||||
{
|
||||
return node_ && node_->is_array_of_tables();
|
||||
@ -221,10 +222,10 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \see toml::node::is()
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is() const noexcept
|
||||
{
|
||||
return node_ ? node_->template is<T>() : false;
|
||||
return node_ ? node_->template is<impl::unwrap_node<impl::remove_cvref<T>>>() : false;
|
||||
}
|
||||
|
||||
/// \brief Checks if the viewed node contains values/elements of only one type.
|
||||
@ -275,7 +276,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "all floats: "sv << cfg["arr"].is_homogeneous(toml::node_type::floating_point) << "\n";
|
||||
/// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous(toml::node_type::array) << "\n";
|
||||
/// std::cout << "all ints: "sv << cfg["arr"].is_homogeneous(toml::node_type::integer) << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -307,7 +307,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "all doubles: "sv << cfg["arr"].is_homogeneous<double>() << "\n";
|
||||
/// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous<toml::array>() << "\n";
|
||||
/// std::cout << "all integers: "sv << cfg["arr"].is_homogeneous<int64_t>() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -326,10 +325,10 @@ TOML_NAMESPACE_START
|
||||
/// \remarks Always returns `false` if the view does not reference a node, or if the viewed node is
|
||||
/// an empty table or array.
|
||||
template <typename ElemType = void>
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
return node_ ? node_->template is_homogeneous<impl::unwrap_node<ElemType>>() : false;
|
||||
return node_ ? node_->template is_homogeneous<impl::unwrap_node<impl::remove_cvref<ElemType>>>() : false;
|
||||
}
|
||||
|
||||
/// @}
|
||||
@ -337,69 +336,6 @@ TOML_NAMESPACE_START
|
||||
/// \name Type casts
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::table, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_table() const noexcept
|
||||
{
|
||||
return as<table>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::array, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_array() const noexcept
|
||||
{
|
||||
return as<array>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<string>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_string() const noexcept
|
||||
{
|
||||
return as<std::string>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<int64_t>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_integer() const noexcept
|
||||
{
|
||||
return as<int64_t>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<double>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_floating_point() const noexcept
|
||||
{
|
||||
return as<double>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<bool>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_boolean() const noexcept
|
||||
{
|
||||
return as<bool>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_date() const noexcept
|
||||
{
|
||||
return as<date>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<time>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_time() const noexcept
|
||||
{
|
||||
return as<time>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date_time>, if it is one.
|
||||
TOML_NODISCARD
|
||||
auto as_date_time() const noexcept
|
||||
{
|
||||
return as<date_time>();
|
||||
}
|
||||
|
||||
/// \brief Gets a pointer to the viewed node as a more specific node type.
|
||||
///
|
||||
/// \tparam T The node type or TOML value type to cast to.
|
||||
@ -408,12 +344,75 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \see toml::node::as()
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
auto as() const noexcept
|
||||
TOML_PURE_GETTER
|
||||
auto* as() const noexcept
|
||||
{
|
||||
return node_ ? node_->template as<T>() : nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::table, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_table() const noexcept
|
||||
{
|
||||
return as<table>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::array, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_array() const noexcept
|
||||
{
|
||||
return as<array>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<string>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_string() const noexcept
|
||||
{
|
||||
return as<std::string>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<int64_t>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_integer() const noexcept
|
||||
{
|
||||
return as<int64_t>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<double>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_floating_point() const noexcept
|
||||
{
|
||||
return as<double>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<bool>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_boolean() const noexcept
|
||||
{
|
||||
return as<bool>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_date() const noexcept
|
||||
{
|
||||
return as<date>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<time>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_time() const noexcept
|
||||
{
|
||||
return as<time>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date_time>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto* as_date_time() const noexcept
|
||||
{
|
||||
return as<date_time>();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Value retrieval
|
||||
@ -433,16 +432,13 @@ TOML_NAMESPACE_START
|
||||
/// \see node_view::value()
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
optional<T> value_exact() const noexcept
|
||||
optional<T> value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>)
|
||||
{
|
||||
if (node_)
|
||||
return node_->template value_exact<T>();
|
||||
return {};
|
||||
}
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_INIT_WARNINGS;
|
||||
|
||||
/// \brief Gets the value contained by the referenced node.
|
||||
///
|
||||
/// \detail This function has 'permissive' retrieval semantics; some value types are allowed
|
||||
@ -464,15 +460,13 @@ TOML_NAMESPACE_START
|
||||
/// - node_view::value_exact()
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
optional<T> value() const noexcept
|
||||
optional<T> value() const noexcept(impl::value_retrieval_is_nothrow<T>)
|
||||
{
|
||||
if (node_)
|
||||
return node_->template value<T>();
|
||||
return {};
|
||||
}
|
||||
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
/// \brief Gets the raw value contained by the referenced node, or a default.
|
||||
///
|
||||
/// \tparam T Default value type. Must be one of the native TOML value types,
|
||||
@ -492,17 +486,17 @@ TOML_NAMESPACE_START
|
||||
/// - node_view::value_exact()
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
auto value_or(T&& default_value) const noexcept
|
||||
auto value_or(T&& default_value) const noexcept(impl::value_retrieval_is_nothrow<T>)
|
||||
{
|
||||
using namespace ::toml::impl;
|
||||
|
||||
static_assert(!is_wide_string<T> || TOML_WINDOWS_COMPAT,
|
||||
static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
|
||||
"Retrieving values as wide-character strings is only "
|
||||
"supported on Windows with TOML_WINDOWS_COMPAT enabled.");
|
||||
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
|
||||
|
||||
if constexpr (is_wide_string<T>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
if (node_)
|
||||
return node_->value_or(static_cast<T&&>(default_value));
|
||||
@ -544,18 +538,28 @@ TOML_NAMESPACE_START
|
||||
/// int64_t& min_ref = tbl["min"].ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl["max"].ref<double>(); // mismatched type, hits assert()
|
||||
/// int64_t& foo_ref = tbl["foo"].ref<int64_t>(); // nonexistent key, hits assert()
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \note Specifying explicit ref qualifiers acts as an explicit ref-category cast,
|
||||
/// whereas specifying explicit cv-ref qualifiers merges them with whatever
|
||||
/// the cv qualification of the viewed node is (to ensure cv-correctness is propagated), e.g.:
|
||||
/// | node_view | T | return type |
|
||||
/// |-----------------------|------------------------|------------------------------|
|
||||
/// | node_view<node> | std::string | std::string& |
|
||||
/// | node_view<node> | std::string&& | std::string&& |
|
||||
/// | node_view<const node> | volatile std::string | const volatile std::string& |
|
||||
/// | node_view<const node> | volatile std::string&& | const volatile std::string&& |
|
||||
///
|
||||
///
|
||||
/// \tparam T One of the TOML value types.
|
||||
///
|
||||
/// \returns A reference to the underlying data.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
decltype(auto) ref() const noexcept
|
||||
{
|
||||
TOML_ASSERT(node_ && "toml::node_view::ref() called on a node_view that did not reference a node");
|
||||
return node_->template ref<impl::unwrap_node<T>>();
|
||||
TOML_ASSERT_ASSUME(node_ && "toml::node_view::ref() called on a node_view that did not reference a node");
|
||||
return node_->template ref<T>();
|
||||
}
|
||||
|
||||
/// @}
|
||||
@ -583,6 +587,23 @@ TOML_NAMESPACE_START
|
||||
/// \name Equality
|
||||
/// @{
|
||||
|
||||
public:
|
||||
/// \brief Returns true if the two views refer to nodes of the same type and value.
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
friend bool operator==(const node_view& lhs, const node_view<T>& rhs) noexcept
|
||||
{
|
||||
return impl::node_deep_equality(lhs.node_, rhs.node_);
|
||||
}
|
||||
|
||||
/// \brief Returns true if the two views do not refer to nodes of the same type and value.
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
friend bool operator!=(const node_view& lhs, const node_view<T>& rhs) noexcept
|
||||
{
|
||||
return !impl::node_deep_equality(lhs.node_, rhs.node_);
|
||||
}
|
||||
|
||||
/// \brief Returns true if the viewed node is a table with the same contents as RHS.
|
||||
TOML_NODISCARD
|
||||
friend bool operator==(const node_view& lhs, const table& rhs) noexcept
|
||||
@ -618,17 +639,17 @@ TOML_NAMESPACE_START
|
||||
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const toml::value<T>&, template <typename T>);
|
||||
|
||||
/// \brief Returns true if the viewed node is a value with the same value as RHS.
|
||||
TOML_CONSTRAINED_TEMPLATE((impl::is_native<T> || impl::is_losslessly_convertible_to_native<T>), typename T)
|
||||
TOML_CONSTRAINED_TEMPLATE(impl::is_losslessly_convertible_to_native<T>, typename T)
|
||||
TOML_NODISCARD
|
||||
friend bool operator==(const node_view& lhs, const T& rhs) noexcept
|
||||
friend bool operator==(const node_view& lhs, const T& rhs) noexcept(!impl::is_wide_string<T>)
|
||||
{
|
||||
static_assert(!impl::is_wide_string<T> || TOML_WINDOWS_COMPAT,
|
||||
static_assert(!impl::is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
|
||||
"Comparison with wide-character strings is only "
|
||||
"supported on Windows with TOML_WINDOWS_COMPAT enabled.");
|
||||
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
|
||||
|
||||
if constexpr (impl::is_wide_string<T>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
return lhs == impl::narrow(rhs);
|
||||
#else
|
||||
static_assert(impl::dependent_false<T>, "Evaluated unreachable branch!");
|
||||
@ -640,16 +661,16 @@ TOML_NAMESPACE_START
|
||||
return val && *val == rhs;
|
||||
}
|
||||
}
|
||||
TOML_ASYMMETRICAL_EQUALITY_OPS(
|
||||
const node_view&,
|
||||
const T&,
|
||||
TOML_CONSTRAINED_TEMPLATE((impl::is_native<T> || impl::is_losslessly_convertible_to_native<T>),
|
||||
typename T));
|
||||
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&,
|
||||
const T&,
|
||||
TOML_CONSTRAINED_TEMPLATE(impl::is_losslessly_convertible_to_native<T>,
|
||||
typename T));
|
||||
|
||||
/// \brief Returns true if the viewed node is an array with the same contents as the RHS initializer list.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
friend bool operator==(const node_view& lhs, const std::initializer_list<T>& rhs) noexcept
|
||||
friend bool operator==(const node_view& lhs,
|
||||
const std::initializer_list<T>& rhs) noexcept(!impl::is_wide_string<T>)
|
||||
{
|
||||
const auto arr = lhs.as<array>();
|
||||
return arr && *arr == rhs;
|
||||
@ -659,7 +680,7 @@ TOML_NAMESPACE_START
|
||||
/// \brief Returns true if the viewed node is an array with the same contents as the RHS vector.
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
friend bool operator==(const node_view& lhs, const std::vector<T>& rhs) noexcept
|
||||
friend bool operator==(const node_view& lhs, const std::vector<T>& rhs) noexcept(!impl::is_wide_string<T>)
|
||||
{
|
||||
const auto arr = lhs.as<array>();
|
||||
return arr && *arr == rhs;
|
||||
@ -682,28 +703,48 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (auto tbl = this->as_table())
|
||||
return node_view{ tbl->get(key) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
node_view at_path(std::string_view path) const noexcept
|
||||
{
|
||||
return node_ ? node_->at_path(path) : node_view{};
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns a view of the selected subnode.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \param key The key of the node to retrieve
|
||||
///
|
||||
/// \returns A view of the selected node if this node represented a table and it contained a
|
||||
/// value at the given key, or an empty view.
|
||||
TOML_NODISCARD
|
||||
node_view operator[](std::wstring_view key) const noexcept
|
||||
node_view operator[](std::wstring_view key) const
|
||||
{
|
||||
if (auto tbl = this->as_table())
|
||||
return node_view{ tbl->get(key) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
node_view at_path(std::wstring_view path) const
|
||||
{
|
||||
return node_ ? node_->at_path(path) : node_view{};
|
||||
}
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns a view of the selected subnode.
|
||||
///
|
||||
@ -716,100 +757,62 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (auto arr = this->as_array())
|
||||
return node_view{ arr->get(index) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
template <typename Char, typename T>
|
||||
friend std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>&, const node_view<T>&);
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
/// \brief Prints the viewed node out to a stream.
|
||||
///
|
||||
/// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
friend std::ostream& operator<<(std::ostream& os, const node_view& nv)
|
||||
{
|
||||
if (nv.node_)
|
||||
nv.node_->visit([&os](const auto& n) { os << n; });
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
/// \cond
|
||||
|
||||
template <typename T>
|
||||
node_view(const value<T>&) -> node_view<const node>;
|
||||
node_view(const table&)->node_view<const node>;
|
||||
node_view(const array&)->node_view<const node>;
|
||||
template <typename T>
|
||||
node_view(value<T>&) -> node_view<node>;
|
||||
node_view(table&)->node_view<node>;
|
||||
node_view(array&)->node_view<node>;
|
||||
node_view(const T&) -> node_view<const node>;
|
||||
|
||||
template <typename T>
|
||||
node_view(const T*) -> node_view<const node>;
|
||||
|
||||
template <typename T>
|
||||
node_view(T&) -> node_view<node>;
|
||||
|
||||
template <typename T>
|
||||
node_view(T*) -> node_view<node>;
|
||||
|
||||
/// \brief Prints the viewed node out to a stream.
|
||||
template <typename Char, typename T>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& os, const node_view<T>& nv)
|
||||
{
|
||||
if (nv.node_)
|
||||
{
|
||||
nv.node_->visit([&os](const auto& n) { os << n; });
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
|
||||
extern template class TOML_API node_view<node>;
|
||||
extern template class TOML_API node_view<const node>;
|
||||
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const node_view<node>&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const node_view<const node>&);
|
||||
|
||||
#define TOML_EXTERN(name, T) \
|
||||
extern template TOML_API \
|
||||
optional<T> node_view<node>::name<T>() const noexcept; \
|
||||
extern template TOML_API \
|
||||
optional<T> node_view<const node>::name<T>() const noexcept
|
||||
TOML_EXTERN(value_exact, std::string_view);
|
||||
TOML_EXTERN(value_exact, std::string);
|
||||
TOML_EXTERN(value_exact, const char*);
|
||||
TOML_EXTERN(value_exact, int64_t);
|
||||
TOML_EXTERN(value_exact, double);
|
||||
TOML_EXTERN(value_exact, date);
|
||||
TOML_EXTERN(value_exact, time);
|
||||
TOML_EXTERN(value_exact, date_time);
|
||||
TOML_EXTERN(value_exact, bool);
|
||||
TOML_EXTERN(value, std::string_view);
|
||||
TOML_EXTERN(value, std::string);
|
||||
TOML_EXTERN(value, const char*);
|
||||
TOML_EXTERN(value, signed char);
|
||||
TOML_EXTERN(value, signed short);
|
||||
TOML_EXTERN(value, signed int);
|
||||
TOML_EXTERN(value, signed long);
|
||||
TOML_EXTERN(value, signed long long);
|
||||
TOML_EXTERN(value, unsigned char);
|
||||
TOML_EXTERN(value, unsigned short);
|
||||
TOML_EXTERN(value, unsigned int);
|
||||
TOML_EXTERN(value, unsigned long);
|
||||
TOML_EXTERN(value, unsigned long long);
|
||||
TOML_EXTERN(value, double);
|
||||
TOML_EXTERN(value, float);
|
||||
TOML_EXTERN(value, date);
|
||||
TOML_EXTERN(value, time);
|
||||
TOML_EXTERN(value, date_time);
|
||||
TOML_EXTERN(value, bool);
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_EXTERN(value_exact, std::u8string_view);
|
||||
TOML_EXTERN(value_exact, std::u8string);
|
||||
TOML_EXTERN(value_exact, const char8_t*);
|
||||
TOML_EXTERN(value, std::u8string_view);
|
||||
TOML_EXTERN(value, std::u8string);
|
||||
TOML_EXTERN(value, const char8_t*);
|
||||
#endif
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
TOML_EXTERN(value_exact, std::wstring);
|
||||
TOML_EXTERN(value, std::wstring);
|
||||
#endif
|
||||
|
||||
#undef TOML_EXTERN
|
||||
|
||||
#endif // !TOML_HEADER_ONLY
|
||||
/// \endcond
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_ARITHMETIC_WARNINGS
|
||||
/// \cond
|
||||
#if TOML_EXTERN_TEMPLATES && !TOML_IMPLEMENTATION
|
||||
#include "node_view_extern.inl"
|
||||
#endif
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
inline node::operator node_view<node>() noexcept
|
||||
{
|
||||
return node_view<node>{ this };
|
||||
}
|
||||
|
||||
inline node::operator node_view<const node>() const noexcept
|
||||
{
|
||||
return node_view<const node>{ this };
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
#include "header_end.h"
|
||||
|
21
include/toml++/impl/node_view.inl
Normal file
21
include/toml++/impl/node_view.inl
Normal file
@ -0,0 +1,21 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "node_view.h"
|
||||
#include "header_start.h"
|
||||
|
||||
#if TOML_EXTERN_TEMPLATES && TOML_IMPLEMENTATION
|
||||
#include "node_view_extern.inl"
|
||||
#endif // TOML_EXTERN_TEMPLATES
|
||||
|
||||
#include "header_end.h"
|
71
include/toml++/impl/node_view_extern.inl
Normal file
71
include/toml++/impl/node_view_extern.inl
Normal file
@ -0,0 +1,71 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
/// \cond
|
||||
|
||||
#include "node_view.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERN
|
||||
template class TOML_API node_view<node>;
|
||||
TOML_EXTERN
|
||||
template class TOML_API node_view<const node>;
|
||||
|
||||
#define TOML_EXTERN_FUNC(name, T) \
|
||||
TOML_EXTERN \
|
||||
template TOML_API \
|
||||
optional<T> node_view<node>::name<T>() const TOML_EXTERN_NOEXCEPT(impl::value_retrieval_is_nothrow<T>); \
|
||||
TOML_EXTERN \
|
||||
template TOML_API \
|
||||
optional<T> node_view<const node>::name<T>() const TOML_EXTERN_NOEXCEPT(impl::value_retrieval_is_nothrow<T>)
|
||||
|
||||
TOML_EXTERN_FUNC(value_exact, std::string_view);
|
||||
TOML_EXTERN_FUNC(value_exact, std::string);
|
||||
TOML_EXTERN_FUNC(value_exact, const char*);
|
||||
TOML_EXTERN_FUNC(value_exact, int64_t);
|
||||
TOML_EXTERN_FUNC(value_exact, double);
|
||||
TOML_EXTERN_FUNC(value_exact, date);
|
||||
TOML_EXTERN_FUNC(value_exact, time);
|
||||
TOML_EXTERN_FUNC(value_exact, date_time);
|
||||
TOML_EXTERN_FUNC(value_exact, bool);
|
||||
TOML_EXTERN_FUNC(value, std::string_view);
|
||||
TOML_EXTERN_FUNC(value, std::string);
|
||||
TOML_EXTERN_FUNC(value, const char*);
|
||||
TOML_EXTERN_FUNC(value, signed char);
|
||||
TOML_EXTERN_FUNC(value, signed short);
|
||||
TOML_EXTERN_FUNC(value, signed int);
|
||||
TOML_EXTERN_FUNC(value, signed long);
|
||||
TOML_EXTERN_FUNC(value, signed long long);
|
||||
TOML_EXTERN_FUNC(value, unsigned char);
|
||||
TOML_EXTERN_FUNC(value, unsigned short);
|
||||
TOML_EXTERN_FUNC(value, unsigned int);
|
||||
TOML_EXTERN_FUNC(value, unsigned long);
|
||||
TOML_EXTERN_FUNC(value, unsigned long long);
|
||||
TOML_EXTERN_FUNC(value, double);
|
||||
TOML_EXTERN_FUNC(value, float);
|
||||
TOML_EXTERN_FUNC(value, date);
|
||||
TOML_EXTERN_FUNC(value, time);
|
||||
TOML_EXTERN_FUNC(value, date_time);
|
||||
TOML_EXTERN_FUNC(value, bool);
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_EXTERN_FUNC(value_exact, std::u8string_view);
|
||||
TOML_EXTERN_FUNC(value_exact, std::u8string);
|
||||
TOML_EXTERN_FUNC(value_exact, const char8_t*);
|
||||
TOML_EXTERN_FUNC(value, std::u8string_view);
|
||||
TOML_EXTERN_FUNC(value, std::u8string);
|
||||
TOML_EXTERN_FUNC(value, const char8_t*);
|
||||
#endif
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
TOML_EXTERN_FUNC(value_exact, std::wstring);
|
||||
TOML_EXTERN_FUNC(value, std::wstring);
|
||||
#endif
|
||||
|
||||
#undef TOML_EXTERN_FUNC
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
/// \endcond
|
@ -2,85 +2,52 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_INIT_WARNINGS;
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_PARSER
|
||||
|
||||
#include "std_except.h"
|
||||
#include "source_region.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "header_start.h"
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
|
||||
#define TOML_PARSE_ERROR_BASE
|
||||
#else
|
||||
#define TOML_PARSE_ERROR_BASE : public std::runtime_error
|
||||
#endif
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
|
||||
|
||||
/// \brief An error generated when parsing fails.
|
||||
///
|
||||
/// \remarks This class inherits from std::runtime_error when exceptions are enabled.
|
||||
/// The public interface is the same regardless of exception mode.
|
||||
class parse_error final
|
||||
class parse_error TOML_PARSE_ERROR_BASE
|
||||
{
|
||||
private:
|
||||
#if !TOML_EXCEPTIONS
|
||||
std::string description_;
|
||||
#endif
|
||||
source_region source_;
|
||||
|
||||
public:
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, source_region&& src) noexcept
|
||||
: description_{ std::move(desc) },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
#if TOML_EXCEPTIONS
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, const source_region& src) noexcept
|
||||
: parse_error{ std::move(desc), source_region{ src } }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
||||
: parse_error{ std::move(desc), source_region{ position, position, path } }
|
||||
{}
|
||||
|
||||
/// \brief Returns a textual description of the error.
|
||||
/// \remark The backing string is guaranteed to be null-terminated.
|
||||
TOML_NODISCARD
|
||||
std::string_view description() const noexcept
|
||||
{
|
||||
return description_;
|
||||
}
|
||||
|
||||
/// \brief Returns the region of the source document responsible for the error.
|
||||
TOML_NODISCARD
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class parse_error final : public std::runtime_error
|
||||
{
|
||||
private:
|
||||
source_region source_;
|
||||
|
||||
public:
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_ATTR(nonnull)
|
||||
parse_error(const char* desc, source_region&& src) noexcept
|
||||
parse_error(const char* desc, source_region&& src) noexcept //
|
||||
: std::runtime_error{ desc },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_ATTR(nonnull)
|
||||
parse_error(const char* desc, const source_region& src) noexcept : parse_error{ desc, source_region{ src } }
|
||||
parse_error(const char* desc, const source_region& src) noexcept //
|
||||
: parse_error{ desc, source_region{ src } }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
@ -89,62 +56,84 @@ TOML_NAMESPACE_START
|
||||
: parse_error{ desc, source_region{ position, position, path } }
|
||||
{}
|
||||
|
||||
#else
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, source_region&& src) noexcept //
|
||||
: description_{ std::move(desc) },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, const source_region& src) noexcept //
|
||||
: parse_error{ std::move(desc), source_region{ src } }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(std::string&& desc, const source_position& position, const source_path_ptr& path = {}) noexcept
|
||||
: parse_error{ std::move(desc), source_region{ position, position, path } }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Returns a textual description of the error.
|
||||
/// \remark The backing string is guaranteed to be null-terminated.
|
||||
TOML_NODISCARD
|
||||
std::string_view description() const noexcept
|
||||
{
|
||||
#if TOML_EXCEPTIONS
|
||||
return std::string_view{ what() };
|
||||
#else
|
||||
return description_;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Returns the region of the source document responsible for the error.
|
||||
TOML_NODISCARD
|
||||
const source_region& source() const noexcept
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
|
||||
/// \brief Prints a parse_error to a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// try
|
||||
/// {
|
||||
/// auto tbl = toml::parse("enabled = trUe"sv);
|
||||
/// }
|
||||
/// catch (const toml::parse_error & err)
|
||||
/// {
|
||||
/// std::cerr << "Parsing failed:\n"sv << err << "\n";
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// Parsing failed:
|
||||
/// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
|
||||
/// (error occurred at line 1, column 13)
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The output stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The parse_error.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const parse_error& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs.description());
|
||||
impl::print_to_stream(lhs, "\n\t(error occurred at "sv);
|
||||
impl::print_to_stream(lhs, rhs.source());
|
||||
impl::print_to_stream(lhs, ")"sv);
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
|
||||
/// \brief Prints a parse_error to a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// try
|
||||
/// {
|
||||
/// auto tbl = toml::parse("enabled = trUe"sv);
|
||||
/// }
|
||||
/// catch (const toml::parse_error & err)
|
||||
/// {
|
||||
/// std::cerr << "Parsing failed:\n"sv << err << "\n";
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// Parsing failed:
|
||||
/// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU'
|
||||
/// (error occurred at line 1, column 13)
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The output stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The parse_error.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const parse_error& rhs)
|
||||
{
|
||||
lhs << rhs.description();
|
||||
lhs << "\n\t(error occurred at "sv;
|
||||
lhs << rhs.source();
|
||||
lhs << ")"sv;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const parse_error&);
|
||||
#endif
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_INIT_WARNINGS
|
||||
#undef TOML_PARSE_ERROR_BASE
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_PARSER
|
||||
|
@ -2,34 +2,39 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
#if defined(DOXYGEN) || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
#include "table.h"
|
||||
#include "parse_error.h"
|
||||
#include "header_start.h"
|
||||
|
||||
#if defined(DOXYGEN) || !TOML_EXCEPTIONS
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_START(noex);
|
||||
|
||||
/// \brief The result of a parsing operation.
|
||||
///
|
||||
/// \availability <strong>This type only exists when exceptions are disabled.</strong>
|
||||
/// Otherwise parse_result is just an alias for toml::table: \cpp
|
||||
/// #if TOML_EXCEPTIONS
|
||||
/// using parse_result = table;
|
||||
/// #else
|
||||
/// class parse_result { // ...
|
||||
/// #endif
|
||||
/// \ecpp
|
||||
///
|
||||
/// \detail A parse_result is effectively a discriminated union containing either a toml::table
|
||||
/// or a toml::parse_error. Most member functions assume a particular one of these two states,
|
||||
/// and calling them when in the wrong state will cause errors (e.g. attempting to access the
|
||||
/// error object when parsing was successful). \cpp
|
||||
/// parse_result result = toml::parse_file("config.toml");
|
||||
/// toml::parse_result result = toml::parse_file("config.toml");
|
||||
/// if (result)
|
||||
/// do_stuff_with_a_table(result); //implicitly converts to table&
|
||||
/// else
|
||||
/// std::cerr << "Parse failed:\n"sv << result.error() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -40,19 +45,10 @@ TOML_NAMESPACE_START
|
||||
/// (error occurred at line 1, column 13 of 'config.toml')
|
||||
/// \eout
|
||||
///
|
||||
/// Getting node_views (`operator[]`) and using the iterator accessor functions (`begin(), end()` etc.) are
|
||||
/// Getting node_views (`operator[]`, `at_path()`) and using the iterator accessor functions (`begin()`, `end()` etc.) are
|
||||
/// unconditionally safe; when parsing fails these just return 'empty' values. A ranged-for loop on a failed
|
||||
/// parse_result is also safe since `begin()` and `end()` return the same iterator and will not lead to any
|
||||
/// dereferences and iterations.
|
||||
///
|
||||
/// \availability <strong>This type only exists when exceptions are disabled.</strong>
|
||||
/// Otherwise parse_result is just an alias for toml::table: \cpp
|
||||
/// #if TOML_EXCEPTIONS
|
||||
/// using parse_result = table;
|
||||
/// #else
|
||||
/// class parse_result final { // ...
|
||||
/// #endif
|
||||
/// \ecpp
|
||||
class parse_result
|
||||
{
|
||||
private:
|
||||
@ -86,123 +82,7 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
public:
|
||||
/// \brief A BidirectionalIterator for iterating over key-value pairs in a wrapped toml::table.
|
||||
using iterator = table_iterator;
|
||||
|
||||
/// \brief A BidirectionalIterator for iterating over const key-value pairs in a wrapped toml::table.
|
||||
using const_iterator = const_table_iterator;
|
||||
|
||||
/// \brief Returns true if parsing succeeeded.
|
||||
TOML_NODISCARD
|
||||
bool succeeded() const noexcept
|
||||
{
|
||||
return !err_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if parsing failed.
|
||||
TOML_NODISCARD
|
||||
bool failed() const noexcept
|
||||
{
|
||||
return err_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if parsing succeeded.
|
||||
TOML_NODISCARD
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return !err_;
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table.
|
||||
TOML_NODISCARD
|
||||
toml::table& table() & noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return *get_as<toml::table>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
toml::table&& table() && noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return static_cast<toml::table&&>(*get_as<toml::table>(storage_));
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
const toml::table& table() const& noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
return *get_as<const toml::table>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error.
|
||||
TOML_NODISCARD
|
||||
parse_error& error() & noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return *get_as<parse_error>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
parse_error&& error() && noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return static_cast<parse_error&&>(*get_as<parse_error>(storage_));
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
const parse_error& error() const& noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
return *get_as<const parse_error>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table.
|
||||
TOML_NODISCARD
|
||||
operator toml::table&() noexcept
|
||||
{
|
||||
return table();
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
operator toml::table&&() noexcept
|
||||
{
|
||||
return std::move(table());
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
operator const toml::table&() const noexcept
|
||||
{
|
||||
return table();
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error.
|
||||
TOML_NODISCARD
|
||||
explicit operator parse_error&() noexcept
|
||||
{
|
||||
return error();
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
explicit operator parse_error&&() noexcept
|
||||
{
|
||||
return std::move(error());
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
explicit operator const parse_error&() const noexcept
|
||||
{
|
||||
return error();
|
||||
}
|
||||
|
||||
/// \brief Default constructs an 'error' result.
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_result() noexcept //
|
||||
: err_{ true }
|
||||
@ -263,6 +143,191 @@ TOML_NAMESPACE_START
|
||||
destroy();
|
||||
}
|
||||
|
||||
/// \name Result state
|
||||
/// @{
|
||||
|
||||
/// \brief Returns true if parsing succeeeded.
|
||||
TOML_NODISCARD
|
||||
bool succeeded() const noexcept
|
||||
{
|
||||
return !err_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if parsing failed.
|
||||
TOML_NODISCARD
|
||||
bool failed() const noexcept
|
||||
{
|
||||
return err_;
|
||||
}
|
||||
|
||||
/// \brief Returns true if parsing succeeded.
|
||||
TOML_NODISCARD
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return !err_;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Successful parses
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the internal toml::table.
|
||||
TOML_NODISCARD
|
||||
toml::table& table() & noexcept
|
||||
{
|
||||
TOML_ASSERT_ASSUME(!err_);
|
||||
return *get_as<toml::table>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
toml::table&& table() && noexcept
|
||||
{
|
||||
TOML_ASSERT_ASSUME(!err_);
|
||||
return static_cast<toml::table&&>(*get_as<toml::table>(storage_));
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
const toml::table& table() const& noexcept
|
||||
{
|
||||
TOML_ASSERT_ASSUME(!err_);
|
||||
return *get_as<const toml::table>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table.
|
||||
TOML_NODISCARD
|
||||
/* implicit */ operator toml::table&() noexcept
|
||||
{
|
||||
return table();
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
/* implicit */ operator toml::table&&() noexcept
|
||||
{
|
||||
return std::move(table());
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::table (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
/* implicit */ operator const toml::table&() const noexcept
|
||||
{
|
||||
return table();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Failed parses
|
||||
/// @{
|
||||
|
||||
/// \brief Returns the internal toml::parse_error.
|
||||
TOML_NODISCARD
|
||||
parse_error& error() & noexcept
|
||||
{
|
||||
TOML_ASSERT_ASSUME(err_);
|
||||
return *get_as<parse_error>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
parse_error&& error() && noexcept
|
||||
{
|
||||
TOML_ASSERT_ASSUME(err_);
|
||||
return static_cast<parse_error&&>(*get_as<parse_error>(storage_));
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
const parse_error& error() const& noexcept
|
||||
{
|
||||
TOML_ASSERT_ASSUME(err_);
|
||||
return *get_as<const parse_error>(storage_);
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error.
|
||||
TOML_NODISCARD
|
||||
explicit operator parse_error&() noexcept
|
||||
{
|
||||
return error();
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
explicit operator parse_error&&() noexcept
|
||||
{
|
||||
return std::move(error());
|
||||
}
|
||||
|
||||
/// \brief Returns the internal toml::parse_error (const lvalue overload).
|
||||
TOML_NODISCARD
|
||||
explicit operator const parse_error&() const noexcept
|
||||
{
|
||||
return error();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Iterators
|
||||
/// @{
|
||||
|
||||
/// \brief A BidirectionalIterator for iterating over key-value pairs in a wrapped toml::table.
|
||||
using iterator = table_iterator;
|
||||
|
||||
/// \brief A BidirectionalIterator for iterating over const key-value pairs in a wrapped toml::table.
|
||||
using const_iterator = const_table_iterator;
|
||||
|
||||
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
|
||||
/// \remarks Always returns the same value as #end() if parsing failed.
|
||||
TOML_NODISCARD
|
||||
table_iterator begin() noexcept
|
||||
{
|
||||
return err_ ? table_iterator{} : table().begin();
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
|
||||
/// \remarks Always returns the same value as #end() if parsing failed.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator begin() const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().begin();
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
|
||||
/// \remarks Always returns the same value as #cend() if parsing failed.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator cbegin() const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().cbegin();
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
|
||||
TOML_NODISCARD
|
||||
table_iterator end() noexcept
|
||||
{
|
||||
return err_ ? table_iterator{} : table().end();
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator end() const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().end();
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator cend() const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().cend();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Node views
|
||||
/// @{
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair in the wrapped table.
|
||||
///
|
||||
/// \param key The key used for the lookup.
|
||||
@ -272,7 +337,7 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \see toml::node_view
|
||||
TOML_NODISCARD
|
||||
node_view<node> operator[](string_view key) noexcept
|
||||
node_view<node> operator[](std::string_view key) noexcept
|
||||
{
|
||||
return err_ ? node_view<node>{} : table()[key];
|
||||
}
|
||||
@ -286,16 +351,34 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \see toml::node_view
|
||||
TOML_NODISCARD
|
||||
node_view<const node> operator[](string_view key) const noexcept
|
||||
node_view<const node> operator[](std::string_view key) const noexcept
|
||||
{
|
||||
return err_ ? node_view<const node>{} : table()[key];
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
node_view<node> at_path(std::string_view path) noexcept
|
||||
{
|
||||
return err_ ? node_view<node>{} : table().at_path(path);
|
||||
}
|
||||
|
||||
/// \brief Returns a const view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
node_view<const node> at_path(std::string_view path) const noexcept
|
||||
{
|
||||
return err_ ? node_view<const node>{} : table().at_path(path);
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair in the wrapped table.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \param key The key used for the lookup.
|
||||
///
|
||||
@ -311,7 +394,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload).
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \param key The key used for the lookup.
|
||||
///
|
||||
@ -325,65 +408,48 @@ TOML_NAMESPACE_START
|
||||
return err_ ? node_view<const node>{} : table()[key];
|
||||
}
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
|
||||
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
|
||||
/// \brief Returns a view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
table_iterator begin() noexcept
|
||||
node_view<node> at_path(std::wstring_view path) noexcept
|
||||
{
|
||||
return err_ ? table_iterator{} : table().begin();
|
||||
return err_ ? node_view<node>{} : table().at_path(path);
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
|
||||
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
|
||||
/// \brief Returns a const view of the subnode matching a fully-qualified "TOML path".
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \see #toml::at_path(node&, std::string_view)
|
||||
TOML_NODISCARD
|
||||
const_table_iterator begin() const noexcept
|
||||
node_view<const node> at_path(std::wstring_view path) const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().begin();
|
||||
return err_ ? node_view<const node>{} : table().at_path(path);
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
|
||||
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator cbegin() const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().cbegin();
|
||||
}
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
|
||||
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
|
||||
TOML_NODISCARD
|
||||
table_iterator end() noexcept
|
||||
{
|
||||
return err_ ? table_iterator{} : table().end();
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
|
||||
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator end() const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().end();
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
|
||||
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
|
||||
TOML_NODISCARD
|
||||
const_table_iterator cend() const noexcept
|
||||
{
|
||||
return err_ ? const_table_iterator{} : table().cend();
|
||||
}
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
/// \brief Prints the held error or table object out to a text stream.
|
||||
template <typename Char>
|
||||
friend std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& os, const parse_result& result)
|
||||
///
|
||||
/// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
friend std::ostream& operator<<(std::ostream& os, const parse_result& result)
|
||||
{
|
||||
return result.err_ ? (os << result.error()) : (os << result.table());
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_END;
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
#endif // !TOML_EXCEPTIONS
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_PARSER && !TOML_EXCEPTIONS
|
||||
|
@ -2,32 +2,14 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_PARSER
|
||||
|
||||
#include "table.h"
|
||||
#include "parse_error.h"
|
||||
#include "parse_result.h"
|
||||
#include "utf8_streams.h"
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result do_parse(utf8_reader_interface &&) TOML_MAY_THROW;
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
@ -38,7 +20,6 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -56,14 +37,13 @@ TOML_NAMESPACE_START
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::string_view doc, std::string_view source_path = {}) TOML_MAY_THROW;
|
||||
parse_result parse(std::string_view doc, std::string_view source_path = {});
|
||||
|
||||
/// \brief Parses a TOML document from a string view.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv, "foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -81,235 +61,7 @@ TOML_NAMESPACE_START
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::string_view doc, std::string && source_path) TOML_MAY_THROW;
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a TOML document from a string view.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv, L"foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::string_view doc, std::wstring_view source_path) TOML_MAY_THROW;
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
/// \brief Parses a TOML document from a char8_t string view.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::u8string_view doc, std::string_view source_path = {}) TOML_MAY_THROW;
|
||||
|
||||
/// \brief Parses a TOML document from a char8_t string view.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv, "foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::u8string_view doc, std::string && source_path) TOML_MAY_THROW;
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a TOML document from a char8_t string view.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv, L"foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::u8string_view doc, std::wstring_view source_path) TOML_MAY_THROW;
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
#endif // TOML_HAS_CHAR8
|
||||
|
||||
/// \brief Parses a TOML document from a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// std::stringstream ss;
|
||||
/// ss << "a = 3"sv;
|
||||
///
|
||||
/// auto tbl = toml::parse(ss);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
template <typename Char>
|
||||
TOML_NODISCARD
|
||||
inline parse_result parse(std::basic_istream<Char> & doc, std::string_view source_path = {}) TOML_MAY_THROW
|
||||
{
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
|
||||
return impl::do_parse(impl::utf8_reader{ doc, source_path });
|
||||
}
|
||||
|
||||
/// \brief Parses a TOML document from a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// std::stringstream ss;
|
||||
/// ss << "a = 3"sv;
|
||||
///
|
||||
/// auto tbl = toml::parse(ss, "foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
template <typename Char>
|
||||
TOML_NODISCARD
|
||||
inline parse_result parse(std::basic_istream<Char> & doc, std::string && source_path) TOML_MAY_THROW
|
||||
{
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
|
||||
return impl::do_parse(impl::utf8_reader{ doc, std::move(source_path) });
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a TOML document from a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// std::stringstream ss;
|
||||
/// ss << "a = 3"sv;
|
||||
///
|
||||
/// auto tbl = toml::parse(ss);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \tparam Char The stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
template <typename Char>
|
||||
TOML_NODISCARD
|
||||
inline parse_result parse(std::basic_istream<Char> & doc, std::wstring_view source_path) TOML_MAY_THROW
|
||||
{
|
||||
return parse(doc, impl::narrow(source_path));
|
||||
}
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
parse_result parse(std::istream&, std::string_view) TOML_MAY_THROW;
|
||||
extern template TOML_API
|
||||
parse_result parse(std::istream&, std::string &&) TOML_MAY_THROW;
|
||||
#endif
|
||||
parse_result parse(std::string_view doc, std::string && source_path);
|
||||
|
||||
/// \brief Parses a TOML document from a file.
|
||||
///
|
||||
@ -328,10 +80,58 @@ TOML_NAMESPACE_START
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse_file(std::string_view file_path) TOML_MAY_THROW;
|
||||
parse_result parse_file(std::string_view file_path);
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
/// \brief Parses a TOML document from a char8_t string view.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::u8string_view doc, std::string_view source_path = {});
|
||||
|
||||
/// \brief Parses a TOML document from a char8_t string view.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv, "foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::u8string_view doc, std::string && source_path);
|
||||
|
||||
/// \brief Parses a TOML document from a file.
|
||||
///
|
||||
/// \detail \cpp
|
||||
@ -349,14 +149,71 @@ TOML_NAMESPACE_START
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse_file(std::u8string_view file_path) TOML_MAY_THROW;
|
||||
parse_result parse_file(std::u8string_view file_path);
|
||||
|
||||
#endif // TOML_HAS_CHAR8
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a TOML document from a string view.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv, L"foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::string_view doc, std::wstring_view source_path);
|
||||
|
||||
/// \brief Parses a TOML document from a stream.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// std::stringstream ss;
|
||||
/// ss << "a = 3"sv;
|
||||
///
|
||||
/// auto tbl = toml::parse(ss);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::istream & doc, std::wstring_view source_path);
|
||||
|
||||
/// \brief Parses a TOML document from a file.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// toml::parse_result get_foo_toml()
|
||||
/// {
|
||||
@ -364,8 +221,6 @@ TOML_NAMESPACE_START
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \param file_path The TOML document to parse. Must be valid UTF-8.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
@ -374,9 +229,93 @@ TOML_NAMESPACE_START
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse_file(std::wstring_view file_path) TOML_MAY_THROW;
|
||||
parse_result parse_file(std::wstring_view file_path);
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
#if TOML_HAS_CHAR8 && TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a TOML document from a char8_t string view.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv, L"foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::u8string_view doc, std::wstring_view source_path);
|
||||
|
||||
#endif // TOML_HAS_CHAR8 && TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Parses a TOML document from a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// std::stringstream ss;
|
||||
/// ss << "a = 3"sv;
|
||||
///
|
||||
/// auto tbl = toml::parse(ss);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::istream & doc, std::string_view source_path = {});
|
||||
|
||||
/// \brief Parses a TOML document from a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// std::stringstream ss;
|
||||
/// ss << "a = 3"sv;
|
||||
///
|
||||
/// auto tbl = toml::parse(ss, "foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// 3
|
||||
/// \eout
|
||||
///
|
||||
/// \param doc The TOML document to parse. Must be valid UTF-8.
|
||||
/// \param source_path The path used to initialize each node's `source().path`.
|
||||
/// If you don't have a path (or you have no intention of using paths in diagnostics)
|
||||
/// then this parameter can safely be left blank.
|
||||
///
|
||||
/// \returns \conditional_return{With exceptions}
|
||||
/// A toml::table.
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result parse(std::istream & doc, std::string && source_path);
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
|
||||
@ -391,7 +330,6 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// auto tbl = "a = 3"_toml;
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -406,8 +344,10 @@ TOML_NAMESPACE_START
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result operator"" _toml(const char* str, size_t len) TOML_MAY_THROW;
|
||||
inline parse_result operator"" _toml(const char* str, size_t len)
|
||||
{
|
||||
return parse(std::string_view{ str, len });
|
||||
}
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
@ -418,7 +358,6 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// auto tbl = u8"a = 3"_toml;
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -433,8 +372,10 @@ TOML_NAMESPACE_START
|
||||
/// \conditional_return{Without exceptions}
|
||||
/// A toml::parse_result.
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
parse_result operator"" _toml(const char8_t* str, size_t len) TOML_MAY_THROW;
|
||||
inline parse_result operator"" _toml(const char8_t* str, size_t len)
|
||||
{
|
||||
return parse(std::u8string_view{ str, len });
|
||||
}
|
||||
|
||||
#endif // TOML_HAS_CHAR8
|
||||
|
||||
@ -442,3 +383,6 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_PARSER
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -66,25 +66,27 @@
|
||||
_Pragma("clang diagnostic ignored \"-Wswitch\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_DISABLE_INIT_WARNINGS \
|
||||
_Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_DISABLE_ARITHMETIC_WARNINGS \
|
||||
_Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wdouble-promotion\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wchar-subscripts\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wshift-sign-overflow\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_DISABLE_SHADOW_WARNINGS \
|
||||
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wshadow-field\"") \
|
||||
static_assert(true)
|
||||
#if TOML_CLANG >= 10
|
||||
#define TOML_DISABLE_SPAM_WARNINGS_CLANG_10 \
|
||||
_Pragma("clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"") \
|
||||
static_assert(true)
|
||||
#else
|
||||
#define TOML_DISABLE_SPAM_WARNINGS_CLANG_10 static_assert(true)
|
||||
#endif
|
||||
|
||||
#define TOML_DISABLE_SPAM_WARNINGS \
|
||||
TOML_DISABLE_SPAM_WARNINGS_CLANG_10; \
|
||||
_Pragma("clang diagnostic ignored \"-Wweak-vtables\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wweak-template-vtables\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wdouble-promotion\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wchar-subscripts\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wpadded\"") \
|
||||
static_assert(true)
|
||||
|
||||
@ -99,7 +101,7 @@
|
||||
|
||||
#define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS
|
||||
|
||||
#define TOML_ASSUME(cond) __builtin_assume(cond)
|
||||
#define TOML_ASSUME(expr) __builtin_assume(expr)
|
||||
#define TOML_UNREACHABLE __builtin_unreachable()
|
||||
#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
|
||||
#if defined(_MSC_VER) // msvc compat mode
|
||||
@ -128,6 +130,17 @@
|
||||
#if !defined(TOML_TRIVIAL_ABI) && __has_attribute(trivial_abi)
|
||||
#define TOML_TRIVIAL_ABI __attribute__((__trivial_abi__))
|
||||
#endif
|
||||
#if !defined(TOML_FLAGS_ENUM) && __has_attribute(flag_enum)
|
||||
#define TOML_FLAGS_ENUM __attribute__((__flag_enum__))
|
||||
#endif
|
||||
#if __has_attribute(enum_extensibility)
|
||||
#ifndef TOML_OPEN_ENUM
|
||||
#define TOML_OPEN_ENUM __attribute__((enum_extensibility(open)))
|
||||
#endif
|
||||
#ifndef TOML_CLOSED_ENUM
|
||||
#define TOML_CLOSED_ENUM __attribute__((enum_extensibility(closed)))
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#define TOML_LIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 1) )
|
||||
#define TOML_UNLIKELY(...) (__builtin_expect(!!(__VA_ARGS__), 0) )
|
||||
@ -162,8 +175,8 @@
|
||||
#endif
|
||||
|
||||
#define TOML_DISABLE_SWITCH_WARNINGS \
|
||||
__pragma(warning(disable: 4061)) \
|
||||
__pragma(warning(disable: 4062)) \
|
||||
__pragma(warning(disable: 4061)) /* enumerator 'identifier' is not explicitly handled by a case label */ \
|
||||
__pragma(warning(disable: 4062)) /* enumerator 'identifier' is not handled */ \
|
||||
__pragma(warning(disable: 4063)) \
|
||||
__pragma(warning(disable: 26819)) \
|
||||
static_assert(true)
|
||||
@ -222,7 +235,7 @@
|
||||
#define TOML_ALWAYS_INLINE __forceinline
|
||||
#endif
|
||||
#define TOML_NEVER_INLINE __declspec(noinline)
|
||||
#define TOML_ASSUME(cond) __assume(cond)
|
||||
#define TOML_ASSUME(expr) __assume(expr)
|
||||
#define TOML_UNREACHABLE __assume(0)
|
||||
#define TOML_ABSTRACT_BASE __declspec(novtable)
|
||||
#define TOML_EMPTY_BASES __declspec(empty_bases)
|
||||
@ -278,23 +291,17 @@
|
||||
#define TOML_DISABLE_SWITCH_WARNINGS \
|
||||
_Pragma("GCC diagnostic ignored \"-Wswitch\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wswitch-enum\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wswitch-default\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_DISABLE_INIT_WARNINGS \
|
||||
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wuninitialized\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wswitch-default\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_DISABLE_ARITHMETIC_WARNINGS \
|
||||
_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wsign-conversion\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wchar-subscripts\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_DISABLE_SHADOW_WARNINGS \
|
||||
_Pragma("GCC diagnostic ignored \"-Wshadow\"") \
|
||||
#define TOML_DISABLE_SUGGEST_ATTR_WARNINGS \
|
||||
_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=const\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=pure\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_DISABLE_SPAM_WARNINGS \
|
||||
@ -303,8 +310,10 @@
|
||||
_Pragma("GCC diagnostic ignored \"-Wcomment\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wuseless-cast\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=const\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=pure\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wchar-subscripts\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wsubobject-linkage\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") \
|
||||
static_assert(true)
|
||||
|
||||
#define TOML_POP_WARNINGS \
|
||||
@ -317,10 +326,9 @@
|
||||
_Pragma("GCC diagnostic ignored \"-Wextra\"") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wpedantic\"") \
|
||||
TOML_DISABLE_SWITCH_WARNINGS; \
|
||||
TOML_DISABLE_INIT_WARNINGS; \
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS; \
|
||||
TOML_DISABLE_SHADOW_WARNINGS; \
|
||||
TOML_DISABLE_SPAM_WARNINGS; \
|
||||
TOML_DISABLE_SUGGEST_ATTR_WARNINGS; \
|
||||
static_assert(true)
|
||||
|
||||
|
||||
@ -339,91 +347,7 @@
|
||||
#endif
|
||||
|
||||
//#====================================================================================================================
|
||||
//# USER CONFIGURATION
|
||||
//#====================================================================================================================
|
||||
|
||||
#ifdef TOML_CONFIG_HEADER
|
||||
#include TOML_CONFIG_HEADER
|
||||
#endif
|
||||
|
||||
#ifdef DOXYGEN
|
||||
#define TOML_HEADER_ONLY 0
|
||||
#define TOML_WINDOWS_COMPAT 1
|
||||
#endif
|
||||
|
||||
#if defined(TOML_ALL_INLINE) && !defined(TOML_HEADER_ONLY)
|
||||
#define TOML_HEADER_ONLY TOML_ALL_INLINE
|
||||
#endif
|
||||
|
||||
#if !defined(TOML_HEADER_ONLY) || (defined(TOML_HEADER_ONLY) && TOML_HEADER_ONLY) || TOML_INTELLISENSE
|
||||
#undef TOML_HEADER_ONLY
|
||||
#define TOML_HEADER_ONLY 1
|
||||
#endif
|
||||
|
||||
#if defined(TOML_IMPLEMENTATION) || TOML_HEADER_ONLY
|
||||
#undef TOML_IMPLEMENTATION
|
||||
#define TOML_IMPLEMENTATION 1
|
||||
#else
|
||||
#define TOML_IMPLEMENTATION 0
|
||||
#endif
|
||||
|
||||
#ifndef TOML_API
|
||||
#define TOML_API
|
||||
#endif
|
||||
|
||||
#ifndef TOML_UNRELEASED_FEATURES
|
||||
#if TOML_INTELLISENSE
|
||||
#define TOML_UNRELEASED_FEATURES 1
|
||||
#else
|
||||
#define TOML_UNRELEASED_FEATURES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TOML_LARGE_FILES
|
||||
#define TOML_LARGE_FILES 0
|
||||
#endif
|
||||
|
||||
#ifndef TOML_UNDEF_MACROS
|
||||
#define TOML_UNDEF_MACROS 1
|
||||
#endif
|
||||
|
||||
#ifndef TOML_PARSER
|
||||
#define TOML_PARSER 1
|
||||
#endif
|
||||
|
||||
#ifndef TOML_MAX_NESTED_VALUES
|
||||
#define TOML_MAX_NESTED_VALUES 256
|
||||
// this refers to the depth of nested values, e.g. inline tables and arrays.
|
||||
// 256 is crazy high! if you're hitting this limit with real input, TOML is probably the wrong tool for the job...
|
||||
#endif
|
||||
|
||||
#ifndef TOML_WINDOWS_COMPAT
|
||||
#define TOML_WINDOWS_COMPAT 1
|
||||
#endif
|
||||
/// \cond
|
||||
#ifndef _WIN32
|
||||
#undef TOML_WINDOWS_COMPAT
|
||||
#define TOML_WINDOWS_COMPAT 0
|
||||
#endif
|
||||
/// \endcond
|
||||
#ifndef TOML_INCLUDE_WINDOWS_H
|
||||
#define TOML_INCLUDE_WINDOWS_H 0
|
||||
#endif
|
||||
|
||||
#ifdef TOML_OPTIONAL_TYPE
|
||||
#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 1
|
||||
#else
|
||||
#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 0
|
||||
#endif
|
||||
|
||||
#ifdef TOML_CHAR_8_STRINGS
|
||||
#if TOML_CHAR_8_STRINGS
|
||||
#error TOML_CHAR_8_STRINGS was removed in toml++ 2.0.0; all value setters and getters now work with char8_t strings implicitly.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#====================================================================================================================
|
||||
//# ATTRIBUTES, UTILITY MACROS ETC
|
||||
//# CPP VERSION
|
||||
//#====================================================================================================================
|
||||
|
||||
#ifndef TOML_CPP_VERSION
|
||||
@ -433,17 +357,116 @@
|
||||
#error toml++ requires C++17 or higher. For a TOML library supporting pre-C++11 see https://github.com/ToruNiina/Boost.toml
|
||||
#elif TOML_CPP_VERSION < 201703L
|
||||
#error toml++ requires C++17 or higher. For a TOML library supporting C++11 see https://github.com/ToruNiina/toml11
|
||||
#elif TOML_CPP_VERSION >= 202600L
|
||||
#define TOML_CPP 26
|
||||
#elif TOML_CPP_VERSION >= 202300L
|
||||
#define TOML_CPP 23
|
||||
#elif TOML_CPP_VERSION >= 202002L
|
||||
#define TOML_CPP 20
|
||||
#elif TOML_CPP_VERSION >= 201703L
|
||||
#define TOML_CPP 17
|
||||
#endif
|
||||
#undef TOML_CPP_VERSION
|
||||
|
||||
//#====================================================================================================================
|
||||
//# USER CONFIGURATION
|
||||
//#====================================================================================================================
|
||||
|
||||
#ifdef TOML_CONFIG_HEADER
|
||||
#include TOML_CONFIG_HEADER
|
||||
#endif
|
||||
|
||||
// header-only mode
|
||||
#if !defined(TOML_HEADER_ONLY) && defined(TOML_ALL_INLINE) // was TOML_ALL_INLINE pre-2.0
|
||||
#define TOML_HEADER_ONLY TOML_ALL_INLINE
|
||||
#endif
|
||||
#if !defined(TOML_HEADER_ONLY) || (defined(TOML_HEADER_ONLY) && TOML_HEADER_ONLY) || TOML_INTELLISENSE
|
||||
#undef TOML_HEADER_ONLY
|
||||
#define TOML_HEADER_ONLY 1
|
||||
#endif
|
||||
#ifdef DOXYGEN
|
||||
#undef TOML_HEADER_ONLY
|
||||
#define TOML_HEADER_ONLY 0
|
||||
#endif
|
||||
|
||||
// extern templates (for !TOML_HEADER_ONLY)
|
||||
#ifndef TOML_EXTERN_TEMPLATES
|
||||
#define TOML_EXTERN_TEMPLATES 1
|
||||
#endif
|
||||
#if (defined(DOXYGEN) || TOML_HEADER_ONLY)
|
||||
#undef TOML_EXTERN_TEMPLATES
|
||||
#define TOML_EXTERN_TEMPLATES 0
|
||||
#endif
|
||||
|
||||
// internal implementation switch
|
||||
#if defined(TOML_IMPLEMENTATION) || TOML_HEADER_ONLY
|
||||
#undef TOML_IMPLEMENTATION
|
||||
#define TOML_IMPLEMENTATION 1
|
||||
#else
|
||||
#define TOML_IMPLEMENTATION 0
|
||||
#endif
|
||||
|
||||
// dllexport etc
|
||||
#ifndef TOML_API
|
||||
#define TOML_API
|
||||
#endif
|
||||
|
||||
// experimental language features
|
||||
#if !defined(TOML_ENABLE_UNRELEASED_FEATURES) && defined(TOML_UNRELEASED_FEATURES) // was TOML_UNRELEASED_FEATURES pre-3.0
|
||||
#define TOML_ENABLE_UNRELEASED_FEATURES TOML_UNRELEASED_FEATURES
|
||||
#endif
|
||||
#if (defined(TOML_ENABLE_UNRELEASED_FEATURES) && TOML_ENABLE_UNRELEASED_FEATURES) || TOML_INTELLISENSE
|
||||
#undef TOML_ENABLE_UNRELEASED_FEATURES
|
||||
#define TOML_ENABLE_UNRELEASED_FEATURES 1
|
||||
#endif
|
||||
#ifndef TOML_ENABLE_UNRELEASED_FEATURES
|
||||
#define TOML_ENABLE_UNRELEASED_FEATURES 0
|
||||
#endif
|
||||
|
||||
// parser
|
||||
#if !defined(TOML_ENABLE_PARSER) && defined(TOML_PARSER) // was TOML_PARSER pre-3.0
|
||||
#define TOML_ENABLE_PARSER TOML_PARSER
|
||||
#endif
|
||||
#if !defined(TOML_ENABLE_PARSER) || (defined(TOML_ENABLE_PARSER) && TOML_ENABLE_PARSER) || TOML_INTELLISENSE
|
||||
#undef TOML_ENABLE_PARSER
|
||||
#define TOML_ENABLE_PARSER 1
|
||||
#endif
|
||||
|
||||
// formatters
|
||||
#if !defined(TOML_ENABLE_FORMATTERS) \
|
||||
|| (defined(TOML_ENABLE_FORMATTERS) && TOML_ENABLE_FORMATTERS) \
|
||||
|| TOML_INTELLISENSE
|
||||
#undef TOML_ENABLE_FORMATTERS
|
||||
#define TOML_ENABLE_FORMATTERS 1
|
||||
#endif
|
||||
|
||||
// SIMD
|
||||
#if !defined(TOML_ENABLE_SIMD) \
|
||||
|| (defined(TOML_ENABLE_SIMD) && TOML_ENABLE_SIMD) \
|
||||
|| TOML_INTELLISENSE
|
||||
#undef TOML_ENABLE_SIMD
|
||||
#define TOML_ENABLE_SIMD 1
|
||||
#endif
|
||||
|
||||
// windows compat
|
||||
#if !defined(TOML_ENABLE_WINDOWS_COMPAT) && defined(TOML_WINDOWS_COMPAT) // was TOML_WINDOWS_COMPAT pre-3.0
|
||||
#define TOML_ENABLE_WINDOWS_COMPAT TOML_WINDOWS_COMPAT
|
||||
#endif
|
||||
#if !defined(TOML_ENABLE_WINDOWS_COMPAT) \
|
||||
|| (defined(TOML_ENABLE_WINDOWS_COMPAT) && TOML_ENABLE_WINDOWS_COMPAT) \
|
||||
|| TOML_INTELLISENSE
|
||||
#undef TOML_ENABLE_WINDOWS_COMPAT
|
||||
#define TOML_ENABLE_WINDOWS_COMPAT 1
|
||||
#endif
|
||||
/// \cond
|
||||
#ifndef _WIN32
|
||||
#undef TOML_ENABLE_WINDOWS_COMPAT
|
||||
#define TOML_ENABLE_WINDOWS_COMPAT 0
|
||||
#endif
|
||||
/// \endcond
|
||||
#ifndef TOML_INCLUDE_WINDOWS_H
|
||||
#define TOML_INCLUDE_WINDOWS_H 0
|
||||
#endif
|
||||
|
||||
// custom optional
|
||||
#ifdef TOML_OPTIONAL_TYPE
|
||||
#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 1
|
||||
#else
|
||||
#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 0
|
||||
#endif
|
||||
|
||||
// exceptions (compiler support)
|
||||
#ifndef TOML_COMPILER_EXCEPTIONS
|
||||
#if defined(__EXCEPTIONS) || defined(__cpp_exceptions)
|
||||
#define TOML_COMPILER_EXCEPTIONS 1
|
||||
@ -451,6 +474,8 @@
|
||||
#define TOML_COMPILER_EXCEPTIONS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// exceptions (library use)
|
||||
#if TOML_COMPILER_EXCEPTIONS
|
||||
#if !defined(TOML_EXCEPTIONS) || (defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS)
|
||||
#undef TOML_EXCEPTIONS
|
||||
@ -464,18 +489,39 @@
|
||||
#define TOML_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
#if defined(DOXYGEN) || TOML_EXCEPTIONS
|
||||
#define TOML_MAY_THROW
|
||||
#else
|
||||
#define TOML_MAY_THROW noexcept
|
||||
#ifndef TOML_UNDEF_MACROS
|
||||
#define TOML_UNDEF_MACROS 1
|
||||
#endif
|
||||
|
||||
#if TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL)
|
||||
|
||||
#ifndef TOML_MAX_NESTED_VALUES
|
||||
#define TOML_MAX_NESTED_VALUES 256
|
||||
// this refers to the depth of nested values, e.g. inline tables and arrays.
|
||||
// 256 is crazy high! if you're hitting this limit with real input, TOML is probably the wrong tool for the job...
|
||||
#endif
|
||||
|
||||
#ifdef TOML_CHAR_8_STRINGS
|
||||
#if TOML_CHAR_8_STRINGS
|
||||
#error TOML_CHAR_8_STRINGS was removed in toml++ 2.0.0; all value setters and getters now work with char8_t strings implicitly.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TOML_LARGE_FILES
|
||||
#if !TOML_LARGE_FILES
|
||||
#error Support for !TOML_LARGE_FILES (i.e. 'small files') was removed in toml++ 3.0.0.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#====================================================================================================================
|
||||
//# ATTRIBUTES, UTILITY MACROS ETC
|
||||
//#====================================================================================================================
|
||||
|
||||
#if !defined(TOML_FLOAT_CHARCONV) && (TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL))
|
||||
// not supported by any version of GCC or Clang as of 26/11/2020
|
||||
// not supported by any version of ICC on Linux as of 11/01/2021
|
||||
#define TOML_FLOAT_CHARCONV 0
|
||||
#endif
|
||||
#if defined(__EMSCRIPTEN__) || defined(__APPLE__)
|
||||
#if !defined(TOML_INT_CHARCONV) && (defined(__EMSCRIPTEN__) || defined(__APPLE__))
|
||||
// causes link errors on emscripten
|
||||
// causes Mac OS SDK version errors on some versions of Apple Clang
|
||||
#define TOML_INT_CHARCONV 0
|
||||
@ -502,8 +548,8 @@
|
||||
#ifndef TOML_DISABLE_SWITCH_WARNINGS
|
||||
#define TOML_DISABLE_SWITCH_WARNINGS static_assert(true)
|
||||
#endif
|
||||
#ifndef TOML_DISABLE_INIT_WARNINGS
|
||||
#define TOML_DISABLE_INIT_WARNINGS static_assert(true)
|
||||
#ifndef TOML_DISABLE_SUGGEST_ATTR_WARNINGS
|
||||
#define TOML_DISABLE_SUGGEST_ATTR_WARNINGS static_assert(true)
|
||||
#endif
|
||||
#ifndef TOML_DISABLE_SPAM_WARNINGS
|
||||
#define TOML_DISABLE_SPAM_WARNINGS static_assert(true)
|
||||
@ -511,9 +557,6 @@
|
||||
#ifndef TOML_DISABLE_ARITHMETIC_WARNINGS
|
||||
#define TOML_DISABLE_ARITHMETIC_WARNINGS static_assert(true)
|
||||
#endif
|
||||
#ifndef TOML_DISABLE_SHADOW_WARNINGS
|
||||
#define TOML_DISABLE_SHADOW_WARNINGS static_assert(true)
|
||||
#endif
|
||||
#ifndef TOML_POP_WARNINGS
|
||||
#define TOML_POP_WARNINGS static_assert(true)
|
||||
#endif
|
||||
@ -544,18 +587,31 @@
|
||||
#endif
|
||||
|
||||
#ifndef TOML_ASSUME
|
||||
#define TOML_ASSUME(cond) (void)0
|
||||
#define TOML_ASSUME(expr) static_assert(true)
|
||||
#endif
|
||||
|
||||
#ifndef TOML_UNREACHABLE
|
||||
#define TOML_UNREACHABLE TOML_ASSERT(false)
|
||||
#define TOML_UNREACHABLE TOML_ASSUME(false)
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_consteval) && __cpp_consteval >= 201811 && !defined(_MSC_VER)
|
||||
// https://developercommunity.visualstudio.com/t/Erroneous-C7595-error-with-consteval-in/1404234
|
||||
#define TOML_CONSTEVAL consteval
|
||||
#else
|
||||
#define TOML_CONSTEVAL constexpr
|
||||
#ifndef TOML_FLAGS_ENUM
|
||||
#define TOML_FLAGS_ENUM
|
||||
#endif
|
||||
|
||||
#ifndef TOML_OPEN_ENUM
|
||||
#define TOML_OPEN_ENUM
|
||||
#endif
|
||||
|
||||
#ifndef TOML_CLOSED_ENUM
|
||||
#define TOML_CLOSED_ENUM
|
||||
#endif
|
||||
|
||||
#ifndef TOML_OPEN_FLAGS_ENUM
|
||||
#define TOML_OPEN_FLAGS_ENUM TOML_OPEN_ENUM TOML_FLAGS_ENUM
|
||||
#endif
|
||||
|
||||
#ifndef TOML_CLOSED_FLAGS_ENUM
|
||||
#define TOML_CLOSED_FLAGS_ENUM TOML_CLOSED_ENUM TOML_FLAGS_ENUM
|
||||
#endif
|
||||
|
||||
#ifdef __has_cpp_attribute
|
||||
@ -564,19 +620,35 @@
|
||||
#define TOML_HAS_ATTR(...) 0
|
||||
#endif
|
||||
|
||||
#if !defined(TOML_LIKELY) && TOML_HAS_ATTR(likely) >= 201803
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__) [[likely]]
|
||||
#if TOML_HAS_ATTR(likely) >= 201803
|
||||
#ifndef TOML_LIKELY
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__) [[likely]]
|
||||
#endif
|
||||
#ifndef TOML_LIKELY_CASE
|
||||
#define TOML_LIKELY_CASE [[likely]]
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TOML_LIKELY
|
||||
#define TOML_LIKELY(...) (__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef TOML_LIKELY_CASE
|
||||
#define TOML_LIKELY_CASE
|
||||
#endif
|
||||
|
||||
#if !defined(TOML_UNLIKELY) && TOML_HAS_ATTR(unlikely) >= 201803
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__) [[unlikely]]
|
||||
#if TOML_HAS_ATTR(unlikely) >= 201803
|
||||
#ifndef TOML_UNLIKELY
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__) [[unlikely]]
|
||||
#endif
|
||||
#ifndef TOML_UNLIKELY_CASE
|
||||
#define TOML_UNLIKELY_CASE [[unlikely]]
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TOML_UNLIKELY
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef TOML_UNLIKELY_CASE
|
||||
#define TOML_UNLIKELY_CASE
|
||||
#endif
|
||||
|
||||
#if TOML_HAS_ATTR(nodiscard)
|
||||
#define TOML_NODISCARD [[nodiscard]]
|
||||
@ -618,9 +690,7 @@
|
||||
#endif
|
||||
|
||||
#define TOML_MAKE_FLAGS_(name, op) \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr name operator op(name lhs, name rhs) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
@ -636,17 +706,13 @@
|
||||
TOML_MAKE_FLAGS_(name, &); \
|
||||
TOML_MAKE_FLAGS_(name, |); \
|
||||
TOML_MAKE_FLAGS_(name, ^); \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr name operator~(name val) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
return static_cast<name>(~static_cast<under>(val)); \
|
||||
} \
|
||||
TOML_NODISCARD \
|
||||
TOML_ALWAYS_INLINE \
|
||||
TOML_ATTR(const) \
|
||||
TOML_CONST_INLINE_GETTER \
|
||||
constexpr bool operator!(name val) noexcept \
|
||||
{ \
|
||||
using under = std::underlying_type_t<name>; \
|
||||
@ -663,6 +729,37 @@
|
||||
#define POXY_IMPLEMENTATION_DETAIL(...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
#if TOML_IMPLEMENTATION
|
||||
#define TOML_EXTERN
|
||||
#else
|
||||
#define TOML_EXTERN extern
|
||||
#endif
|
||||
#if TOML_CLANG
|
||||
#define TOML_EXTERN_NOEXCEPT(...)
|
||||
#else
|
||||
#define TOML_EXTERN_NOEXCEPT(...) noexcept(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define TOML_PURE_GETTER TOML_NODISCARD TOML_ATTR(pure)
|
||||
#define TOML_CONST_GETTER TOML_NODISCARD TOML_ATTR(const)
|
||||
#define TOML_PURE_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE TOML_ATTR(pure)
|
||||
#define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE TOML_ATTR(const)
|
||||
#else
|
||||
#define TOML_PURE_GETTER TOML_NODISCARD
|
||||
#define TOML_CONST_GETTER TOML_NODISCARD
|
||||
#define TOML_PURE_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE
|
||||
#define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#define TOML_UNUSED(...) static_cast<void>(__VA_ARGS__)
|
||||
|
||||
#define TOML_DELETE_DEFAULTS(T) \
|
||||
T(const T&) = delete; \
|
||||
T(T&&) = delete; \
|
||||
T& operator=(const T&) = delete; \
|
||||
T& operator=(T&&) = delete
|
||||
|
||||
//======================================================================================================================
|
||||
// SFINAE
|
||||
//======================================================================================================================
|
||||
@ -675,10 +772,16 @@
|
||||
#endif
|
||||
#define TOML_ENABLE_IF(...) , typename std::enable_if<(__VA_ARGS__), int>::type = 0
|
||||
#define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__ TOML_ENABLE_IF(condition)> TOML_REQUIRES(condition)
|
||||
#define TOML_HIDDEN_CONSTRAINT(condition, ...) TOML_CONSTRAINED_TEMPLATE(condition, __VA_ARGS__)
|
||||
/// \endcond
|
||||
//# {{
|
||||
#ifndef TOML_CONSTRAINED_TEMPLATE
|
||||
#define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__>
|
||||
#endif
|
||||
#ifndef TOML_HIDDEN_CONSTRAINT
|
||||
#define TOML_HIDDEN_CONSTRAINT(condition, ...)
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
//#====================================================================================================================
|
||||
//# EXTENDED INT AND FLOAT TYPES
|
||||
@ -721,24 +824,24 @@
|
||||
|
||||
#define TOML_LIB_SINGLE_HEADER 0
|
||||
|
||||
#define TOML_MAKE_VERSION(maj, min, rev) \
|
||||
((maj) * 1000 + (min) * 25 + (rev))
|
||||
#define TOML_MAKE_VERSION(major, minor, patch) \
|
||||
((major) * 10000 + (minor) * 100 + (patch))
|
||||
|
||||
#if TOML_UNRELEASED_FEATURES
|
||||
#define TOML_LANG_EFFECTIVE_VERSION \
|
||||
#if TOML_ENABLE_UNRELEASED_FEATURES
|
||||
#define TOML_LANG_EFFECTIVE_VERSION \
|
||||
TOML_MAKE_VERSION(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH+1)
|
||||
#else
|
||||
#define TOML_LANG_EFFECTIVE_VERSION \
|
||||
#define TOML_LANG_EFFECTIVE_VERSION \
|
||||
TOML_MAKE_VERSION(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH)
|
||||
#endif
|
||||
|
||||
#define TOML_LANG_HIGHER_THAN(maj, min, rev) \
|
||||
(TOML_LANG_EFFECTIVE_VERSION > TOML_MAKE_VERSION(maj, min, rev))
|
||||
#define TOML_LANG_HIGHER_THAN(major, minor, patch) \
|
||||
(TOML_LANG_EFFECTIVE_VERSION > TOML_MAKE_VERSION(major, minor, patch))
|
||||
|
||||
#define TOML_LANG_AT_LEAST(maj, min, rev) \
|
||||
(TOML_LANG_EFFECTIVE_VERSION >= TOML_MAKE_VERSION(maj, min, rev))
|
||||
#define TOML_LANG_AT_LEAST(major, minor, patch) \
|
||||
(TOML_LANG_EFFECTIVE_VERSION >= TOML_MAKE_VERSION(major, minor, patch))
|
||||
|
||||
#define TOML_LANG_UNRELEASED \
|
||||
#define TOML_LANG_UNRELEASED \
|
||||
TOML_LANG_HIGHER_THAN(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_PATCH)
|
||||
|
||||
#ifndef TOML_ABI_NAMESPACES
|
||||
@ -766,17 +869,17 @@
|
||||
#define TOML_IMPL_NAMESPACE_START TOML_NAMESPACE_START { namespace impl
|
||||
#define TOML_IMPL_NAMESPACE_END } TOML_NAMESPACE_END
|
||||
#if TOML_HEADER_ONLY
|
||||
#define TOML_ANON_NAMESPACE_START TOML_IMPL_NAMESPACE_START
|
||||
#define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); TOML_IMPL_NAMESPACE_START
|
||||
#define TOML_ANON_NAMESPACE_END TOML_IMPL_NAMESPACE_END
|
||||
#define TOML_ANON_NAMESPACE TOML_NAMESPACE::impl
|
||||
#define TOML_USING_ANON_NAMESPACE using namespace TOML_ANON_NAMESPACE
|
||||
#define TOML_EXTERNAL_LINKAGE inline
|
||||
#define TOML_INTERNAL_LINKAGE inline
|
||||
#else
|
||||
#define TOML_ANON_NAMESPACE_START namespace
|
||||
#define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); \
|
||||
using namespace toml; \
|
||||
namespace
|
||||
#define TOML_ANON_NAMESPACE_END static_assert(true)
|
||||
#define TOML_ANON_NAMESPACE
|
||||
#define TOML_USING_ANON_NAMESPACE static_cast<void>(0)
|
||||
#define TOML_EXTERNAL_LINKAGE
|
||||
#define TOML_INTERNAL_LINKAGE static
|
||||
#endif
|
||||
@ -785,18 +888,23 @@
|
||||
//# ASSERT
|
||||
//#====================================================================================================================
|
||||
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#ifndef TOML_ASSERT
|
||||
#if defined(NDEBUG) || !defined(_DEBUG)
|
||||
#define TOML_ASSERT(expr) static_cast<void>(0)
|
||||
#else
|
||||
#ifndef assert
|
||||
#include <cassert>
|
||||
#endif
|
||||
#define TOML_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
#ifdef NDEBUG
|
||||
#undef TOML_ASSERT
|
||||
#define TOML_ASSERT(expr) static_assert(true)
|
||||
#endif
|
||||
#ifndef TOML_ASSERT
|
||||
#ifndef assert
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <cassert>
|
||||
TOML_ENABLE_WARNINGS;
|
||||
#endif
|
||||
#define TOML_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
#ifdef NDEBUG
|
||||
#define TOML_ASSERT_ASSUME(expr) TOML_ASSUME(expr)
|
||||
#else
|
||||
#define TOML_ASSERT_ASSUME(expr) TOML_ASSERT(expr)
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
//#====================================================================================================================
|
||||
//# STATIC ASSERT MESSAGE FORMATTING
|
||||
@ -914,12 +1022,6 @@ TOML_ENABLE_WARNINGS;
|
||||
/// \detail Not defined by default. Meaningless when #TOML_HEADER_ONLY is enabled.
|
||||
|
||||
|
||||
/// \def TOML_LARGE_FILES
|
||||
/// \brief Sets whether line and column indices are 32-bit integers.
|
||||
/// \detail Defaults to `0`.
|
||||
/// \see toml::source_index
|
||||
|
||||
|
||||
#define TOML_OPTIONAL_TYPE
|
||||
/// \def TOML_OPTIONAL_TYPE
|
||||
/// \brief Overrides the `optional<T>` type used by the library.
|
||||
@ -929,11 +1031,22 @@ TOML_ENABLE_WARNINGS;
|
||||
/// (e.g. [tl::optional](https://github.com/TartanLlama/optional)).
|
||||
|
||||
|
||||
/// \def TOML_PARSER
|
||||
/// \brief Sets whether the parser-related parts of the library are included.
|
||||
/// \detail Defaults to `1`.
|
||||
/// \remarks If you don't need to parse TOML data from any strings or files (e.g. you're only using the library to
|
||||
/// serialize data as TOML), setting `TOML_PARSER` to `0` can yield decent compilation speed improvements.
|
||||
/// \def TOML_ENABLE_PARSER
|
||||
/// \brief Sets whether the parser-related parts of the library are included.
|
||||
/// \detail Defaults to `1`.
|
||||
/// \remarks If you don't parse any TOML from files or strings, setting `TOML_ENABLE_PARSER`
|
||||
/// to `0` can improve compilation speed and reduce binary size.
|
||||
|
||||
|
||||
/// \def TOML_ENABLE_FORMATTERS
|
||||
/// \brief Sets whether the various formatter classes are enabled.
|
||||
/// \detail Defaults to `1`.
|
||||
/// \remarks If you don't need to re-serialize TOML data, setting `TOML_ENABLE_FORMATTERS`
|
||||
/// to `0` can improve compilation speed and reduce binary size.
|
||||
/// \see
|
||||
/// - toml::toml_formatter
|
||||
/// - toml::json_formatter
|
||||
/// - toml::yaml_formatter
|
||||
|
||||
|
||||
#define TOML_SMALL_FLOAT_TYPE
|
||||
@ -943,20 +1056,21 @@ TOML_ENABLE_WARNINGS;
|
||||
/// \remark If you're building for a platform that has a built-in half precision float (e.g. `_Float16`), you don't
|
||||
/// need to use this configuration option to make toml++ aware of it; the library comes with that built-in.
|
||||
|
||||
|
||||
#define TOML_SMALL_INT_TYPE
|
||||
/// \def TOML_SMALL_INT_TYPE
|
||||
/// \brief If your codebase has an additional 'small' integer type (e.g. 24-bits), this tells toml++ about it.
|
||||
/// \detail Not defined by default.
|
||||
|
||||
|
||||
/// \def TOML_UNRELEASED_FEATURES
|
||||
/// \def TOML_ENABLE_UNRELEASED_FEATURES
|
||||
/// \brief Enables support for unreleased TOML language features not yet part of a
|
||||
/// [numbered version](https://github.com/toml-lang/toml/releases).
|
||||
/// \detail Defaults to `0`.
|
||||
/// \see [TOML Language Support](https://github.com/marzer/tomlplusplus/blob/master/README.md#toml-language-support)
|
||||
|
||||
|
||||
/// \def TOML_WINDOWS_COMPAT
|
||||
/// \def TOML_ENABLE_WINDOWS_COMPAT
|
||||
/// \brief Enables the use of wide strings (wchar_t, std::wstring) in various places throughout the library
|
||||
/// when building for Windows.
|
||||
/// \detail Defaults to `1` when building for Windows, `0` otherwise. Has no effect when building for anything other
|
||||
|
@ -2,465 +2,123 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "date_time.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
#include "std_string.h"
|
||||
#include "forward_declarations.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
// Q: "why does print_to_stream() exist? why not just use ostream::write(), ostream::put() etc?"
|
||||
// A: - I'm supporting C++20's char8_t as well; wrapping streams allows switching string modes transparently.
|
||||
// - I'm using <charconv> to format numerics. Faster and locale-independent.
|
||||
// - I can avoid forcing users to drag in <sstream> and <iomanip>.
|
||||
|
||||
// Q: "there's a bit of reinterpret_casting here, is any of it UB?"
|
||||
// A: - If the source string data is char and the output string is char8_t, then technically yes,
|
||||
// but not in the other direction. I test in both modes on Clang, GCC and MSVC and have yet to
|
||||
// see it actually causing an issue, but in the event it does present a problem it's not going to
|
||||
// be a show-stopper since all it means is I need to do duplicate some code.
|
||||
// - I can (potentially) avoid forcing users to drag in <sstream> and <iomanip>.
|
||||
// - Strings in C++. Honestly.
|
||||
|
||||
template <typename Char1, typename Char2>
|
||||
inline void print_to_stream(std::basic_string_view<Char1> str, std::basic_ostream<Char2> & stream)
|
||||
{
|
||||
static_assert(sizeof(Char1) == 1);
|
||||
static_assert(sizeof(Char2) == 1);
|
||||
stream.write(reinterpret_cast<const Char2*>(str.data()), static_cast<std::streamsize>(str.length()));
|
||||
}
|
||||
|
||||
template <typename Char1, typename Char2>
|
||||
inline void print_to_stream(const std::basic_string<Char1>& str, std::basic_ostream<Char2>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char1) == 1);
|
||||
static_assert(sizeof(Char2) == 1);
|
||||
stream.write(reinterpret_cast<const Char2*>(str.data()), static_cast<std::streamsize>(str.length()));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(char character, std::basic_ostream<Char>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
stream.put(static_cast<Char>(character));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
TOML_API
|
||||
TOML_ATTR(nonnull)
|
||||
inline void print_to_stream(const char* str, size_t len, std::basic_ostream<Char>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
stream.write(reinterpret_cast<const Char*>(str), static_cast<std::streamsize>(len));
|
||||
}
|
||||
void print_to_stream(std::ostream&, const char*, size_t);
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, std::string_view);
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(char8_t character, std::basic_ostream<Char>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
stream.put(static_cast<Char>(character));
|
||||
}
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const std::string&);
|
||||
|
||||
template <typename Char>
|
||||
TOML_ATTR(nonnull)
|
||||
inline void print_to_stream(const char8_t* str, size_t len, std::basic_ostream<Char>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
stream.write(reinterpret_cast<const Char*>(str), static_cast<std::streamsize>(len));
|
||||
}
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, char);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, int8_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, int16_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, int32_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, int64_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, uint8_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, uint16_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, uint32_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, uint64_t, value_flags = {}, size_t min_digits = 0);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, float, value_flags = {}, bool relaxed_precision = false);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, double, value_flags = {}, bool relaxed_precision = false);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, bool);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const toml::date&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const toml::time&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const toml::time_offset&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const toml::date_time&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const source_position&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const source_region&);
|
||||
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const array&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const table&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const value<std::string>&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const value<int64_t>&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const value<double>&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const value<bool>&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const value<date>&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const value<time>&);
|
||||
|
||||
TOML_API
|
||||
void print_to_stream(std::ostream&, const value<date_time>&);
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline constexpr size_t charconv_buffer_length = 0;
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<double> = 60;
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<float> = 40;
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint64_t> = 20; // strlen("18446744073709551615")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int64_t> = 20; // strlen("-9223372036854775808")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int32_t> = 11; // strlen("-2147483648")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int16_t> = 6; // strlen("-32768")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int8_t> = 4; // strlen("-128")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint32_t> = 10; // strlen("4294967295")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint16_t> = 5; // strlen("65535")
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint8_t> = 3; // strlen("255")
|
||||
|
||||
template <typename T, typename Char>
|
||||
inline void print_integer_to_stream(T val, std::basic_ostream<Char> & stream, value_flags format = {})
|
||||
template <typename T, typename U>
|
||||
inline void print_to_stream_bookended(std::ostream & stream, const T& val, const U& bookend)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
|
||||
if (!val)
|
||||
{
|
||||
print_to_stream('0', stream);
|
||||
return;
|
||||
}
|
||||
|
||||
int base = 10;
|
||||
if (format != value_flags::none && val >= T{})
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case value_flags::format_as_binary: base = 2; break;
|
||||
case value_flags::format_as_octal: base = 8; break;
|
||||
case value_flags::format_as_hexadecimal: base = 16; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML_INT_CHARCONV
|
||||
|
||||
char buf[(sizeof(T) * CHAR_BIT)];
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val, base);
|
||||
const auto len = static_cast<size_t>(res.ptr - buf);
|
||||
if (base == 16)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
if (buf[i] >= 'a')
|
||||
buf[i] -= 32;
|
||||
}
|
||||
print_to_stream(buf, len, stream);
|
||||
|
||||
#else
|
||||
|
||||
using unsigned_type = std::conditional_t<(sizeof(T) > sizeof(unsigned)), std::make_unsigned_t<T>, unsigned>;
|
||||
using cast_type = std::conditional_t<std::is_signed_v<T>, std::make_signed_t<unsigned_type>, unsigned_type>;
|
||||
|
||||
if TOML_UNLIKELY(format == value_flags::format_as_binary)
|
||||
{
|
||||
bool found_one = false;
|
||||
const auto v = static_cast<unsigned_type>(val);
|
||||
unsigned_type mask = unsigned_type{ 1 } << (sizeof(unsigned_type) * CHAR_BIT - 1u);
|
||||
for (unsigned i = 0; i < sizeof(unsigned_type) * CHAR_BIT; i++)
|
||||
{
|
||||
if ((v & mask))
|
||||
{
|
||||
print_to_stream('1', stream);
|
||||
found_one = true;
|
||||
}
|
||||
else if (found_one)
|
||||
print_to_stream('0', stream);
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss << std::uppercase << std::setbase(base);
|
||||
ss << static_cast<cast_type>(val);
|
||||
const auto str = std::move(ss).str();
|
||||
print_to_stream(str, stream);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#define TOML_P2S_OVERLOAD(T) \
|
||||
template <typename Char> \
|
||||
inline void print_to_stream(T val, std::basic_ostream<Char>& stream, value_flags format) \
|
||||
{ \
|
||||
static_assert(sizeof(Char) == 1); \
|
||||
print_integer_to_stream(val, stream, format); \
|
||||
} \
|
||||
static_assert(true)
|
||||
|
||||
TOML_P2S_OVERLOAD(int8_t);
|
||||
TOML_P2S_OVERLOAD(int16_t);
|
||||
TOML_P2S_OVERLOAD(int32_t);
|
||||
TOML_P2S_OVERLOAD(int64_t);
|
||||
TOML_P2S_OVERLOAD(uint8_t);
|
||||
TOML_P2S_OVERLOAD(uint16_t);
|
||||
TOML_P2S_OVERLOAD(uint32_t);
|
||||
TOML_P2S_OVERLOAD(uint64_t);
|
||||
|
||||
#undef TOML_P2S_OVERLOAD
|
||||
|
||||
template <typename T, typename Char>
|
||||
inline void print_floating_point_to_stream(T val, std::basic_ostream<Char> & stream, bool hexfloat = false)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
|
||||
switch (impl::fpclassify(val))
|
||||
{
|
||||
case fp_class::neg_inf: print_to_stream("-inf"sv, stream); break;
|
||||
|
||||
case fp_class::pos_inf: print_to_stream("inf"sv, stream); break;
|
||||
|
||||
case fp_class::nan: print_to_stream("nan"sv, stream); break;
|
||||
|
||||
case fp_class::ok:
|
||||
{
|
||||
static constexpr auto needs_decimal_point = [](auto&& s) noexcept
|
||||
{
|
||||
for (auto c : s)
|
||||
if (c == '.' || c == 'E' || c == 'e')
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
#if TOML_FLOAT_CHARCONV
|
||||
|
||||
char buf[charconv_buffer_length<T>];
|
||||
const auto res = hexfloat ? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
: std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
print_to_stream(str, stream);
|
||||
if (!hexfloat && needs_decimal_point(str))
|
||||
print_to_stream(".0"sv, stream);
|
||||
|
||||
#else
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss.precision(std::numeric_limits<T>::digits10 + 1);
|
||||
if (hexfloat)
|
||||
ss << std::hexfloat;
|
||||
ss << val;
|
||||
const auto str = std::move(ss).str();
|
||||
print_to_stream(str, stream);
|
||||
if (!hexfloat && needs_decimal_point(str))
|
||||
print_to_stream(".0"sv, stream);
|
||||
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
void print_floating_point_to_stream(double, std::ostream&, bool);
|
||||
#endif
|
||||
|
||||
#define TOML_P2S_OVERLOAD(Type) \
|
||||
template <typename Char> \
|
||||
inline void print_to_stream(Type val, std::basic_ostream<Char>& stream) \
|
||||
{ \
|
||||
static_assert(sizeof(Char) == 1); \
|
||||
print_floating_point_to_stream(val, stream); \
|
||||
} \
|
||||
static_assert(true)
|
||||
|
||||
TOML_P2S_OVERLOAD(double);
|
||||
|
||||
#undef TOML_P2S_OVERLOAD
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(bool val, std::basic_ostream<Char>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
print_to_stream(val ? "true"sv : "false"sv, stream);
|
||||
}
|
||||
|
||||
template <typename T, typename Char>
|
||||
inline void print_to_stream(T val, std::basic_ostream<Char> & stream, size_t zero_pad_to_digits)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
#if TOML_INT_CHARCONV
|
||||
|
||||
char buf[charconv_buffer_length<T>];
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto len = static_cast<size_t>(res.ptr - buf);
|
||||
for (size_t i = len; i < zero_pad_to_digits; i++)
|
||||
print_to_stream('0', stream);
|
||||
print_to_stream(buf, static_cast<size_t>(res.ptr - buf), stream);
|
||||
|
||||
#else
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
using cast_type = std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>;
|
||||
ss << std::setfill('0') << std::setw(static_cast<int>(zero_pad_to_digits)) << static_cast<cast_type>(val);
|
||||
const auto str = std::move(ss).str();
|
||||
print_to_stream(str, stream);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(const toml::date& val, std::basic_ostream<Char>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
print_to_stream(val.year, stream, 4_sz);
|
||||
print_to_stream('-', stream);
|
||||
print_to_stream(val.month, stream, 2_sz);
|
||||
print_to_stream('-', stream);
|
||||
print_to_stream(val.day, stream, 2_sz);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(const toml::time& val, std::basic_ostream<Char>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
print_to_stream(val.hour, stream, 2_sz);
|
||||
print_to_stream(':', stream);
|
||||
print_to_stream(val.minute, stream, 2_sz);
|
||||
print_to_stream(':', stream);
|
||||
print_to_stream(val.second, stream, 2_sz);
|
||||
if (val.nanosecond && val.nanosecond <= 999999999u)
|
||||
{
|
||||
print_to_stream('.', stream);
|
||||
auto ns = val.nanosecond;
|
||||
size_t digits = 9_sz;
|
||||
while (ns % 10u == 0u)
|
||||
{
|
||||
ns /= 10u;
|
||||
digits--;
|
||||
}
|
||||
print_to_stream(ns, stream, digits);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(toml::time_offset val, std::basic_ostream<Char> & stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
if (!val.minutes)
|
||||
print_to_stream('Z', stream);
|
||||
else
|
||||
{
|
||||
auto mins = static_cast<int>(val.minutes);
|
||||
if (mins < 0)
|
||||
{
|
||||
print_to_stream('-', stream);
|
||||
mins = -mins;
|
||||
}
|
||||
else
|
||||
print_to_stream('+', stream);
|
||||
const auto hours = mins / 60;
|
||||
if (hours)
|
||||
{
|
||||
print_to_stream(static_cast<unsigned int>(hours), stream, 2_sz);
|
||||
mins -= hours * 60;
|
||||
}
|
||||
else
|
||||
print_to_stream("00"sv, stream);
|
||||
print_to_stream(':', stream);
|
||||
print_to_stream(static_cast<unsigned int>(mins), stream, 2_sz);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void print_to_stream(const toml::date_time& val, std::basic_ostream<Char>& stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
print_to_stream(val.date, stream);
|
||||
print_to_stream('T', stream);
|
||||
print_to_stream(val.time, stream);
|
||||
if (val.offset)
|
||||
print_to_stream(*val.offset, stream);
|
||||
}
|
||||
|
||||
template <typename T, typename Char>
|
||||
void print_to_stream_with_escapes(T && str, std::basic_ostream<Char> & stream)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1);
|
||||
for (auto c : str)
|
||||
{
|
||||
if TOML_UNLIKELY(c >= '\x00' && c <= '\x1F')
|
||||
print_to_stream(low_character_escape_table[c], stream);
|
||||
else if TOML_UNLIKELY(c == '\x7F')
|
||||
print_to_stream("\\u007F"sv, stream);
|
||||
else if TOML_UNLIKELY(c == '"')
|
||||
print_to_stream("\\\""sv, stream);
|
||||
else if TOML_UNLIKELY(c == '\\')
|
||||
print_to_stream("\\\\"sv, stream);
|
||||
else
|
||||
print_to_stream(c, stream);
|
||||
}
|
||||
print_to_stream(stream, bookend);
|
||||
print_to_stream(stream, val);
|
||||
print_to_stream(stream, bookend);
|
||||
}
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief Prints a source_position to a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("bar = 42"sv);
|
||||
///
|
||||
/// std::cout << "The value for 'bar' was found on "sv
|
||||
/// << tbl.get("bar")->source().begin()
|
||||
/// << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// The value for 'bar' was found on line 1, column 7
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The output stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The source_position.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const source_position& rhs)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
impl::print_to_stream("line "sv, lhs);
|
||||
impl::print_to_stream(rhs.line, lhs);
|
||||
impl::print_to_stream(", column "sv, lhs);
|
||||
impl::print_to_stream(rhs.column, lhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints a source_region to a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("bar = 42", "config.toml");
|
||||
///
|
||||
/// std::cout << "The value for 'bar' was found on "sv
|
||||
/// << tbl.get("bar")->source()
|
||||
/// << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// The value for 'bar' was found on line 1, column 7 of 'config.toml'
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Char The output stream's underlying character type. Must be 1 byte in size.
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The source_position.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
template <typename Char>
|
||||
inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const source_region& rhs)
|
||||
{
|
||||
static_assert(sizeof(Char) == 1, "The stream's underlying character type must be 1 byte in size.");
|
||||
lhs << rhs.begin;
|
||||
if (rhs.path)
|
||||
{
|
||||
impl::print_to_stream(" of '"sv, lhs);
|
||||
impl::print_to_stream(*rhs.path, lhs);
|
||||
impl::print_to_stream('\'', lhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#if !defined(DOXYGEN) && !TOML_HEADER_ONLY
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const source_position&);
|
||||
extern template TOML_API
|
||||
std::ostream& operator<<(std::ostream&, const source_region&);
|
||||
#endif
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS;
|
||||
#include "header_end.h"
|
||||
|
472
include/toml++/impl/print_to_stream.inl
Normal file
472
include/toml++/impl/print_to_stream.inl
Normal file
@ -0,0 +1,472 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "print_to_stream.h"
|
||||
#include "source_region.h"
|
||||
#include "date_time.h"
|
||||
#include "toml_formatter.h"
|
||||
#include "value.h"
|
||||
#include "array.h"
|
||||
#include "table.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <ostream>
|
||||
#if TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV
|
||||
#include <charconv>
|
||||
#endif
|
||||
#if !TOML_INT_CHARCONV || !TOML_FLOAT_CHARCONV
|
||||
#include <sstream>
|
||||
#endif
|
||||
#if !TOML_INT_CHARCONV
|
||||
#include <iomanip>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_ANON_NAMESPACE_START
|
||||
{
|
||||
template <typename T>
|
||||
inline constexpr size_t charconv_buffer_length = 0;
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int8_t> = 4; // strlen("-128")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int16_t> = 6; // strlen("-32768")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int32_t> = 11; // strlen("-2147483648")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<int64_t> = 20; // strlen("-9223372036854775808")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint8_t> = 3; // strlen("255")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint16_t> = 5; // strlen("65535")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint32_t> = 10; // strlen("4294967295")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<uint64_t> = 20; // strlen("18446744073709551615")
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<float> = 64;
|
||||
|
||||
template <>
|
||||
inline constexpr size_t charconv_buffer_length<double> = 64;
|
||||
|
||||
template <typename T>
|
||||
TOML_INTERNAL_LINKAGE
|
||||
void print_integer_to_stream(std::ostream & stream, T val, value_flags format = {}, size_t min_digits = 0)
|
||||
{
|
||||
if (!val)
|
||||
{
|
||||
if (!min_digits)
|
||||
min_digits = 1;
|
||||
|
||||
for (size_t i = 0; i < min_digits; i++)
|
||||
stream.put('0');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static constexpr auto value_flags_mask =
|
||||
value_flags::format_as_binary | value_flags::format_as_octal | value_flags::format_as_hexadecimal;
|
||||
format &= value_flags_mask;
|
||||
|
||||
int base = 10;
|
||||
if (format != value_flags::none && val > T{})
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case value_flags::format_as_binary: base = 2; break;
|
||||
case value_flags::format_as_octal: base = 8; break;
|
||||
case value_flags::format_as_hexadecimal: base = 16; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML_INT_CHARCONV
|
||||
|
||||
char buf[(sizeof(T) * CHAR_BIT)];
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val, base);
|
||||
const auto len = static_cast<size_t>(res.ptr - buf);
|
||||
for (size_t i = len; i < min_digits; i++)
|
||||
stream.put('0');
|
||||
if (base == 16)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
if (buf[i] >= 'a')
|
||||
buf[i] -= 32;
|
||||
}
|
||||
impl::print_to_stream(stream, buf, len);
|
||||
|
||||
#else
|
||||
|
||||
using unsigned_type = std::conditional_t<(sizeof(T) > sizeof(unsigned)), std::make_unsigned_t<T>, unsigned>;
|
||||
using cast_type = std::conditional_t<std::is_signed_v<T>, std::make_signed_t<unsigned_type>, unsigned_type>;
|
||||
|
||||
if (base == 2)
|
||||
{
|
||||
const auto len = sizeof(T) * CHAR_BIT;
|
||||
for (size_t i = len; i < min_digits; i++)
|
||||
stream.put('0');
|
||||
|
||||
bool found_one = false;
|
||||
const auto v = static_cast<unsigned_type>(val);
|
||||
unsigned_type mask = unsigned_type{ 1 } << (len - 1u);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
if ((v & mask))
|
||||
{
|
||||
stream.put('1');
|
||||
found_one = true;
|
||||
}
|
||||
else if (found_one)
|
||||
stream.put('0');
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss << std::uppercase << std::setbase(base);
|
||||
if (min_digits)
|
||||
ss << std::setfill('0') << std::setw(static_cast<int>(min_digits));
|
||||
ss << static_cast<cast_type>(val);
|
||||
const auto str = std::move(ss).str();
|
||||
impl::print_to_stream(stream, str);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_INTERNAL_LINKAGE
|
||||
void print_floating_point_to_stream(std::ostream & stream,
|
||||
T val,
|
||||
value_flags format,
|
||||
[[maybe_unused]] bool relaxed_precision)
|
||||
{
|
||||
switch (impl::fpclassify(val))
|
||||
{
|
||||
case impl::fp_class::neg_inf: impl::print_to_stream(stream, "-inf"sv); break;
|
||||
|
||||
case impl::fp_class::pos_inf: impl::print_to_stream(stream, "inf"sv); break;
|
||||
|
||||
case impl::fp_class::nan: impl::print_to_stream(stream, "nan"sv); break;
|
||||
|
||||
case impl::fp_class::ok:
|
||||
{
|
||||
static constexpr auto needs_decimal_point = [](auto&& s) noexcept
|
||||
{
|
||||
for (auto c : s)
|
||||
if (c == '.' || c == 'E' || c == 'e')
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
#if TOML_FLOAT_CHARCONV
|
||||
|
||||
const auto hex = !!(format & value_flags::format_as_hexadecimal);
|
||||
char buf[charconv_buffer_length<T>];
|
||||
auto res = hex ? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
: std::to_chars(buf, buf + sizeof(buf), val);
|
||||
auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
|
||||
char buf2[charconv_buffer_length<T>];
|
||||
if (!hex && relaxed_precision)
|
||||
{
|
||||
res = std::to_chars(buf2, buf2 + sizeof(buf2), val, std::chars_format::general, 6);
|
||||
const auto str2 = std::string_view{ buf2, static_cast<size_t>(res.ptr - buf2) };
|
||||
if (str2.length() < str.length())
|
||||
str = str2;
|
||||
}
|
||||
|
||||
impl::print_to_stream(stream, str);
|
||||
if (!hex && needs_decimal_point(str))
|
||||
toml::impl::print_to_stream(stream, ".0"sv);
|
||||
|
||||
#else
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
if (!relaxed_precision)
|
||||
ss.precision(std::numeric_limits<T>::max_digits10);
|
||||
if (!!(format & value_flags::format_as_hexadecimal))
|
||||
ss << std::hexfloat;
|
||||
ss << val;
|
||||
const auto str = std::move(ss).str();
|
||||
impl::print_to_stream(stream, str);
|
||||
if (!(format & value_flags::format_as_hexadecimal) && needs_decimal_point(str))
|
||||
impl::print_to_stream(stream, ".0"sv);
|
||||
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_ANON_NAMESPACE_END;
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(nonnull)
|
||||
void print_to_stream(std::ostream & stream, const char* val, size_t len)
|
||||
{
|
||||
stream.write(val, static_cast<std::streamsize>(len));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, std::string_view val)
|
||||
{
|
||||
stream.write(val.data(), static_cast<std::streamsize>(val.length()));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const std::string& val)
|
||||
{
|
||||
stream.write(val.data(), static_cast<std::streamsize>(val.length()));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, char val)
|
||||
{
|
||||
stream.put(val);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, int8_t val, value_flags format, size_t min_digits)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_integer_to_stream(stream, val, format, min_digits);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, int16_t val, value_flags format, size_t min_digits)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_integer_to_stream(stream, val, format, min_digits);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, int32_t val, value_flags format, size_t min_digits)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_integer_to_stream(stream, val, format, min_digits);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, int64_t val, value_flags format, size_t min_digits)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_integer_to_stream(stream, val, format, min_digits);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, uint8_t val, value_flags format, size_t min_digits)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_integer_to_stream(stream, val, format, min_digits);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, uint16_t val, value_flags format, size_t min_digits)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_integer_to_stream(stream, val, format, min_digits);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, uint32_t val, value_flags format, size_t min_digits)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_integer_to_stream(stream, val, format, min_digits);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, uint64_t val, value_flags format, size_t min_digits)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_integer_to_stream(stream, val, format, min_digits);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, float val, value_flags format, bool relaxed_precision)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format, relaxed_precision);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, double val, value_flags format, bool relaxed_precision)
|
||||
{
|
||||
TOML_ANON_NAMESPACE::print_floating_point_to_stream(stream, val, format, relaxed_precision);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, bool val)
|
||||
{
|
||||
print_to_stream(stream, val ? "true"sv : "false"sv);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const toml::date& val)
|
||||
{
|
||||
print_to_stream(stream, val.year, {}, 4);
|
||||
stream.put('-');
|
||||
print_to_stream(stream, val.month, {}, 2);
|
||||
stream.put('-');
|
||||
print_to_stream(stream, val.day, {}, 2);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const toml::time& val)
|
||||
{
|
||||
print_to_stream(stream, val.hour, {}, 2);
|
||||
stream.put(':');
|
||||
print_to_stream(stream, val.minute, {}, 2);
|
||||
stream.put(':');
|
||||
print_to_stream(stream, val.second, {}, 2);
|
||||
if (val.nanosecond && val.nanosecond <= 999999999u)
|
||||
{
|
||||
stream.put('.');
|
||||
auto ns = val.nanosecond;
|
||||
size_t digits = 9u;
|
||||
while (ns % 10u == 0u)
|
||||
{
|
||||
ns /= 10u;
|
||||
digits--;
|
||||
}
|
||||
print_to_stream(stream, ns, {}, digits);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const toml::time_offset& val)
|
||||
{
|
||||
if (!val.minutes)
|
||||
{
|
||||
stream.put('Z');
|
||||
return;
|
||||
}
|
||||
|
||||
auto mins = static_cast<int>(val.minutes);
|
||||
if (mins < 0)
|
||||
{
|
||||
stream.put('-');
|
||||
mins = -mins;
|
||||
}
|
||||
else
|
||||
stream.put('+');
|
||||
const auto hours = mins / 60;
|
||||
if (hours)
|
||||
{
|
||||
print_to_stream(stream, static_cast<unsigned int>(hours), {}, 2);
|
||||
mins -= hours * 60;
|
||||
}
|
||||
else
|
||||
print_to_stream(stream, "00"sv);
|
||||
stream.put(':');
|
||||
print_to_stream(stream, static_cast<unsigned int>(mins), {}, 2);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const toml::date_time& val)
|
||||
{
|
||||
print_to_stream(stream, val.date);
|
||||
stream.put('T');
|
||||
print_to_stream(stream, val.time);
|
||||
if (val.offset)
|
||||
print_to_stream(stream, *val.offset);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const source_position& val)
|
||||
{
|
||||
print_to_stream(stream, "line "sv);
|
||||
print_to_stream(stream, val.line);
|
||||
print_to_stream(stream, ", column "sv);
|
||||
print_to_stream(stream, val.column);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const source_region& val)
|
||||
{
|
||||
print_to_stream(stream, val.begin);
|
||||
if (val.path)
|
||||
{
|
||||
print_to_stream(stream, " of '"sv);
|
||||
print_to_stream(stream, *val.path);
|
||||
stream.put('\'');
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const array& arr)
|
||||
{
|
||||
stream << toml_formatter{ arr };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const table& tbl)
|
||||
{
|
||||
stream << toml_formatter{ tbl };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const value<std::string>& val)
|
||||
{
|
||||
stream << toml_formatter{ val };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const value<int64_t>& val)
|
||||
{
|
||||
stream << toml_formatter{ val };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const value<double>& val)
|
||||
{
|
||||
stream << toml_formatter{ val };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const value<bool>& val)
|
||||
{
|
||||
stream << toml_formatter{ val };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const value<date>& val)
|
||||
{
|
||||
stream << toml_formatter{ val };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const value<time>& val)
|
||||
{
|
||||
stream << toml_formatter{ val };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void print_to_stream(std::ostream & stream, const value<date_time>& val)
|
||||
{
|
||||
stream << toml_formatter{ val };
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
35
include/toml++/impl/simd.h
Normal file
35
include/toml++/impl/simd.h
Normal file
@ -0,0 +1,35 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_SIMD
|
||||
|
||||
#if defined(__SSE2__) \
|
||||
|| (defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)))
|
||||
#define TOML_HAS_SSE2 1
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_1__) || (defined(_MSC_VER) && (defined(__AVX__) || defined(__AVX2__)))
|
||||
#define TOML_HAS_SSE4_1 1
|
||||
#endif
|
||||
|
||||
#endif // TOML_ENABLE_SIMD
|
||||
|
||||
#ifndef TOML_HAS_SSE2
|
||||
#define TOML_HAS_SSE2 0
|
||||
#endif
|
||||
#ifndef TOML_HAS_SSE4_1
|
||||
#define TOML_HAS_SSE4_1 0
|
||||
#endif
|
||||
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#if TOML_HAS_SSE4_1
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
#if TOML_HAS_SSE2
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
195
include/toml++/impl/source_region.h
Normal file
195
include/toml++/impl/source_region.h
Normal file
@ -0,0 +1,195 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "std_optional.h"
|
||||
#include "std_string.h"
|
||||
#include "forward_declarations.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief The integer type used to tally line numbers and columns.
|
||||
using source_index = uint32_t;
|
||||
|
||||
/// \brief A pointer to a shared string resource containing a source path.
|
||||
using source_path_ptr = std::shared_ptr<const std::string>;
|
||||
|
||||
/// \brief A source document line-and-column pair.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto table = toml::parse_file("config.toml"sv);
|
||||
/// std::cout << "The node 'description' was defined at "sv
|
||||
/// << table.get("description")->source().begin()
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// The value 'description' was defined at line 7, column 15
|
||||
/// \eout
|
||||
///
|
||||
/// \remarks toml++'s parser is unicode-aware insofar as it knows how to handle
|
||||
/// non-ASCII whitespace and newline characters, but it doesn't give much thought
|
||||
/// to combining marks, grapheme clusters vs. characters, et cetera.
|
||||
/// If a TOML document contains lots of codepoints outside of the ASCII range
|
||||
/// you may find that your source_positions don't match those given by a text editor
|
||||
/// (typically the line numbers will be accurate but column numbers will be too high).
|
||||
/// <strong>This is not an error.</strong> I've chosen this behaviour as a deliberate trade-off
|
||||
/// between parser complexity and correctness.
|
||||
struct TOML_TRIVIAL_ABI source_position
|
||||
{
|
||||
/// \brief The line number.
|
||||
/// \remarks Valid line numbers start at 1.
|
||||
source_index line;
|
||||
|
||||
/// \brief The column number.
|
||||
/// \remarks Valid column numbers start at 1.
|
||||
source_index column;
|
||||
|
||||
/// \brief Returns true if both line and column numbers are non-zero.
|
||||
TOML_NODISCARD
|
||||
explicit constexpr operator bool() const noexcept
|
||||
{
|
||||
return line > source_index{} && column > source_index{};
|
||||
}
|
||||
|
||||
/// \brief Returns true if two source_positions represent the same line and column.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator==(const source_position& lhs, const source_position& rhs) noexcept
|
||||
{
|
||||
return lhs.line == rhs.line && lhs.column == rhs.column;
|
||||
}
|
||||
|
||||
/// \brief Returns true if two source_positions do not represent the same line and column.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator!=(const source_position& lhs, const source_position& rhs) noexcept
|
||||
{
|
||||
return lhs.line != rhs.line || lhs.column != rhs.column;
|
||||
}
|
||||
|
||||
/// \brief Returns true if the LHS position is before the RHS position.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<(const source_position& lhs, const source_position& rhs) noexcept
|
||||
{
|
||||
return lhs.line < rhs.line || (lhs.line == rhs.line && lhs.column < rhs.column);
|
||||
}
|
||||
|
||||
/// \brief Returns true if the LHS position is before the RHS position or equal to it.
|
||||
TOML_NODISCARD
|
||||
friend constexpr bool operator<=(const source_position& lhs, const source_position& rhs) noexcept
|
||||
{
|
||||
return lhs.line < rhs.line || (lhs.line == rhs.line && lhs.column <= rhs.column);
|
||||
}
|
||||
|
||||
/// \brief Prints a source_position to a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("bar = 42"sv);
|
||||
///
|
||||
/// std::cout << "The value for 'bar' was found on "sv
|
||||
/// << tbl.get("bar")->source().begin()
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// The value for 'bar' was found on line 1, column 7
|
||||
/// \eout
|
||||
///
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The source_position.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const source_position& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A source document region.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse_file("config.toml"sv);
|
||||
/// if (auto server = tbl.get("server"))
|
||||
/// {
|
||||
/// std::cout << "begin: "sv << server->source().begin << "\n";
|
||||
/// std::cout << "end: "sv << server->source().end << "\n";
|
||||
/// std::cout << "path: "sv << *server->source().path << "\n";
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// begin: line 3, column 1
|
||||
/// end: line 3, column 22
|
||||
/// path: config.toml
|
||||
/// \eout
|
||||
///
|
||||
/// \remarks toml++'s parser is unicode-aware insofar as it knows how to handle
|
||||
/// non-ASCII whitespace and newline characters, but it doesn't give much thought
|
||||
/// to combining marks, grapheme clusters vs. characters, et cetera.
|
||||
/// If a TOML document contains lots of codepoints outside of the ASCII range
|
||||
/// you may find that your source_positions don't match those given by a text editor
|
||||
/// (typically the line numbers will be accurate but column numbers will be too high).
|
||||
/// <strong>This is not an error.</strong> I've chosen this behaviour as a deliberate trade-off
|
||||
/// between parser complexity and correctness.
|
||||
struct source_region
|
||||
{
|
||||
/// \brief The beginning of the region (inclusive).
|
||||
source_position begin;
|
||||
|
||||
/// \brief The end of the region (exclusive).
|
||||
source_position end;
|
||||
|
||||
/// \brief The path to the corresponding source document.
|
||||
///
|
||||
/// \remarks This will be `nullptr` if no path was provided to toml::parse().
|
||||
source_path_ptr path;
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief The path to the corresponding source document as a wide-string.
|
||||
///
|
||||
/// \availability This function is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \remarks This will return an empty optional if no path was provided to toml::parse().
|
||||
TOML_NODISCARD
|
||||
optional<std::wstring> wide_path() const
|
||||
{
|
||||
if (!path || path->empty())
|
||||
return {};
|
||||
return { impl::widen(*path) };
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Prints a source_region to a stream.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("bar = 42", "config.toml");
|
||||
///
|
||||
/// std::cout << "The value for 'bar' was found on "sv
|
||||
/// << tbl.get("bar")->source()
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// The value for 'bar' was found on line 1, column 7 of 'config.toml'
|
||||
/// \eout
|
||||
///
|
||||
/// \param lhs The stream.
|
||||
/// \param rhs The source_position.
|
||||
///
|
||||
/// \returns The input stream.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const source_region& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
12
include/toml++/impl/std_except.h
Normal file
12
include/toml++/impl/std_except.h
Normal file
@ -0,0 +1,12 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#if TOML_EXCEPTIONS
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
10
include/toml++/impl/std_initializer_list.h
Normal file
10
include/toml++/impl/std_initializer_list.h
Normal file
@ -0,0 +1,10 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <initializer_list>
|
||||
TOML_ENABLE_WARNINGS;
|
11
include/toml++/impl/std_map.h
Normal file
11
include/toml++/impl/std_map.h
Normal file
@ -0,0 +1,11 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <map>
|
||||
#include <iterator>
|
||||
TOML_ENABLE_WARNINGS;
|
18
include/toml++/impl/std_new.h
Normal file
18
include/toml++/impl/std_new.h
Normal file
@ -0,0 +1,18 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <new>
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
#if TOML_CLANG >= 8 || TOML_GCC >= 7 || TOML_ICC >= 1910 || TOML_MSVC >= 1914
|
||||
#define TOML_LAUNDER(x) __builtin_launder(x)
|
||||
#elif defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
|
||||
#define TOML_LAUNDER(x) std::launder(x)
|
||||
#else
|
||||
#define TOML_LAUNDER(x) x
|
||||
#endif
|
32
include/toml++/impl/std_optional.h
Normal file
32
include/toml++/impl/std_optional.h
Normal file
@ -0,0 +1,32 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#if !TOML_HAS_CUSTOM_OPTIONAL_TYPE
|
||||
#include <optional>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
#if TOML_HAS_CUSTOM_OPTIONAL_TYPE
|
||||
|
||||
template <typename T>
|
||||
using optional = TOML_OPTIONAL_TYPE<T>;
|
||||
|
||||
#else
|
||||
|
||||
/// \brief The 'optional' type used throughout the library.
|
||||
///
|
||||
/// \remarks By default this will be an alias for std::optional, but you can change the optional type
|
||||
/// used by the library by defining #TOML_OPTIONAL_TYPE.
|
||||
template <typename T>
|
||||
using optional = std::optional<T>;
|
||||
|
||||
#endif
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
53
include/toml++/impl/std_string.h
Normal file
53
include/toml++/impl/std_string.h
Normal file
@ -0,0 +1,53 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
#if defined(DOXYGEN) \
|
||||
|| (defined(__cpp_char8_t) && __cpp_char8_t >= 201811 && defined(__cpp_lib_char8_t) \
|
||||
&& __cpp_lib_char8_t >= 201907)
|
||||
#define TOML_HAS_CHAR8 1
|
||||
#else
|
||||
#define TOML_HAS_CHAR8 0
|
||||
#endif
|
||||
|
||||
/// \cond
|
||||
|
||||
namespace toml // non-abi namespace; this is not an error
|
||||
{
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
std::string narrow(std::wstring_view);
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
std::wstring widen(std::string_view);
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
std::wstring widen(std::u8string_view);
|
||||
|
||||
#endif
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \endcond
|
99
include/toml++/impl/std_string.inl
Normal file
99
include/toml++/impl/std_string.inl
Normal file
@ -0,0 +1,99 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
#include "std_string.h"
|
||||
#ifndef _WINDOWS_
|
||||
#if TOML_INCLUDE_WINDOWS_H
|
||||
#include <Windows.h>
|
||||
#else
|
||||
|
||||
extern "C" __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int CodePage,
|
||||
unsigned long dwFlags,
|
||||
const wchar_t* lpWideCharStr,
|
||||
int cchWideChar,
|
||||
char* lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
const char* lpDefaultChar,
|
||||
int* lpUsedDefaultChar);
|
||||
|
||||
extern "C" __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage,
|
||||
unsigned long dwFlags,
|
||||
const char* lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
wchar_t* lpWideCharStr,
|
||||
int cchWideChar);
|
||||
|
||||
#endif // TOML_INCLUDE_WINDOWS_H
|
||||
#endif // _WINDOWS_
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::string narrow(std::wstring_view str)
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
|
||||
std::string s;
|
||||
const auto len =
|
||||
::WideCharToMultiByte(65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0, nullptr, nullptr);
|
||||
if (len)
|
||||
{
|
||||
s.resize(static_cast<size_t>(len));
|
||||
::WideCharToMultiByte(65001,
|
||||
0,
|
||||
str.data(),
|
||||
static_cast<int>(str.length()),
|
||||
s.data(),
|
||||
len,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::wstring widen(std::string_view str)
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
|
||||
std::wstring s;
|
||||
const auto len = ::MultiByteToWideChar(65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0);
|
||||
if (len)
|
||||
{
|
||||
s.resize(static_cast<size_t>(len));
|
||||
::MultiByteToWideChar(65001, 0, str.data(), static_cast<int>(str.length()), s.data(), len);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
std::wstring widen(std::u8string_view str)
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
|
||||
return widen(std::string_view{ reinterpret_cast<const char*>(str.data()), str.length() });
|
||||
}
|
||||
|
||||
#endif // TOML_HAS_CHAR8
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
10
include/toml++/impl/std_utility.h
Normal file
10
include/toml++/impl/std_utility.h
Normal file
@ -0,0 +1,10 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <utility>
|
||||
TOML_ENABLE_WARNINGS;
|
11
include/toml++/impl/std_vector.h
Normal file
11
include/toml++/impl/std_vector.h
Normal file
@ -0,0 +1,11 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
TOML_ENABLE_WARNINGS;
|
File diff suppressed because it is too large
Load Diff
294
include/toml++/impl/table.inl
Normal file
294
include/toml++/impl/table.inl
Normal file
@ -0,0 +1,294 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "table.h"
|
||||
#include "node_view.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(const impl::table_init_pair* b, const impl::table_init_pair* e)
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
|
||||
TOML_ASSERT_ASSUME(b);
|
||||
TOML_ASSERT_ASSUME(e);
|
||||
TOML_ASSERT_ASSUME(b <= e);
|
||||
|
||||
if TOML_UNLIKELY(b == e)
|
||||
return;
|
||||
|
||||
for (; b != e; b++)
|
||||
{
|
||||
if (!b->value) // empty node_views
|
||||
continue;
|
||||
|
||||
map_.insert_or_assign(std::move(b->key), std::move(b->value));
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(const table& other) //
|
||||
: node(other),
|
||||
inline_{ other.inline_ }
|
||||
{
|
||||
for (auto&& [k, v] : other.map_)
|
||||
map_.emplace_hint(map_.end(), k, impl::make_node(*v));
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(table && other) noexcept //
|
||||
: node(std::move(other)),
|
||||
map_{ std::move(other.map_) },
|
||||
inline_{ other.inline_ }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::operator=(const table& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(rhs);
|
||||
map_.clear();
|
||||
for (auto&& [k, v] : rhs.map_)
|
||||
map_.emplace_hint(map_.end(), k, impl::make_node(*v));
|
||||
inline_ = rhs.inline_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::operator=(table&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
map_ = std::move(rhs.map_);
|
||||
inline_ = rhs.inline_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::is_homogeneous(node_type ntype) const noexcept
|
||||
{
|
||||
if (map_.empty())
|
||||
return false;
|
||||
|
||||
if (ntype == node_type::none)
|
||||
ntype = map_.cbegin()->second->type();
|
||||
|
||||
for (auto&& [k, v] : map_)
|
||||
{
|
||||
TOML_UNUSED(k);
|
||||
if (v->type() != ntype)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::is_homogeneous(node_type ntype, node * &first_nonmatch) noexcept
|
||||
{
|
||||
if (map_.empty())
|
||||
{
|
||||
first_nonmatch = {};
|
||||
return false;
|
||||
}
|
||||
if (ntype == node_type::none)
|
||||
ntype = map_.cbegin()->second->type();
|
||||
for (const auto& [k, v] : map_)
|
||||
{
|
||||
TOML_UNUSED(k);
|
||||
if (v->type() != ntype)
|
||||
{
|
||||
first_nonmatch = v.get();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept
|
||||
{
|
||||
node* fnm = nullptr;
|
||||
const auto result = const_cast<table&>(*this).is_homogeneous(ntype, fnm);
|
||||
first_nonmatch = fnm;
|
||||
return result;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node* table::get(std::string_view key) noexcept
|
||||
{
|
||||
if (auto it = map_.find(key); it != map_.end())
|
||||
return it->second.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node& table::at(std::string_view key)
|
||||
{
|
||||
auto n = get(key);
|
||||
|
||||
#if TOML_COMPILER_EXCEPTIONS
|
||||
|
||||
if (!n)
|
||||
{
|
||||
auto err = "key '"s;
|
||||
err.append(key);
|
||||
err.append("' not found in table"sv);
|
||||
throw std::out_of_range{ err };
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
TOML_ASSERT_ASSUME(n && "key not found in table!");
|
||||
|
||||
#endif
|
||||
|
||||
return *n;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::map_iterator table::get_lower_bound(std::string_view key) noexcept
|
||||
{
|
||||
return map_.lower_bound(key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::find(std::string_view key) noexcept
|
||||
{
|
||||
return iterator{ map_.find(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::const_iterator table::find(std::string_view key) const noexcept
|
||||
{
|
||||
return const_iterator{ map_.find(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::map_iterator table::erase(const_map_iterator pos) noexcept
|
||||
{
|
||||
return map_.erase(pos);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::map_iterator table::erase(const_map_iterator begin, const_map_iterator end) noexcept
|
||||
{
|
||||
return map_.erase(begin, end);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
size_t table::erase(std::string_view key) noexcept
|
||||
{
|
||||
if (auto it = map_.find(key); it != map_.end())
|
||||
{
|
||||
map_.erase(it);
|
||||
return size_t{ 1 };
|
||||
}
|
||||
return size_t{};
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::prune(bool recursive)& noexcept
|
||||
{
|
||||
if (map_.empty())
|
||||
return *this;
|
||||
|
||||
for (auto it = map_.begin(); it != map_.end();)
|
||||
{
|
||||
if (auto arr = it->second->as_array())
|
||||
{
|
||||
if (recursive)
|
||||
arr->prune(true);
|
||||
|
||||
if (arr->empty())
|
||||
{
|
||||
it = map_.erase(it);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (auto tbl = it->second->as_table())
|
||||
{
|
||||
if (recursive)
|
||||
tbl->prune(true);
|
||||
|
||||
if (tbl->empty())
|
||||
{
|
||||
it = map_.erase(it);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void table::clear() noexcept
|
||||
{
|
||||
map_.clear();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::map_iterator table::insert_with_hint(const_iterator hint, key && k, impl::node_ptr && v)
|
||||
{
|
||||
return map_.emplace_hint(const_map_iterator{ hint }, std::move(k), std::move(v));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::equal(const table& lhs, const table& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.map_.size() != rhs.map_.size())
|
||||
return false;
|
||||
|
||||
for (auto l = lhs.map_.begin(), r = rhs.map_.begin(), e = lhs.map_.end(); l != e; l++, r++)
|
||||
{
|
||||
if (l->first != r->first)
|
||||
return false;
|
||||
|
||||
const auto lhs_type = l->second->type();
|
||||
const node& rhs_ = *r->second;
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = l->second->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
@ -1,210 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "table.h"
|
||||
#include "node_view.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table() noexcept
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(const table& other) noexcept //
|
||||
: node(other),
|
||||
inline_{ other.inline_ }
|
||||
{
|
||||
for (auto&& [k, v] : other)
|
||||
map.emplace_hint(map.end(), k, impl::make_node(v));
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(table && other) noexcept //
|
||||
: node(std::move(other)),
|
||||
map{ std::move(other.map) },
|
||||
inline_{ other.inline_ }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::operator=(const table& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(rhs);
|
||||
map.clear();
|
||||
for (auto&& [k, v] : rhs)
|
||||
map.emplace_hint(map.end(), k, impl::make_node(v));
|
||||
inline_ = rhs.inline_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::operator=(table&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
map = std::move(rhs.map);
|
||||
inline_ = rhs.inline_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(impl::table_init_pair * pairs, size_t count) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
if (!pairs[i].value) // empty node_views
|
||||
continue;
|
||||
map.insert_or_assign(std::move(pairs[i].key), std::move(pairs[i].value));
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::is_homogeneous(node_type ntype) const noexcept
|
||||
{
|
||||
if (map.empty())
|
||||
return false;
|
||||
|
||||
if (ntype == node_type::none)
|
||||
ntype = map.cbegin()->second->type();
|
||||
|
||||
for (const auto& [k, v] : map)
|
||||
{
|
||||
(void)k;
|
||||
if (v->type() != ntype)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template <typename T, typename U>
|
||||
TOML_INTERNAL_LINKAGE
|
||||
bool table_is_homogeneous(T& map, node_type ntype, U& first_nonmatch) noexcept
|
||||
{
|
||||
if (map.empty())
|
||||
{
|
||||
first_nonmatch = {};
|
||||
return false;
|
||||
}
|
||||
if (ntype == node_type::none)
|
||||
ntype = map.cbegin()->second->type();
|
||||
for (const auto& [k, v] : map)
|
||||
{
|
||||
(void)k;
|
||||
if (v->type() != ntype)
|
||||
{
|
||||
first_nonmatch = v.get();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::is_homogeneous(node_type ntype, toml::node * &first_nonmatch) noexcept
|
||||
{
|
||||
return impl::table_is_homogeneous(map, ntype, first_nonmatch);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::is_homogeneous(node_type ntype, const toml::node*& first_nonmatch) const noexcept
|
||||
{
|
||||
return impl::table_is_homogeneous(map, ntype, first_nonmatch);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<node> table::operator[](std::string_view key) noexcept
|
||||
{
|
||||
return node_view<node>{ this->get(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<const node> table::operator[](std::string_view key) const noexcept
|
||||
{
|
||||
return node_view<const node>{ this->get(key) };
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<node> table::operator[](std::wstring_view key) noexcept
|
||||
{
|
||||
return node_view<node>{ this->get(key) };
|
||||
}
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node_view<const node> table::operator[](std::wstring_view key) const noexcept
|
||||
{
|
||||
return node_view<const node>{ this->get(key) };
|
||||
}
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator==(const table& lhs, const table& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.map.size() != rhs.map.size())
|
||||
return false;
|
||||
|
||||
for (auto l = lhs.map.begin(), r = rhs.map.begin(), e = lhs.map.end(); l != e; l++, r++)
|
||||
{
|
||||
if (l->first != r->first)
|
||||
return false;
|
||||
|
||||
const auto lhs_type = l->second->type();
|
||||
const node& rhs_ = *r->second;
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = l->second->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool operator!=(const table& lhs, const table& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
/// \endcond
|
@ -1,148 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
#if TOML_HEADER_ONLY && !TOML_INTELLISENSE
|
||||
#error This header cannot not be included when TOML_HEADER_ONLY is enabled.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
#include "node_view.h"
|
||||
#include "default_formatter.h"
|
||||
#include "json_formatter.h"
|
||||
#if TOML_PARSER
|
||||
#include "parser.h"
|
||||
#endif
|
||||
|
||||
// internal implementation namespace
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
// formatters
|
||||
template class formatter<char>;
|
||||
|
||||
// print to stream machinery
|
||||
template void print_floating_point_to_stream(double, std::ostream&, bool);
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
// public namespace
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
// value<>
|
||||
template class value<std::string>;
|
||||
template class value<int64_t>;
|
||||
template class value<double>;
|
||||
template class value<bool>;
|
||||
template class value<date>;
|
||||
template class value<time>;
|
||||
template class value<date_time>;
|
||||
|
||||
// node_view
|
||||
template class node_view<node>;
|
||||
template class node_view<const node>;
|
||||
|
||||
// formatters
|
||||
template class default_formatter<char>;
|
||||
template class json_formatter<char>;
|
||||
|
||||
// various ostream operators
|
||||
template std::ostream& operator<<(std::ostream&, const source_position&);
|
||||
template std::ostream& operator<<(std::ostream&, const source_region&);
|
||||
template std::ostream& operator<<(std::ostream&, const date&);
|
||||
template std::ostream& operator<<(std::ostream&, const time&);
|
||||
template std::ostream& operator<<(std::ostream&, const time_offset&);
|
||||
template std::ostream& operator<<(std::ostream&, const date_time&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<std::string>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<int64_t>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<double>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<bool>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<toml::date>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<toml::time>&);
|
||||
template std::ostream& operator<<(std::ostream&, const value<toml::date_time>&);
|
||||
template std::ostream& operator<<(std::ostream&, default_formatter<char>&);
|
||||
template std::ostream& operator<<(std::ostream&, default_formatter<char>&&);
|
||||
template std::ostream& operator<<(std::ostream&, json_formatter<char>&);
|
||||
template std::ostream& operator<<(std::ostream&, json_formatter<char>&&);
|
||||
template std::ostream& operator<<(std::ostream&, const table&);
|
||||
template std::ostream& operator<<(std::ostream&, const array&);
|
||||
template std::ostream& operator<<(std::ostream&, const node_view<node>&);
|
||||
template std::ostream& operator<<(std::ostream&, const node_view<const node>&);
|
||||
template std::ostream& operator<<(std::ostream&, node_type);
|
||||
|
||||
// node::value, node_view:::value etc
|
||||
#define TOML_INSTANTIATE(name, T) \
|
||||
template optional<T> node::name<T>() const noexcept; \
|
||||
template optional<T> node_view<node>::name<T>() const noexcept; \
|
||||
template optional<T> node_view<const node>::name<T>() const noexcept
|
||||
|
||||
TOML_INSTANTIATE(value_exact, std::string_view);
|
||||
TOML_INSTANTIATE(value_exact, std::string);
|
||||
TOML_INSTANTIATE(value_exact, const char*);
|
||||
TOML_INSTANTIATE(value_exact, int64_t);
|
||||
TOML_INSTANTIATE(value_exact, double);
|
||||
TOML_INSTANTIATE(value_exact, date);
|
||||
TOML_INSTANTIATE(value_exact, time);
|
||||
TOML_INSTANTIATE(value_exact, date_time);
|
||||
TOML_INSTANTIATE(value_exact, bool);
|
||||
TOML_INSTANTIATE(value, std::string_view);
|
||||
TOML_INSTANTIATE(value, std::string);
|
||||
TOML_INSTANTIATE(value, const char*);
|
||||
TOML_INSTANTIATE(value, signed char);
|
||||
TOML_INSTANTIATE(value, signed short);
|
||||
TOML_INSTANTIATE(value, signed int);
|
||||
TOML_INSTANTIATE(value, signed long);
|
||||
TOML_INSTANTIATE(value, signed long long);
|
||||
TOML_INSTANTIATE(value, unsigned char);
|
||||
TOML_INSTANTIATE(value, unsigned short);
|
||||
TOML_INSTANTIATE(value, unsigned int);
|
||||
TOML_INSTANTIATE(value, unsigned long);
|
||||
TOML_INSTANTIATE(value, unsigned long long);
|
||||
TOML_INSTANTIATE(value, double);
|
||||
TOML_INSTANTIATE(value, float);
|
||||
TOML_INSTANTIATE(value, date);
|
||||
TOML_INSTANTIATE(value, time);
|
||||
TOML_INSTANTIATE(value, date_time);
|
||||
TOML_INSTANTIATE(value, bool);
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_INSTANTIATE(value_exact, std::u8string_view);
|
||||
TOML_INSTANTIATE(value_exact, std::u8string);
|
||||
TOML_INSTANTIATE(value_exact, const char8_t*);
|
||||
TOML_INSTANTIATE(value, std::u8string_view);
|
||||
TOML_INSTANTIATE(value, std::u8string);
|
||||
TOML_INSTANTIATE(value, const char8_t*);
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
TOML_INSTANTIATE(value_exact, std::wstring);
|
||||
TOML_INSTANTIATE(value, std::wstring);
|
||||
#endif
|
||||
#undef TOML_INSTANTIATE
|
||||
|
||||
// parser instantiations
|
||||
#if TOML_PARSER
|
||||
|
||||
// parse error ostream
|
||||
template std::ostream& operator<<(std::ostream&, const parse_error&);
|
||||
|
||||
// parse() and parse_file()
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
template parse_result parse(std::istream&, std::string_view) TOML_MAY_THROW;
|
||||
template parse_result parse(std::istream&, std::string &&) TOML_MAY_THROW;
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
|
||||
#endif // TOML_PARSER
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
153
include/toml++/impl/toml_formatter.h
Normal file
153
include/toml++/impl/toml_formatter.h
Normal file
@ -0,0 +1,153 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "std_vector.h"
|
||||
#include "formatter.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted TOML.
|
||||
///
|
||||
/// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
///
|
||||
/// \remarks You generally don't need to create an instance of this class explicitly; the stream
|
||||
/// operators of the TOML node types already print themselves out using this formatter.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::table{
|
||||
/// { "description", "This is some TOML, yo." },
|
||||
/// { "fruit", toml::array{ "apple", "orange", "pear" } },
|
||||
/// { "numbers", toml::array{ 1, 2, 3, 4, 5 } },
|
||||
/// { "table", toml::table{ { "foo", "bar" } } }
|
||||
/// };
|
||||
///
|
||||
/// // these two lines are equivalent:
|
||||
/// std::cout << toml::toml_formatter{ tbl } << "\n";
|
||||
/// std::cout << tbl << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// description = "This is some TOML, yo."
|
||||
/// fruit = ["apple", "orange", "pear"]
|
||||
/// numbers = [1, 2, 3, 4, 5]
|
||||
///
|
||||
/// [table]
|
||||
/// foo = "bar"
|
||||
/// \eout
|
||||
class toml_formatter : impl::formatter
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter;
|
||||
std::vector<const key*> key_path_;
|
||||
bool pending_table_separator_ = false;
|
||||
|
||||
TOML_API
|
||||
void print_pending_table_separator();
|
||||
|
||||
TOML_API
|
||||
void print(const key&);
|
||||
|
||||
TOML_API
|
||||
void print_inline(const toml::table&);
|
||||
|
||||
TOML_API
|
||||
void print(const toml::array&);
|
||||
|
||||
TOML_API
|
||||
void print(const toml::table&);
|
||||
|
||||
TOML_API
|
||||
void print();
|
||||
|
||||
static constexpr impl::formatter_constants constants = { format_flags::none, // mandatory
|
||||
format_flags::none, // ignored
|
||||
"inf"sv,
|
||||
"-inf"sv,
|
||||
"nan"sv,
|
||||
"true"sv,
|
||||
"false"sv };
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief The default flags for a toml_formatter.
|
||||
static constexpr format_flags default_flags = constants.mandatory_flags //
|
||||
| format_flags::allow_literal_strings //
|
||||
| format_flags::allow_multi_line_strings //
|
||||
| format_flags::allow_unicode_strings //
|
||||
| format_flags::allow_real_tabs_in_strings //
|
||||
| format_flags::allow_binary_integers //
|
||||
| format_flags::allow_octal_integers //
|
||||
| format_flags::allow_hexadecimal_integers //
|
||||
| format_flags::indentation;
|
||||
|
||||
/// \brief Constructs a TOML formatter and binds it to a TOML object.
|
||||
///
|
||||
/// \param source The source TOML object.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit toml_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
|
||||
: base{ &source, nullptr, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a TOML formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
/// \availability This constructor is only available when exceptions are disabled.
|
||||
///
|
||||
/// \attention Formatting a failed parse result will simply dump the error message out as-is.
|
||||
/// This will not be valid TOML, but at least gives you something to log or show up in diagnostics:
|
||||
/// \cpp
|
||||
/// std::cout << toml::toml_formatter{ toml::parse("a = 'b'"sv) } // ok
|
||||
/// << "\n\n"
|
||||
/// << toml::toml_formatter{ toml::parse("a = "sv) } // malformed
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// a = 'b'
|
||||
///
|
||||
/// Error while parsing key-value pair: encountered end-of-file
|
||||
/// (error occurred at line 1, column 5)
|
||||
/// \eout
|
||||
/// Use the library with exceptions if you want to avoid this scenario.
|
||||
///
|
||||
/// \param result The parse result.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit toml_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ nullptr, &result, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as formatted TOML.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, toml_formatter& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.key_path_.clear();
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload).
|
||||
friend std::ostream& operator<<(std::ostream& lhs, toml_formatter&& rhs)
|
||||
{
|
||||
return lhs << rhs; // as lvalue
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
396
include/toml++/impl/toml_formatter.inl
Normal file
396
include/toml++/impl/toml_formatter.inl
Normal file
@ -0,0 +1,396 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
//# {{
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "toml_formatter.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "value.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "unicode.h"
|
||||
#include "header_start.h"
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
TOML_ANON_NAMESPACE_START
|
||||
{
|
||||
TOML_INTERNAL_LINKAGE
|
||||
size_t toml_formatter_count_inline_columns(const node& node, size_t line_wrap_cols) noexcept
|
||||
{
|
||||
switch (node.type())
|
||||
{
|
||||
case node_type::table:
|
||||
{
|
||||
auto& tbl = *reinterpret_cast<const table*>(&node);
|
||||
if (tbl.empty())
|
||||
return 2u; // "{}"
|
||||
size_t weight = 3u; // "{ }"
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
weight += k.length() + toml_formatter_count_inline_columns(v, line_wrap_cols) + 2u; // + ", "
|
||||
if (weight >= line_wrap_cols)
|
||||
break;
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
case node_type::array:
|
||||
{
|
||||
auto& arr = *reinterpret_cast<const array*>(&node);
|
||||
if (arr.empty())
|
||||
return 2u; // "[]"
|
||||
size_t weight = 3u; // "[ ]"
|
||||
for (auto& elem : arr)
|
||||
{
|
||||
weight += toml_formatter_count_inline_columns(elem, line_wrap_cols) + 2u; // + ", "
|
||||
if (weight >= line_wrap_cols)
|
||||
break;
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
case node_type::string:
|
||||
{
|
||||
// todo: proper utf8 decoding?
|
||||
// todo: tab awareness?
|
||||
auto& str = (*reinterpret_cast<const value<std::string>*>(&node)).get();
|
||||
return str.length() + 2u; // + ""
|
||||
}
|
||||
|
||||
case node_type::integer:
|
||||
{
|
||||
auto val = (*reinterpret_cast<const value<int64_t>*>(&node)).get();
|
||||
if (!val)
|
||||
return 1u;
|
||||
size_t weight = {};
|
||||
if (val < 0)
|
||||
{
|
||||
weight += 1u;
|
||||
val *= -1;
|
||||
}
|
||||
return weight + static_cast<size_t>(log10(static_cast<double>(val))) + 1u;
|
||||
}
|
||||
|
||||
case node_type::floating_point:
|
||||
{
|
||||
auto val = (*reinterpret_cast<const value<double>*>(&node)).get();
|
||||
if (val == 0.0)
|
||||
return 3u; // "0.0"
|
||||
size_t weight = 2u; // ".0"
|
||||
if (val < 0.0)
|
||||
{
|
||||
weight += 1u;
|
||||
val *= -1.0;
|
||||
}
|
||||
return weight + static_cast<size_t>(log10(val)) + 1u;
|
||||
break;
|
||||
}
|
||||
|
||||
case node_type::boolean: return 5u;
|
||||
case node_type::date: [[fallthrough]];
|
||||
case node_type::time: return 10u;
|
||||
case node_type::date_time: return 30u;
|
||||
case node_type::none: TOML_UNREACHABLE;
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_INTERNAL_LINKAGE
|
||||
bool toml_formatter_forces_multiline(const node& node, size_t line_wrap_cols, size_t starting_column_bias) noexcept
|
||||
{
|
||||
return (toml_formatter_count_inline_columns(node, line_wrap_cols) + starting_column_bias) >= line_wrap_cols;
|
||||
}
|
||||
}
|
||||
TOML_ANON_NAMESPACE_END;
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print_pending_table_separator()
|
||||
{
|
||||
if (pending_table_separator_)
|
||||
{
|
||||
print_newline(true);
|
||||
print_newline(true);
|
||||
pending_table_separator_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print(const key& k)
|
||||
{
|
||||
print_string(k.str(), false, true);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print_inline(const table& tbl)
|
||||
{
|
||||
if (tbl.empty())
|
||||
{
|
||||
print_unformatted("{}"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
print_unformatted("{ "sv);
|
||||
|
||||
bool first = false;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (first)
|
||||
print_unformatted(", "sv);
|
||||
first = true;
|
||||
|
||||
print(k);
|
||||
print_unformatted(" = "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
print_unformatted(" }"sv);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print(const array& arr)
|
||||
{
|
||||
if (arr.empty())
|
||||
{
|
||||
print_unformatted("[]"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto original_indent = indent();
|
||||
const auto multiline = TOML_ANON_NAMESPACE::toml_formatter_forces_multiline(
|
||||
arr,
|
||||
120u,
|
||||
indent_columns() * static_cast<size_t>(original_indent < 0 ? 0 : original_indent));
|
||||
|
||||
print_unformatted("["sv);
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
if (original_indent < 0)
|
||||
indent(0);
|
||||
if (indent_array_elements())
|
||||
increase_indent();
|
||||
}
|
||||
else
|
||||
print_unformatted(' ');
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
if (i > 0u)
|
||||
{
|
||||
print_unformatted(',');
|
||||
if (!multiline)
|
||||
print_unformatted(' ');
|
||||
}
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
print_newline(true);
|
||||
print_indent();
|
||||
}
|
||||
|
||||
auto& v = arr[i];
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: print_value(v, type);
|
||||
}
|
||||
}
|
||||
if (multiline)
|
||||
{
|
||||
indent(original_indent);
|
||||
print_newline(true);
|
||||
print_indent();
|
||||
}
|
||||
else
|
||||
print_unformatted(' ');
|
||||
|
||||
print_unformatted("]"sv);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print(const table& tbl)
|
||||
{
|
||||
static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept
|
||||
{
|
||||
auto arr = nde.as_array();
|
||||
return arr && arr->is_array_of_tables() && !arr->template get_as<table>(0u)->is_inline();
|
||||
};
|
||||
|
||||
// values, arrays, and inline tables/table arrays
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
const auto type = v.type();
|
||||
if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline())
|
||||
|| (type == node_type::array && is_non_inline_array_of_tables(v)))
|
||||
continue;
|
||||
|
||||
pending_table_separator_ = true;
|
||||
print_newline();
|
||||
print_indent();
|
||||
print(k);
|
||||
print_unformatted(" = "sv);
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
default: print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
const auto print_key_path = [&]()
|
||||
{
|
||||
size_t i{};
|
||||
for (const auto k : key_path_)
|
||||
{
|
||||
if (i++)
|
||||
print_unformatted('.');
|
||||
print(*k);
|
||||
}
|
||||
};
|
||||
|
||||
// non-inline tables
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
const auto type = v.type();
|
||||
if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline())
|
||||
continue;
|
||||
auto& child_tbl = *reinterpret_cast<const table*>(&v);
|
||||
|
||||
// we can skip indenting and emitting the headers for tables that only contain other tables
|
||||
// (so we don't over-nest)
|
||||
size_t child_value_count{}; // includes inline tables and non-table arrays
|
||||
size_t child_table_count{};
|
||||
size_t child_table_array_count{};
|
||||
for (auto&& [child_k, child_v] : child_tbl)
|
||||
{
|
||||
TOML_UNUSED(child_k);
|
||||
const auto child_type = child_v.type();
|
||||
TOML_ASSUME(child_type != node_type::none);
|
||||
switch (child_type)
|
||||
{
|
||||
case node_type::table:
|
||||
if (reinterpret_cast<const table*>(&child_v)->is_inline())
|
||||
child_value_count++;
|
||||
else
|
||||
child_table_count++;
|
||||
break;
|
||||
|
||||
case node_type::array:
|
||||
if (is_non_inline_array_of_tables(child_v))
|
||||
child_table_array_count++;
|
||||
else
|
||||
child_value_count++;
|
||||
break;
|
||||
|
||||
default: child_value_count++;
|
||||
}
|
||||
}
|
||||
bool skip_self = false;
|
||||
if (child_value_count == 0u && (child_table_count > 0u || child_table_array_count > 0u))
|
||||
skip_self = true;
|
||||
|
||||
key_path_.push_back(&k);
|
||||
|
||||
if (!skip_self)
|
||||
{
|
||||
print_pending_table_separator();
|
||||
if (indent_sub_tables())
|
||||
increase_indent();
|
||||
print_indent();
|
||||
print_unformatted("["sv);
|
||||
print_key_path();
|
||||
print_unformatted("]"sv);
|
||||
pending_table_separator_ = true;
|
||||
}
|
||||
|
||||
print(child_tbl);
|
||||
|
||||
key_path_.pop_back();
|
||||
if (!skip_self && indent_sub_tables())
|
||||
decrease_indent();
|
||||
}
|
||||
|
||||
// table arrays
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (!is_non_inline_array_of_tables(v))
|
||||
continue;
|
||||
auto& arr = *reinterpret_cast<const array*>(&v);
|
||||
|
||||
if (indent_sub_tables())
|
||||
increase_indent();
|
||||
key_path_.push_back(&k);
|
||||
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
{
|
||||
print_pending_table_separator();
|
||||
print_indent();
|
||||
print_unformatted("[["sv);
|
||||
print_key_path();
|
||||
print_unformatted("]]"sv);
|
||||
pending_table_separator_ = true;
|
||||
print(*reinterpret_cast<const table*>(&arr[i]));
|
||||
}
|
||||
|
||||
key_path_.pop_back();
|
||||
if (indent_sub_tables())
|
||||
decrease_indent();
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void toml_formatter::print()
|
||||
{
|
||||
if (dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
switch (auto source_type = source().type())
|
||||
{
|
||||
case node_type::table:
|
||||
{
|
||||
auto& tbl = *reinterpret_cast<const table*>(&source());
|
||||
if (tbl.is_inline())
|
||||
print_inline(tbl);
|
||||
else
|
||||
{
|
||||
decrease_indent(); // so root kvps and tables have the same indent
|
||||
print(tbl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&source())); break;
|
||||
|
||||
default: print_value(source(), source_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
@ -2,138 +2,151 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
#include "header_start.h"
|
||||
/// \cond
|
||||
|
||||
#if TOML_GCC && TOML_GCC < 9
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O1") // codegen bugs
|
||||
#endif
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_whitespace(char32_t codepoint) noexcept
|
||||
// note: a number of these functions were machine-generated. you'll know them when you see them.
|
||||
// they are tested separately in another project, I promise!
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_string_delimiter(char32_t c) noexcept
|
||||
{
|
||||
return codepoint == U'\t' || codepoint == U' ';
|
||||
return c == U'"' || c == U'\'';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_non_ascii_whitespace(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_ascii_letter(char32_t c) noexcept
|
||||
{
|
||||
// see: https://en.wikipedia.org/wiki/Whitespace_character#Unicode
|
||||
// (characters that don't say "is a line-break")
|
||||
|
||||
return codepoint == U'\u00A0' // no-break space
|
||||
|| codepoint == U'\u1680' // ogham space mark
|
||||
|| (codepoint >= U'\u2000' && codepoint <= U'\u200A') // em quad -> hair space
|
||||
|| codepoint == U'\u202F' // narrow no-break space
|
||||
|| codepoint == U'\u205F' // medium mathematical space
|
||||
|| codepoint == U'\u3000' // ideographic space
|
||||
;
|
||||
return (c >= U'a' && c <= U'z') || (c >= U'A' && c <= U'Z');
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_whitespace(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_binary_digit(char32_t c) noexcept
|
||||
{
|
||||
return is_ascii_whitespace(codepoint) || is_non_ascii_whitespace(codepoint);
|
||||
return c == U'0' || c == U'1';
|
||||
}
|
||||
|
||||
template <bool IncludeCarriageReturn = true>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_line_break(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_octal_digit(char32_t c) noexcept
|
||||
{
|
||||
constexpr auto low_range_end = IncludeCarriageReturn ? U'\r' : U'\f';
|
||||
return (codepoint >= U'\n' && codepoint <= low_range_end);
|
||||
return (c >= U'0' && c <= U'7');
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_non_ascii_line_break(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_decimal_digit(char32_t c) noexcept
|
||||
{
|
||||
// see https://en.wikipedia.org/wiki/Whitespace_character#Unicode
|
||||
// (characters that say "is a line-break")
|
||||
|
||||
return codepoint == U'\u0085' // next line
|
||||
|| codepoint == U'\u2028' // line separator
|
||||
|| codepoint == U'\u2029' // paragraph separator
|
||||
;
|
||||
return (c >= U'0' && c <= U'9');
|
||||
}
|
||||
|
||||
template <bool IncludeCarriageReturn = true>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_line_break(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_line_break<IncludeCarriageReturn>(codepoint) || is_non_ascii_line_break(codepoint);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_string_delimiter(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'"' || codepoint == U'\'';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_ascii_letter(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'a' && codepoint <= U'z') || (codepoint >= U'A' && codepoint <= U'Z');
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_binary_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'0' || codepoint == U'1';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_octal_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'0' && codepoint <= U'7');
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_decimal_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'0' && codepoint <= U'9');
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_hexadecimal_digit(char32_t c) noexcept
|
||||
{
|
||||
return U'0' <= c && c <= U'f' && (1ull << (static_cast<uint_least64_t>(c) - 0x30u)) & 0x7E0000007E03FFull;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr uint_least32_t hex_to_dec(const T codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr uint_least32_t hex_to_dec(const T c) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<remove_cvref_t<T>, uint_least32_t>)
|
||||
return codepoint >= 0x41u // >= 'A'
|
||||
? 10u + (codepoint | 0x20u) - 0x61u // - 'a'
|
||||
: codepoint - 0x30u // - '0'
|
||||
if constexpr (std::is_same_v<remove_cvref<T>, uint_least32_t>)
|
||||
return c >= 0x41u // >= 'A'
|
||||
? 10u + (c | 0x20u) - 0x61u // - 'a'
|
||||
: c - 0x30u // - '0'
|
||||
;
|
||||
else
|
||||
return hex_to_dec(static_cast<uint_least32_t>(codepoint));
|
||||
return hex_to_dec(static_cast<uint_least32_t>(c));
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_ascii_horizontal_whitespace(char32_t c) noexcept
|
||||
{
|
||||
return c == U'\t' || c == U' ';
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_non_ascii_horizontal_whitespace(char32_t c) noexcept
|
||||
{
|
||||
if (c < U'\xA0' || c > U'\uFEFF')
|
||||
return false;
|
||||
|
||||
const auto child_index_0 = (static_cast<uint_least64_t>(c) - 0xA0ull) / 0x3FAull;
|
||||
if ((1ull << child_index_0) & 0x7FFFFFFFFFFFF75Eull)
|
||||
return false;
|
||||
if (c == U'\xA0' || c == U'\u3000' || c == U'\uFEFF')
|
||||
return true;
|
||||
switch (child_index_0)
|
||||
{
|
||||
case 0x05: return c == U'\u1680' || c == U'\u180E';
|
||||
case 0x07:
|
||||
return (U'\u2000' <= c && c <= U'\u200B') || (U'\u205F' <= c && c <= U'\u2060') || c == U'\u202F';
|
||||
default: TOML_UNREACHABLE;
|
||||
}
|
||||
// 20 code units from 8 ranges (spanning a search area of 65120)
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_horizontal_whitespace(char32_t c) noexcept
|
||||
{
|
||||
return is_ascii_horizontal_whitespace(c) || is_non_ascii_horizontal_whitespace(c);
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_ascii_vertical_whitespace(char32_t c) noexcept
|
||||
{
|
||||
return U'\n' <= c && c <= U'\r';
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_non_ascii_vertical_whitespace(char32_t c) noexcept
|
||||
{
|
||||
return (U'\u2028' <= c && c <= U'\u2029') || c == U'\x85';
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_vertical_whitespace(char32_t c) noexcept
|
||||
{
|
||||
return is_ascii_vertical_whitespace(c) || is_non_ascii_vertical_whitespace(c);
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_whitespace(char32_t c) noexcept
|
||||
{
|
||||
return is_horizontal_whitespace(c) || is_vertical_whitespace(c);
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_ascii_bare_key_character(char32_t c) noexcept
|
||||
{
|
||||
#if TOML_LANG_UNRELEASED // toml/issues/644 ('+' in bare keys)
|
||||
if (c == U'+')
|
||||
return true;
|
||||
#endif
|
||||
|
||||
if (c < U'-' || c > U'z')
|
||||
return false;
|
||||
|
||||
if ((1ull << (static_cast<uint_least64_t>(c) - 0x2Du)) & 0xFFF43FFFFFF01FF9ull)
|
||||
return true;
|
||||
return (((static_cast<uint_least64_t>(c) - 0x2Dull) / 0x40ull) != 0)
|
||||
|| ((1ull << (static_cast<uint_least64_t>(c) - 0x2Du)) & 0xFFF43FFFFFF01FF9ull);
|
||||
}
|
||||
|
||||
#if TOML_LANG_UNRELEASED // toml/issues/687 (unicode bare keys)
|
||||
|
||||
//# Returns true if a codepoint belongs to any of these categories:
|
||||
//# Ll, Lm, Lo, Lt, Lu
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_non_ascii_letter(char32_t c) noexcept
|
||||
{
|
||||
if (U'\xAA' > c || c > U'\U0003134A')
|
||||
@ -486,8 +499,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
//# Returns true if a codepoint belongs to any of these categories:
|
||||
//# Nd, Nl
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_non_ascii_number(char32_t c) noexcept
|
||||
{
|
||||
if (U'\u0660' > c || c > U'\U0001FBF9')
|
||||
@ -640,8 +652,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
//# Returns true if a codepoint belongs to any of these categories:
|
||||
//# Mn, Mc
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_combining_mark(char32_t c) noexcept
|
||||
{
|
||||
if (U'\u0300' > c || c > U'\U000E01EF')
|
||||
@ -849,51 +860,55 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_non_ascii_bare_key_character(char32_t c) noexcept
|
||||
{
|
||||
return is_non_ascii_letter(c) || is_non_ascii_number(c) || is_combining_mark(c);
|
||||
}
|
||||
|
||||
#endif // TOML_LANG_UNRELEASED
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_bare_key_character(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_bare_key_character(char32_t c) noexcept
|
||||
{
|
||||
return is_ascii_letter(codepoint) || is_decimal_digit(codepoint) || codepoint == U'-' || codepoint == U'_'
|
||||
#if TOML_LANG_UNRELEASED // toml/issues/644 ('+' in bare keys) & toml/issues/687 (unicode bare keys)
|
||||
|| codepoint == U'+' || is_non_ascii_letter(codepoint) || is_non_ascii_number(codepoint)
|
||||
|| is_combining_mark(codepoint)
|
||||
return is_ascii_bare_key_character(c)
|
||||
#if TOML_LANG_UNRELEASED // toml/issues/687 (unicode bare keys)
|
||||
|| is_non_ascii_bare_key_character(c)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_value_terminator(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_value_terminator(char32_t c) noexcept
|
||||
{
|
||||
return is_ascii_line_break(codepoint) || is_ascii_whitespace(codepoint) || codepoint == U']'
|
||||
|| codepoint == U'}' || codepoint == U',' || codepoint == U'#' || is_non_ascii_line_break(codepoint)
|
||||
|| is_non_ascii_whitespace(codepoint);
|
||||
return is_whitespace(c) || c == U']' || c == U'}' || c == U',' || c == U'#';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_control_character(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_control_character(char c) noexcept
|
||||
{
|
||||
return codepoint <= U'\u001F' || codepoint == U'\u007F';
|
||||
return c <= '\u001F' || c == '\u007F';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_nontab_control_character(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_control_character(char32_t c) noexcept
|
||||
{
|
||||
return codepoint <= U'\u0008' || (codepoint >= U'\u000A' && codepoint <= U'\u001F') || codepoint == U'\u007F';
|
||||
return c <= U'\u001F' || c == U'\u007F';
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
constexpr bool is_unicode_surrogate(char32_t codepoint) noexcept
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_nontab_control_character(char32_t c) noexcept
|
||||
{
|
||||
return codepoint >= 0xD800u && codepoint <= 0xDFFF;
|
||||
return c <= U'\u0008' || (c >= U'\u000A' && c <= U'\u001F') || c == U'\u007F';
|
||||
}
|
||||
|
||||
struct utf8_decoder final
|
||||
TOML_CONST_GETTER
|
||||
constexpr bool is_unicode_surrogate(char32_t c) noexcept
|
||||
{
|
||||
return c >= 0xD800u && c <= 0xDFFF;
|
||||
}
|
||||
|
||||
struct utf8_decoder
|
||||
{
|
||||
// utf8_decoder based on this: https://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||
@ -919,27 +934,27 @@ TOML_IMPL_NAMESPACE_START
|
||||
36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
|
||||
};
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
constexpr bool error() const noexcept
|
||||
{
|
||||
return state == uint_least32_t{ 12u };
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
constexpr bool has_code_point() const noexcept
|
||||
{
|
||||
return state == uint_least32_t{};
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
constexpr bool needs_more_input() const noexcept
|
||||
{
|
||||
return state > uint_least32_t{} && state != uint_least32_t{ 12u };
|
||||
return !has_code_point() && !error();
|
||||
}
|
||||
|
||||
constexpr void operator()(uint8_t byte) noexcept
|
||||
{
|
||||
TOML_ASSERT(!error());
|
||||
TOML_ASSERT_ASSUME(!error());
|
||||
|
||||
const auto type = state_table[byte];
|
||||
|
||||
@ -949,9 +964,29 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
state = state_table[state + uint_least32_t{ 256u } + type];
|
||||
}
|
||||
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr void operator()(char c) noexcept
|
||||
{
|
||||
operator()(static_cast<uint8_t>(c));
|
||||
}
|
||||
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr void reset() noexcept
|
||||
{
|
||||
state = {};
|
||||
}
|
||||
};
|
||||
|
||||
TOML_PURE_GETTER
|
||||
TOML_ATTR(nonnull)
|
||||
bool is_ascii(const char* str, size_t len) noexcept;
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SWITCH_WARNINGS
|
||||
#if TOML_GCC && TOML_GCC < 9
|
||||
#pragma GCC pop_options
|
||||
#endif
|
||||
|
||||
/// \endcond
|
||||
#include "header_end.h"
|
59
include/toml++/impl/unicode.inl
Normal file
59
include/toml++/impl/unicode.inl
Normal file
@ -0,0 +1,59 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "unicode.h"
|
||||
#include "simd.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool is_ascii(const char* str, size_t len) noexcept
|
||||
{
|
||||
const char* const end = str + len;
|
||||
|
||||
#if TOML_HAS_SSE2 && (128 % CHAR_BIT) == 0
|
||||
{
|
||||
constexpr size_t chars_per_vector = 128u / CHAR_BIT;
|
||||
|
||||
if (const size_t simdable = len - (len % chars_per_vector))
|
||||
{
|
||||
__m128i mask = _mm_setzero_si128();
|
||||
for (const char* const e = str + simdable; str < e; str += chars_per_vector)
|
||||
{
|
||||
const __m128i current_bytes = _mm_loadu_si128(reinterpret_cast<const __m128i*>(str));
|
||||
mask = _mm_or_si128(mask, current_bytes);
|
||||
}
|
||||
const __m128i has_error = _mm_cmpgt_epi8(_mm_setzero_si128(), mask);
|
||||
|
||||
#if TOML_HAS_SSE4_1
|
||||
if (!_mm_testz_si128(has_error, has_error))
|
||||
return false;
|
||||
#else
|
||||
if (_mm_movemask_epi8(_mm_cmpeq_epi8(has_error, _mm_setzero_si128())) != 0xFFFF)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (; str < end; str++)
|
||||
if (static_cast<unsigned char>(*str) > 127u)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
@ -1,399 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
#include "utf8.h"
|
||||
#include "parse_error.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
#define TOML_ERROR_CHECK (void)0
|
||||
#define TOML_ERROR throw parse_error
|
||||
#else
|
||||
#define TOML_ERROR_CHECK \
|
||||
if (err) \
|
||||
return nullptr
|
||||
#define TOML_ERROR err.emplace
|
||||
#endif
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
template <typename T>
|
||||
class utf8_byte_stream;
|
||||
|
||||
inline constexpr auto utf8_byte_order_mark = "\xEF\xBB\xBF"sv;
|
||||
|
||||
template <typename Char>
|
||||
class TOML_API utf8_byte_stream<std::basic_string_view<Char>> final
|
||||
{
|
||||
static_assert(sizeof(Char) == 1_sz);
|
||||
|
||||
private:
|
||||
std::basic_string_view<Char> source;
|
||||
size_t position = {};
|
||||
|
||||
public:
|
||||
explicit constexpr utf8_byte_stream(std::basic_string_view<Char> sv) noexcept : source{ sv }
|
||||
{
|
||||
// trim trailing nulls
|
||||
const size_t initial_len = source.length();
|
||||
size_t actual_len = initial_len;
|
||||
for (size_t i = actual_len; i-- > 0_sz;)
|
||||
{
|
||||
if (source[i] != Char{}) // not '\0'
|
||||
{
|
||||
actual_len = i + 1_sz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (initial_len != actual_len)
|
||||
source = source.substr(0_sz, actual_len);
|
||||
|
||||
// skip bom
|
||||
if (actual_len >= 3_sz && memcmp(utf8_byte_order_mark.data(), source.data(), 3_sz) == 0)
|
||||
position += 3_sz;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool eof() const noexcept
|
||||
{
|
||||
return position >= source.length();
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool peek_eof() const noexcept
|
||||
{
|
||||
return eof();
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
constexpr bool error() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
constexpr unsigned int operator()() noexcept
|
||||
{
|
||||
if (position >= source.length())
|
||||
return 0xFFFFFFFFu;
|
||||
return static_cast<unsigned int>(static_cast<uint8_t>(source[position++]));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
class TOML_API utf8_byte_stream<std::basic_istream<Char>> final
|
||||
{
|
||||
static_assert(sizeof(Char) == 1_sz);
|
||||
|
||||
private:
|
||||
std::basic_istream<Char>* source;
|
||||
|
||||
public:
|
||||
explicit utf8_byte_stream(std::basic_istream<Char>& stream) : source{ &stream }
|
||||
{
|
||||
if (!source->good()) // eof, fail, bad
|
||||
return;
|
||||
|
||||
const auto initial_pos = source->tellg();
|
||||
Char bom[3];
|
||||
source->read(bom, 3);
|
||||
if (source->bad() || (source->gcount() == 3 && memcmp(utf8_byte_order_mark.data(), bom, 3_sz) == 0))
|
||||
return;
|
||||
|
||||
source->clear();
|
||||
source->seekg(initial_pos, std::basic_istream<Char>::beg);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
bool eof() const noexcept
|
||||
{
|
||||
return source->eof();
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
bool peek_eof() const
|
||||
{
|
||||
using stream_traits = typename std::remove_pointer_t<decltype(source)>::traits_type;
|
||||
return eof() || source->peek() == stream_traits::eof();
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
bool error() const noexcept
|
||||
{
|
||||
return !(*source);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
unsigned int operator()()
|
||||
{
|
||||
auto val = source->get();
|
||||
if (val == std::basic_istream<Char>::traits_type::eof())
|
||||
return 0xFFFFFFFFu;
|
||||
return static_cast<unsigned int>(val);
|
||||
}
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_LARGE_FILES, lf, sf);
|
||||
|
||||
struct utf8_codepoint final
|
||||
{
|
||||
char32_t value;
|
||||
char bytes[4];
|
||||
source_position position;
|
||||
|
||||
TOML_NODISCARD
|
||||
std::string_view as_view() const noexcept
|
||||
{
|
||||
return bytes[3] ? std::string_view{ bytes, 4_sz } : std::string_view{ bytes };
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
constexpr operator char32_t&() noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
constexpr operator const char32_t&() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(pure)
|
||||
constexpr const char32_t& operator*() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
static_assert(std::is_trivial_v<utf8_codepoint>);
|
||||
static_assert(std::is_standard_layout_v<utf8_codepoint>);
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_LARGE_FILES
|
||||
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
struct TOML_ABSTRACT_BASE utf8_reader_interface
|
||||
{
|
||||
TOML_NODISCARD
|
||||
virtual const source_path_ptr& source_path() const noexcept = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual const utf8_codepoint* read_next() = 0;
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual bool peek_eof() const = 0;
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
TOML_NODISCARD
|
||||
virtual optional<parse_error>&& error() noexcept = 0;
|
||||
|
||||
#endif
|
||||
|
||||
virtual ~utf8_reader_interface() noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TOML_EMPTY_BASES TOML_API utf8_reader final : public utf8_reader_interface
|
||||
{
|
||||
private:
|
||||
utf8_byte_stream<T> stream;
|
||||
utf8_decoder decoder;
|
||||
utf8_codepoint codepoints[2];
|
||||
size_t cp_idx = 1;
|
||||
uint8_t current_byte_count{};
|
||||
source_path_ptr source_path_;
|
||||
#if !TOML_EXCEPTIONS
|
||||
optional<parse_error> err;
|
||||
#endif
|
||||
|
||||
public:
|
||||
template <typename U, typename String = std::string_view>
|
||||
explicit utf8_reader(U&& source, String&& source_path = {}) noexcept(
|
||||
std::is_nothrow_constructible_v<utf8_byte_stream<T>, U&&>)
|
||||
: stream{ static_cast<U&&>(source) }
|
||||
{
|
||||
std::memset(codepoints, 0, sizeof(codepoints));
|
||||
codepoints[0].position = { 1, 1 };
|
||||
codepoints[1].position = { 1, 1 };
|
||||
|
||||
if (!source_path.empty())
|
||||
source_path_ = std::make_shared<const std::string>(static_cast<String&&>(source_path));
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const source_path_ptr& source_path() const noexcept override
|
||||
{
|
||||
return source_path_;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const utf8_codepoint* read_next() override
|
||||
{
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
auto& prev = codepoints[(cp_idx - 1_sz) % 2_sz];
|
||||
|
||||
if (stream.eof())
|
||||
return nullptr;
|
||||
else if (stream.error())
|
||||
TOML_ERROR("An error occurred while reading from the underlying stream", prev.position, source_path_);
|
||||
else if (decoder.error())
|
||||
TOML_ERROR("Encountered invalid utf-8 sequence", prev.position, source_path_);
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
while (true)
|
||||
{
|
||||
uint8_t next_byte;
|
||||
{
|
||||
unsigned int next_byte_raw{ 0xFFFFFFFFu };
|
||||
if constexpr (noexcept(stream()) || !TOML_EXCEPTIONS)
|
||||
{
|
||||
next_byte_raw = stream();
|
||||
}
|
||||
#if TOML_EXCEPTIONS
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
next_byte_raw = stream();
|
||||
}
|
||||
catch (const std::exception& exc)
|
||||
{
|
||||
throw parse_error{ exc.what(), prev.position, source_path_ };
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw parse_error{ "An unspecified error occurred", prev.position, source_path_ };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (next_byte_raw >= 256u)
|
||||
{
|
||||
if (stream.eof())
|
||||
{
|
||||
if (decoder.needs_more_input())
|
||||
TOML_ERROR("Encountered EOF during incomplete utf-8 code point sequence",
|
||||
prev.position,
|
||||
source_path_);
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
TOML_ERROR("An error occurred while reading from the underlying stream",
|
||||
prev.position,
|
||||
source_path_);
|
||||
}
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
next_byte = static_cast<uint8_t>(next_byte_raw);
|
||||
}
|
||||
|
||||
decoder(next_byte);
|
||||
if (decoder.error())
|
||||
TOML_ERROR("Encountered invalid utf-8 sequence", prev.position, source_path_);
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
auto& current = codepoints[cp_idx % 2_sz];
|
||||
current.bytes[current_byte_count++] = static_cast<char>(next_byte);
|
||||
if (decoder.has_code_point())
|
||||
{
|
||||
// store codepoint
|
||||
current.value = decoder.codepoint;
|
||||
|
||||
// reset prev (will be the next 'current')
|
||||
std::memset(prev.bytes, 0, sizeof(prev.bytes));
|
||||
current_byte_count = {};
|
||||
if (is_line_break<false>(current.value))
|
||||
prev.position = { static_cast<source_index>(current.position.line + 1), 1 };
|
||||
else
|
||||
prev.position = { current.position.line,
|
||||
static_cast<source_index>(current.position.column + 1) };
|
||||
cp_idx++;
|
||||
return ¤t;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool peek_eof() const override
|
||||
{
|
||||
return stream.peek_eof();
|
||||
}
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
TOML_NODISCARD
|
||||
optional<parse_error>&& error() noexcept override
|
||||
{
|
||||
return std::move(err);
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_string_view<Char>, std::string_view) -> utf8_reader<std::basic_string_view<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_string_view<Char>, std::string &&) -> utf8_reader<std::basic_string_view<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_istream<Char>&, std::string_view) -> utf8_reader<std::basic_istream<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_istream<Char>&, std::string &&) -> utf8_reader<std::basic_istream<Char>>;
|
||||
|
||||
class TOML_EMPTY_BASES TOML_API utf8_buffered_reader final : public utf8_reader_interface
|
||||
{
|
||||
public:
|
||||
static constexpr size_t max_history_length = 72;
|
||||
|
||||
private:
|
||||
static constexpr size_t history_buffer_size = max_history_length - 1; //'head' is stored in the reader
|
||||
utf8_reader_interface& reader;
|
||||
struct
|
||||
{
|
||||
utf8_codepoint buffer[history_buffer_size];
|
||||
size_t count, first;
|
||||
} history = {};
|
||||
const utf8_codepoint* head = {};
|
||||
size_t negative_offset = {};
|
||||
|
||||
public:
|
||||
explicit utf8_buffered_reader(utf8_reader_interface& reader_) noexcept;
|
||||
const source_path_ptr& source_path() const noexcept override;
|
||||
const utf8_codepoint* read_next() override;
|
||||
const utf8_codepoint* step_back(size_t count) noexcept;
|
||||
bool peek_eof() const override;
|
||||
#if !TOML_EXCEPTIONS
|
||||
optional<parse_error>&& error() noexcept override;
|
||||
#endif
|
||||
};
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#undef TOML_ERROR_CHECK
|
||||
#undef TOML_ERROR
|
||||
|
||||
/// \endcond
|
@ -1,116 +0,0 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
#if !TOML_PARSER
|
||||
#error This header cannot not be included when TOML_PARSER is disabled.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "utf8_streams.h"
|
||||
|
||||
/// \cond
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
#undef TOML_ERROR_CHECK
|
||||
#define TOML_ERROR_CHECK \
|
||||
if (reader.error()) \
|
||||
return nullptr
|
||||
#else
|
||||
#define TOML_ERROR_CHECK (void)0
|
||||
#endif
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex);
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
utf8_buffered_reader::utf8_buffered_reader(utf8_reader_interface & reader_) noexcept : reader{ reader_ }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
const source_path_ptr& utf8_buffered_reader::source_path() const noexcept
|
||||
{
|
||||
return reader.source_path();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
const utf8_codepoint* utf8_buffered_reader::read_next()
|
||||
{
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
if (negative_offset)
|
||||
{
|
||||
negative_offset--;
|
||||
|
||||
// an entry negative offset of 1 just means "replay the current head"
|
||||
if (!negative_offset)
|
||||
return head;
|
||||
|
||||
// otherwise step back into the history buffer
|
||||
else
|
||||
return history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// first character read from stream
|
||||
if TOML_UNLIKELY(!history.count && !head)
|
||||
head = reader.read_next();
|
||||
|
||||
// subsequent characters and not eof
|
||||
else if (head)
|
||||
{
|
||||
if TOML_UNLIKELY(history.count < history_buffer_size)
|
||||
history.buffer[history.count++] = *head;
|
||||
else
|
||||
history.buffer[(history.first++ + history_buffer_size) % history_buffer_size] = *head;
|
||||
|
||||
head = reader.read_next();
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
const utf8_codepoint* utf8_buffered_reader::step_back(size_t count) noexcept
|
||||
{
|
||||
TOML_ERROR_CHECK;
|
||||
TOML_ASSERT(history.count);
|
||||
TOML_ASSERT(negative_offset + count <= history.count);
|
||||
|
||||
negative_offset += count;
|
||||
|
||||
return negative_offset
|
||||
? history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size)
|
||||
: head;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool utf8_buffered_reader::peek_eof() const
|
||||
{
|
||||
return reader.peek_eof();
|
||||
}
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
optional<parse_error>&& utf8_buffered_reader::error() noexcept
|
||||
{
|
||||
return reader.error();
|
||||
}
|
||||
#endif
|
||||
|
||||
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#undef TOML_ERROR_CHECK
|
||||
|
||||
/// \endcond
|
@ -2,15 +2,18 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "date_time.h"
|
||||
#include "node.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "header_start.h"
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
/// \cond
|
||||
// clang-format off
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
#define TOML_SA_VALUE_MESSAGE_WSTRING TOML_SA_LIST_SEP "std::wstring"
|
||||
#else
|
||||
#define TOML_SA_VALUE_MESSAGE_WSTRING
|
||||
@ -69,11 +72,6 @@
|
||||
// clang-format on
|
||||
/// \endcond
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
TOML_DISABLE_INIT_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
|
||||
/// \cond
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
@ -84,7 +82,10 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
static T make(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args&&...>)
|
||||
{
|
||||
return T(static_cast<Args&&>(args)...);
|
||||
if constexpr (std::is_aggregate_v<T>)
|
||||
return T{ static_cast<Args&&>(args)... };
|
||||
else
|
||||
return T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
@ -100,7 +101,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
};
|
||||
|
||||
#if TOML_HAS_CHAR8 || TOML_WINDOWS_COMPAT
|
||||
#if TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
struct string_maker
|
||||
{
|
||||
@ -108,21 +109,29 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
static std::string make(T&& arg) noexcept
|
||||
{
|
||||
#if TOML_HAS_CHAR8
|
||||
if constexpr (is_one_of<std::decay_t<T>, char8_t*, const char8_t*>)
|
||||
using arg_type = std::decay_t<T>;
|
||||
#if TOML_HAS_CHAR8
|
||||
if constexpr (is_one_of<arg_type, char8_t*, const char8_t*>)
|
||||
{
|
||||
return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg)));
|
||||
else if constexpr (is_one_of<remove_cvref_t<T>, std::u8string, std::u8string_view>)
|
||||
}
|
||||
if constexpr (is_one_of<arg_type, std::u8string, std::u8string_view>)
|
||||
{
|
||||
return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg.data())),
|
||||
arg.length());
|
||||
#endif // TOML_HAS_CHAR8
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
if constexpr (is_wide_string<T>)
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
if constexpr (is_wide_string<arg_type>)
|
||||
{
|
||||
return narrow(static_cast<T&&>(arg));
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#if TOML_HAS_CHAR8
|
||||
|
||||
#if TOML_HAS_CHAR8
|
||||
template <>
|
||||
struct native_value_maker<std::string, char8_t*> : string_maker
|
||||
{};
|
||||
@ -135,8 +144,9 @@ TOML_IMPL_NAMESPACE_START
|
||||
template <>
|
||||
struct native_value_maker<std::string, std::u8string_view> : string_maker
|
||||
{};
|
||||
#endif // TOML_HAS_CHAR8
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#endif // TOML_HAS_CHAR8
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
template <>
|
||||
struct native_value_maker<std::string, wchar_t*> : string_maker
|
||||
{};
|
||||
@ -149,13 +159,12 @@ TOML_IMPL_NAMESPACE_START
|
||||
template <>
|
||||
struct native_value_maker<std::string, std::wstring_view> : string_maker
|
||||
{};
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
#endif // TOML_HAS_CHAR8 || TOML_WINDOWS_COMPAT
|
||||
#endif // TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
TOML_ATTR(const)
|
||||
TOML_CONST_GETTER
|
||||
inline optional<T> node_integer_cast(int64_t val) noexcept
|
||||
{
|
||||
static_assert(node_type_of<T> == node_type::integer);
|
||||
@ -200,20 +209,18 @@ TOML_NAMESPACE_START
|
||||
/// - double
|
||||
/// - bool
|
||||
template <typename ValueType>
|
||||
class TOML_API value final : public node
|
||||
class value : public node
|
||||
{
|
||||
static_assert(impl::is_native<ValueType> && !impl::is_cvref<ValueType>,
|
||||
"A toml::value<> must model one of the native TOML value types:" TOML_SA_NATIVE_VALUE_TYPE_LIST);
|
||||
|
||||
private:
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
|
||||
/// \cond
|
||||
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
|
||||
template <typename T, typename U>
|
||||
TOML_NODISCARD
|
||||
TOML_ALWAYS_INLINE
|
||||
TOML_ATTR(const)
|
||||
TOML_CONST_INLINE_GETTER
|
||||
static auto as_value([[maybe_unused]] U* ptr) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, T>)
|
||||
@ -269,6 +276,18 @@ TOML_NAMESPACE_START
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Copy constructor with flags override.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(const value& other, value_flags flags) noexcept //
|
||||
: node(other),
|
||||
val_{ other.val_ },
|
||||
flags_{ flags == preserve_source_value_flags ? other.flags_ : flags }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_VALUE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(value&& other) noexcept //
|
||||
@ -281,6 +300,18 @@ TOML_NAMESPACE_START
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Move constructor with flags override.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(value&& other, value_flags flags) noexcept //
|
||||
: node(std::move(other)),
|
||||
val_{ std::move(other.val_) },
|
||||
flags_{ flags == preserve_source_value_flags ? other.flags_ : flags }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_VALUE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
value& operator=(const value& rhs) noexcept
|
||||
{
|
||||
@ -303,7 +334,7 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
~value() noexcept override
|
||||
~value() noexcept
|
||||
{
|
||||
TOML_VALUE_DESTROYED;
|
||||
}
|
||||
@ -322,86 +353,20 @@ TOML_NAMESPACE_START
|
||||
/// - node_type::date
|
||||
/// - node_type::time
|
||||
/// - node_type::date_time
|
||||
TOML_NODISCARD
|
||||
node_type type() const noexcept override
|
||||
TOML_CONST_INLINE_GETTER
|
||||
node_type type() const noexcept final
|
||||
{
|
||||
return impl::node_type_of<value_type>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_table() const noexcept override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_array() const noexcept override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_value() const noexcept override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_string() const noexcept override
|
||||
{
|
||||
return std::is_same_v<value_type, std::string>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_integer() const noexcept override
|
||||
{
|
||||
return std::is_same_v<value_type, int64_t>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_floating_point() const noexcept override
|
||||
{
|
||||
return std::is_same_v<value_type, double>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_number() const noexcept override
|
||||
{
|
||||
return impl::is_one_of<value_type, int64_t, double>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_boolean() const noexcept override
|
||||
{
|
||||
return std::is_same_v<value_type, bool>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_date() const noexcept override
|
||||
{
|
||||
return std::is_same_v<value_type, date>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_time() const noexcept override
|
||||
{
|
||||
return std::is_same_v<value_type, time>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_date_time() const noexcept override
|
||||
{
|
||||
return std::is_same_v<value_type, date_time>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_homogeneous(node_type ntype) const noexcept override
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous(node_type ntype) const noexcept final
|
||||
{
|
||||
return ntype == node_type::none || ntype == impl::node_type_of<value_type>;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_homogeneous(node_type ntype, toml::node*& first_nonmatch) noexcept override
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final
|
||||
{
|
||||
if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
|
||||
{
|
||||
@ -411,8 +376,8 @@ TOML_NAMESPACE_START
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
bool is_homogeneous(node_type ntype, const toml::node*& first_nonmatch) const noexcept override
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final
|
||||
{
|
||||
if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
|
||||
{
|
||||
@ -422,8 +387,9 @@ TOML_NAMESPACE_START
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \cond
|
||||
template <typename ElemType = void>
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
@ -439,92 +405,219 @@ TOML_NAMESPACE_START
|
||||
else
|
||||
return impl::node_type_of<type> == impl::node_type_of<value_type>;
|
||||
}
|
||||
/// \endcond
|
||||
|
||||
/// \brief Returns `false`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_table() const noexcept final
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns `false`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_array() const noexcept final
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns `false`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_array_of_tables() const noexcept final
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns `true`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_value() const noexcept final
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Returns `true` if the #value_type is std::string.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_string() const noexcept final
|
||||
{
|
||||
return std::is_same_v<value_type, std::string>;
|
||||
}
|
||||
|
||||
/// \brief Returns `true` if the #value_type is int64_t.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_integer() const noexcept final
|
||||
{
|
||||
return std::is_same_v<value_type, int64_t>;
|
||||
}
|
||||
|
||||
/// \brief Returns `true` if the #value_type is `double`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_floating_point() const noexcept final
|
||||
{
|
||||
return std::is_same_v<value_type, double>;
|
||||
}
|
||||
|
||||
/// \brief Returns `true` if the #value_type is int64_t or `double`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_number() const noexcept final
|
||||
{
|
||||
return impl::is_one_of<value_type, int64_t, double>;
|
||||
}
|
||||
|
||||
/// \brief Returns `true` if the #value_type is `bool`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_boolean() const noexcept final
|
||||
{
|
||||
return std::is_same_v<value_type, bool>;
|
||||
}
|
||||
|
||||
/// \brief Returns `true` if the #value_type is toml::date.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_date() const noexcept final
|
||||
{
|
||||
return std::is_same_v<value_type, date>;
|
||||
}
|
||||
|
||||
/// \brief Returns `true` if the #value_type is toml::time.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_time() const noexcept final
|
||||
{
|
||||
return std::is_same_v<value_type, time>;
|
||||
}
|
||||
|
||||
/// \brief Returns `true` if the #value_type is toml_date_time.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
bool is_date_time() const noexcept final
|
||||
{
|
||||
return std::is_same_v<value_type, date_time>;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Type casts
|
||||
/// @{
|
||||
|
||||
TOML_NODISCARD
|
||||
value<std::string>* as_string() noexcept override
|
||||
/// \brief Returns `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
table* as_table() noexcept final
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
array* as_array() noexcept final
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the value if it is a value<std::string>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
value<std::string>* as_string() noexcept final
|
||||
{
|
||||
return as_value<std::string>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
value<int64_t>* as_integer() noexcept override
|
||||
/// \brief Returns a pointer to the value if it is a value<int64_t>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
value<int64_t>* as_integer() noexcept final
|
||||
{
|
||||
return as_value<int64_t>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
value<double>* as_floating_point() noexcept override
|
||||
/// \brief Returns a pointer to the value if it is a value<double>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
value<double>* as_floating_point() noexcept final
|
||||
{
|
||||
return as_value<double>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
value<bool>* as_boolean() noexcept override
|
||||
/// \brief Returns a pointer to the value if it is a value<bool>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
value<bool>* as_boolean() noexcept final
|
||||
{
|
||||
return as_value<bool>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
value<date>* as_date() noexcept override
|
||||
/// \brief Returns a pointer to the value if it is a value<date>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
value<date>* as_date() noexcept final
|
||||
{
|
||||
return as_value<date>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
value<time>* as_time() noexcept override
|
||||
/// \brief Returns a pointer to the value if it is a value<time>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
value<time>* as_time() noexcept final
|
||||
{
|
||||
return as_value<time>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
value<date_time>* as_date_time() noexcept override
|
||||
/// \brief Returns a pointer to the value if it is a value<date_time>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
value<date_time>* as_date_time() noexcept final
|
||||
{
|
||||
return as_value<date_time>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const value<std::string>* as_string() const noexcept override
|
||||
/// \brief Returns `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const table* as_table() const noexcept final
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const array* as_array() const noexcept final
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a const-qualified pointer to the value if it is a value<std::string>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const value<std::string>* as_string() const noexcept final
|
||||
{
|
||||
return as_value<std::string>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const value<int64_t>* as_integer() const noexcept override
|
||||
/// \brief Returns a const-qualified pointer to the value if it is a value<int64_t>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const value<int64_t>* as_integer() const noexcept final
|
||||
{
|
||||
return as_value<int64_t>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const value<double>* as_floating_point() const noexcept override
|
||||
/// \brief Returns a const-qualified pointer to the value if it is a value<double>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const value<double>* as_floating_point() const noexcept final
|
||||
{
|
||||
return as_value<double>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const value<bool>* as_boolean() const noexcept override
|
||||
/// \brief Returns a const-qualified pointer to the value if it is a value<bool>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const value<bool>* as_boolean() const noexcept final
|
||||
{
|
||||
return as_value<bool>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const value<date>* as_date() const noexcept override
|
||||
/// \brief Returns a const-qualified pointer to the value if it is a value<date>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const value<date>* as_date() const noexcept final
|
||||
{
|
||||
return as_value<date>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const value<time>* as_time() const noexcept override
|
||||
/// \brief Returns a const-qualified pointer to the value if it is a value<time>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const value<time>* as_time() const noexcept final
|
||||
{
|
||||
return as_value<time>(this);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
const value<date_time>* as_date_time() const noexcept override
|
||||
/// \brief Returns a const-qualified pointer to the value if it is a value<date_time>, otherwise `nullptr`.
|
||||
TOML_CONST_INLINE_GETTER
|
||||
const value<date_time>* as_date_time() const noexcept final
|
||||
{
|
||||
return as_value<date_time>(this);
|
||||
}
|
||||
@ -535,68 +628,109 @@ TOML_NAMESPACE_START
|
||||
/// @{
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type& get() & noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type&& get() && noexcept
|
||||
{
|
||||
return static_cast<value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type& get() const& noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const rvalue overload).
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type&& get() const&& noexcept
|
||||
{
|
||||
return static_cast<const value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type& operator*() & noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type&& operator*() && noexcept
|
||||
{
|
||||
return static_cast<value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type& operator*() const& noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const rvalue overload).
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type&& operator*() const&& noexcept
|
||||
{
|
||||
return static_cast<const value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator value_type&() & noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (rvalue overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator value_type&&() && noexcept
|
||||
{
|
||||
return static_cast<value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const overload).
|
||||
TOML_NODISCARD
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator const value_type&() const& noexcept
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const rvalue overload).
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator const value_type&&() && noexcept
|
||||
{
|
||||
return static_cast<const value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the underlying value.
|
||||
///
|
||||
/// \availability This operator is only available when #value_type is a class/struct.
|
||||
TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type)
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type* operator->() noexcept
|
||||
{
|
||||
return &val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the underlying value (const overload).
|
||||
///
|
||||
/// \availability This operator is only available when #value_type is a class/struct.
|
||||
TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type)
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type* operator->() const noexcept
|
||||
{
|
||||
return &val_;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Metadata
|
||||
@ -619,11 +753,6 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// @}
|
||||
|
||||
/// \brief Prints the value out to a stream as formatted TOML.
|
||||
template <typename Char, typename T>
|
||||
friend std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, const value<T>& rhs);
|
||||
// implemented in toml_default_formatter.h
|
||||
|
||||
/// \brief Value-assignment operator.
|
||||
value& operator=(value_arg rhs) noexcept
|
||||
{
|
||||
@ -641,7 +770,7 @@ TOML_NAMESPACE_START
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \name Equality
|
||||
/// \name Equality and Comparison
|
||||
/// @{
|
||||
|
||||
/// \brief Value equality operator.
|
||||
@ -650,12 +779,12 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if constexpr (std::is_same_v<value_type, double>)
|
||||
{
|
||||
const auto lhs_class = impl::fpclassify(lhs.val_);
|
||||
const auto rhs_class = impl::fpclassify(rhs);
|
||||
if (lhs_class == impl::fp_class::nan && rhs_class == impl::fp_class::nan)
|
||||
return true;
|
||||
if ((lhs_class == impl::fp_class::nan) != (rhs_class == impl::fp_class::nan))
|
||||
const auto lhs_nan = impl::fpclassify(lhs.val_) == impl::fp_class::nan;
|
||||
const auto rhs_nan = impl::fpclassify(rhs) == impl::fp_class::nan;
|
||||
if (lhs_nan != rhs_nan)
|
||||
return false;
|
||||
if (lhs_nan)
|
||||
return true;
|
||||
}
|
||||
return lhs.val_ == rhs;
|
||||
}
|
||||
@ -823,25 +952,29 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
/// \brief Prints the value out to a stream as formatted TOML.
|
||||
///
|
||||
/// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const value& rhs)
|
||||
{
|
||||
impl::print_to_stream(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
/// \cond
|
||||
template <typename T>
|
||||
value(T) -> value<impl::native_type_of<impl::remove_cvref_t<T>>>;
|
||||
|
||||
#if !TOML_HEADER_ONLY
|
||||
extern template class TOML_API value<std::string>;
|
||||
extern template class TOML_API value<int64_t>;
|
||||
extern template class TOML_API value<double>;
|
||||
extern template class TOML_API value<bool>;
|
||||
extern template class TOML_API value<date>;
|
||||
extern template class TOML_API value<time>;
|
||||
extern template class TOML_API value<date_time>;
|
||||
#endif
|
||||
template <typename T>
|
||||
value(T) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
inline decltype(auto) node::get_value_exact() const noexcept
|
||||
inline decltype(auto) node::get_value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>)
|
||||
{
|
||||
using namespace impl;
|
||||
|
||||
@ -864,7 +997,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
else if constexpr (std::is_same_v<T, std::wstring>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
return widen(str);
|
||||
#else
|
||||
static_assert(dependent_false<T>, "Evaluated unreachable branch!");
|
||||
@ -888,13 +1021,14 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline optional<T> node::value_exact() const noexcept
|
||||
TOML_NODISCARD
|
||||
inline optional<T> node::value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>)
|
||||
{
|
||||
using namespace impl;
|
||||
|
||||
static_assert(!is_wide_string<T> || TOML_WINDOWS_COMPAT,
|
||||
static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
|
||||
"Retrieving values as wide-character strings with node::value_exact() is only "
|
||||
"supported on Windows with TOML_WINDOWS_COMPAT enabled.");
|
||||
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
|
||||
|
||||
static_assert((is_native<T> || can_represent_native<T>)&&!is_cvref<T>,
|
||||
TOML_SA_VALUE_EXACT_FUNC_MESSAGE("return type of node::value_exact()"));
|
||||
@ -910,13 +1044,14 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline optional<T> node::value() const noexcept
|
||||
TOML_NODISCARD
|
||||
inline optional<T> node::value() const noexcept(impl::value_retrieval_is_nothrow<T>)
|
||||
{
|
||||
using namespace impl;
|
||||
|
||||
static_assert(!is_wide_string<T> || TOML_WINDOWS_COMPAT,
|
||||
static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
|
||||
"Retrieving values as wide-character strings with node::value() is only "
|
||||
"supported on Windows with TOML_WINDOWS_COMPAT enabled.");
|
||||
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
|
||||
static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>)&&!is_cvref<T>,
|
||||
TOML_SA_VALUE_FUNC_MESSAGE("return type of node::value()"));
|
||||
|
||||
@ -1026,17 +1161,18 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline auto node::value_or(T && default_value) const noexcept
|
||||
TOML_NODISCARD
|
||||
inline auto node::value_or(T && default_value) const noexcept(impl::value_retrieval_is_nothrow<T>)
|
||||
{
|
||||
using namespace impl;
|
||||
|
||||
static_assert(!is_wide_string<T> || TOML_WINDOWS_COMPAT,
|
||||
static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
|
||||
"Retrieving values as wide-character strings with node::value_or() is only "
|
||||
"supported on Windows with TOML_WINDOWS_COMPAT enabled.");
|
||||
"supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
|
||||
|
||||
if constexpr (is_wide_string<T>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
if (type() == node_type::string)
|
||||
return widen(*ref_cast<std::string>());
|
||||
@ -1056,39 +1192,47 @@ TOML_NAMESPACE_START
|
||||
std::decay_t<T>>;
|
||||
using traits = value_traits<value_type>;
|
||||
|
||||
// clang-format off
|
||||
|
||||
static_assert(
|
||||
traits::is_native || traits::can_represent_native || traits::can_partially_represent_native,
|
||||
"The default value type of node::value_or() must be one of:" TOML_SA_LIST_NEW
|
||||
"A native TOML value type" TOML_SA_NATIVE_VALUE_TYPE_LIST
|
||||
"The default value type of node::value_or() must be one of:"
|
||||
TOML_SA_LIST_NEW "A native TOML value type"
|
||||
TOML_SA_NATIVE_VALUE_TYPE_LIST
|
||||
|
||||
TOML_SA_LIST_NXT
|
||||
"A non-view type capable of losslessly representing a native TOML value type" TOML_SA_LIST_BEG
|
||||
"std::string"
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
TOML_SA_LIST_NXT "A non-view type capable of losslessly representing a native TOML value type"
|
||||
TOML_SA_LIST_BEG "std::string"
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
TOML_SA_LIST_SEP "std::wstring"
|
||||
#endif
|
||||
TOML_SA_LIST_SEP "any signed integer type >= 64 bits" TOML_SA_LIST_SEP
|
||||
"any floating-point type >= 64 bits" TOML_SA_LIST_END
|
||||
#endif
|
||||
TOML_SA_LIST_SEP "any signed integer type >= 64 bits"
|
||||
TOML_SA_LIST_SEP "any floating-point type >= 64 bits"
|
||||
TOML_SA_LIST_END
|
||||
|
||||
TOML_SA_LIST_NXT
|
||||
"A non-view type capable of (reasonably) representing a native TOML value type" TOML_SA_LIST_BEG
|
||||
"any other integer type" TOML_SA_LIST_SEP "any floating-point type >= 32 bits" TOML_SA_LIST_END
|
||||
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type"
|
||||
TOML_SA_LIST_BEG "any other integer type"
|
||||
TOML_SA_LIST_SEP "any floating-point type >= 32 bits"
|
||||
TOML_SA_LIST_END
|
||||
|
||||
TOML_SA_LIST_NXT "A compatible view type" TOML_SA_LIST_BEG "std::string_view"
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_SA_LIST_NXT "A compatible view type"
|
||||
TOML_SA_LIST_BEG "std::string_view"
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_SA_LIST_SEP "std::u8string_view"
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#endif
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
TOML_SA_LIST_SEP "std::wstring_view"
|
||||
#endif
|
||||
#endif
|
||||
TOML_SA_LIST_SEP "const char*"
|
||||
#if TOML_HAS_CHAR8
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_SA_LIST_SEP "const char8_t*"
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
#endif
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
TOML_SA_LIST_SEP "const wchar_t*"
|
||||
#endif
|
||||
TOML_SA_LIST_END);
|
||||
#endif
|
||||
TOML_SA_LIST_END
|
||||
);
|
||||
|
||||
// clang-format on
|
||||
|
||||
// prevent additional compiler error spam when the static_assert fails by gating behind if constexpr
|
||||
if constexpr (traits::is_native || traits::can_represent_native || traits::can_partially_represent_native)
|
||||
@ -1108,57 +1252,14 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
#if !TOML_HEADER_ONLY
|
||||
|
||||
#define TOML_EXTERN(name, T) \
|
||||
extern template TOML_API \
|
||||
optional<T> node::name<T>() const noexcept
|
||||
TOML_EXTERN(value_exact, std::string_view);
|
||||
TOML_EXTERN(value_exact, std::string);
|
||||
TOML_EXTERN(value_exact, const char*);
|
||||
TOML_EXTERN(value_exact, int64_t);
|
||||
TOML_EXTERN(value_exact, double);
|
||||
TOML_EXTERN(value_exact, date);
|
||||
TOML_EXTERN(value_exact, time);
|
||||
TOML_EXTERN(value_exact, date_time);
|
||||
TOML_EXTERN(value_exact, bool);
|
||||
TOML_EXTERN(value, std::string_view);
|
||||
TOML_EXTERN(value, std::string);
|
||||
TOML_EXTERN(value, const char*);
|
||||
TOML_EXTERN(value, signed char);
|
||||
TOML_EXTERN(value, signed short);
|
||||
TOML_EXTERN(value, signed int);
|
||||
TOML_EXTERN(value, signed long);
|
||||
TOML_EXTERN(value, signed long long);
|
||||
TOML_EXTERN(value, unsigned char);
|
||||
TOML_EXTERN(value, unsigned short);
|
||||
TOML_EXTERN(value, unsigned int);
|
||||
TOML_EXTERN(value, unsigned long);
|
||||
TOML_EXTERN(value, unsigned long long);
|
||||
TOML_EXTERN(value, double);
|
||||
TOML_EXTERN(value, float);
|
||||
TOML_EXTERN(value, date);
|
||||
TOML_EXTERN(value, time);
|
||||
TOML_EXTERN(value, date_time);
|
||||
TOML_EXTERN(value, bool);
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_EXTERN(value_exact, std::u8string_view);
|
||||
TOML_EXTERN(value_exact, std::u8string);
|
||||
TOML_EXTERN(value_exact, const char8_t*);
|
||||
TOML_EXTERN(value, std::u8string_view);
|
||||
TOML_EXTERN(value, std::u8string);
|
||||
TOML_EXTERN(value, const char8_t*);
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
TOML_EXTERN(value_exact, std::wstring);
|
||||
TOML_EXTERN(value, std::wstring);
|
||||
#endif
|
||||
#undef TOML_EXTERN
|
||||
|
||||
#endif // !TOML_HEADER_ONLY
|
||||
|
||||
/// \endcond
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_POP_WARNINGS;
|
||||
/// \cond
|
||||
#if TOML_EXTERN_TEMPLATES && !TOML_IMPLEMENTATION
|
||||
#include "value_extern.inl"
|
||||
#endif
|
||||
/// \endcond
|
||||
|
||||
#include "header_end.h"
|
||||
|
21
include/toml++/impl/value.inl
Normal file
21
include/toml++/impl/value.inl
Normal file
@ -0,0 +1,21 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
//# {{
|
||||
#include "preprocessor.h"
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
|
||||
#include "value.h"
|
||||
#include "header_start.h"
|
||||
|
||||
#if TOML_EXTERN_TEMPLATES && TOML_IMPLEMENTATION
|
||||
#include "value_extern.inl"
|
||||
#endif // TOML_EXTERN_TEMPLATES
|
||||
|
||||
#include "header_end.h"
|
76
include/toml++/impl/value_extern.inl
Normal file
76
include/toml++/impl/value_extern.inl
Normal file
@ -0,0 +1,76 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
/// \cond
|
||||
|
||||
#include "value.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERN
|
||||
template class TOML_API value<std::string>;
|
||||
TOML_EXTERN
|
||||
template class TOML_API value<int64_t>;
|
||||
TOML_EXTERN
|
||||
template class TOML_API value<double>;
|
||||
TOML_EXTERN
|
||||
template class TOML_API value<bool>;
|
||||
TOML_EXTERN
|
||||
template class TOML_API value<date>;
|
||||
TOML_EXTERN
|
||||
template class TOML_API value<time>;
|
||||
TOML_EXTERN
|
||||
template class TOML_API value<date_time>;
|
||||
|
||||
#define TOML_EXTERN_FUNC(name, T) \
|
||||
TOML_EXTERN \
|
||||
template TOML_API \
|
||||
optional<T> node::name<T>() const TOML_EXTERN_NOEXCEPT(impl::value_retrieval_is_nothrow<T>)
|
||||
|
||||
TOML_EXTERN_FUNC(value_exact, std::string_view);
|
||||
TOML_EXTERN_FUNC(value_exact, std::string);
|
||||
TOML_EXTERN_FUNC(value_exact, const char*);
|
||||
TOML_EXTERN_FUNC(value_exact, int64_t);
|
||||
TOML_EXTERN_FUNC(value_exact, double);
|
||||
TOML_EXTERN_FUNC(value_exact, date);
|
||||
TOML_EXTERN_FUNC(value_exact, time);
|
||||
TOML_EXTERN_FUNC(value_exact, date_time);
|
||||
TOML_EXTERN_FUNC(value_exact, bool);
|
||||
TOML_EXTERN_FUNC(value, std::string_view);
|
||||
TOML_EXTERN_FUNC(value, std::string);
|
||||
TOML_EXTERN_FUNC(value, const char*);
|
||||
TOML_EXTERN_FUNC(value, signed char);
|
||||
TOML_EXTERN_FUNC(value, signed short);
|
||||
TOML_EXTERN_FUNC(value, signed int);
|
||||
TOML_EXTERN_FUNC(value, signed long);
|
||||
TOML_EXTERN_FUNC(value, signed long long);
|
||||
TOML_EXTERN_FUNC(value, unsigned char);
|
||||
TOML_EXTERN_FUNC(value, unsigned short);
|
||||
TOML_EXTERN_FUNC(value, unsigned int);
|
||||
TOML_EXTERN_FUNC(value, unsigned long);
|
||||
TOML_EXTERN_FUNC(value, unsigned long long);
|
||||
TOML_EXTERN_FUNC(value, double);
|
||||
TOML_EXTERN_FUNC(value, float);
|
||||
TOML_EXTERN_FUNC(value, date);
|
||||
TOML_EXTERN_FUNC(value, time);
|
||||
TOML_EXTERN_FUNC(value, date_time);
|
||||
TOML_EXTERN_FUNC(value, bool);
|
||||
#if TOML_HAS_CHAR8
|
||||
TOML_EXTERN_FUNC(value_exact, std::u8string_view);
|
||||
TOML_EXTERN_FUNC(value_exact, std::u8string);
|
||||
TOML_EXTERN_FUNC(value_exact, const char8_t*);
|
||||
TOML_EXTERN_FUNC(value, std::u8string_view);
|
||||
TOML_EXTERN_FUNC(value, std::u8string);
|
||||
TOML_EXTERN_FUNC(value, const char8_t*);
|
||||
#endif
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
TOML_EXTERN_FUNC(value_exact, std::wstring);
|
||||
TOML_EXTERN_FUNC(value, std::wstring);
|
||||
#endif
|
||||
|
||||
#undef TOML_EXTERN_FUNC
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
/// \endcond
|
@ -2,11 +2,10 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#define TOML_LIB_MAJOR 2
|
||||
#define TOML_LIB_MINOR 6
|
||||
#define TOML_LIB_MAJOR 3
|
||||
#define TOML_LIB_MINOR 0
|
||||
#define TOML_LIB_PATCH 0
|
||||
|
||||
#define TOML_LANG_MAJOR 1
|
||||
|
139
include/toml++/impl/yaml_formatter.h
Normal file
139
include/toml++/impl/yaml_formatter.h
Normal file
@ -0,0 +1,139 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "formatter.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted YAML.
|
||||
///
|
||||
/// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto some_toml = toml::parse(R"(
|
||||
/// [fruit]
|
||||
/// apple.color = "red"
|
||||
/// apple.taste.sweet = true
|
||||
///
|
||||
/// [fruit.apple.texture]
|
||||
/// smooth = true
|
||||
/// )"sv);
|
||||
/// std::cout << toml::yaml_formatter{ some_toml } << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// fruit:
|
||||
/// apple:
|
||||
/// color: red
|
||||
/// taste:
|
||||
/// sweet: true
|
||||
/// texture:
|
||||
/// smooth: true
|
||||
/// \eout
|
||||
class yaml_formatter : impl::formatter
|
||||
{
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
using base = impl::formatter;
|
||||
|
||||
TOML_API
|
||||
void print_yaml_string(const value<std::string>&);
|
||||
|
||||
TOML_API
|
||||
void print(const toml::table&, bool = false);
|
||||
|
||||
TOML_API
|
||||
void print(const toml::array&, bool = false);
|
||||
|
||||
TOML_API
|
||||
void print();
|
||||
|
||||
static constexpr impl::formatter_constants constants = {
|
||||
//
|
||||
format_flags::quote_dates_and_times | format_flags::indentation, // mandatory
|
||||
format_flags::allow_multi_line_strings, // ignored
|
||||
".inf"sv,
|
||||
"-.inf"sv,
|
||||
".NAN"sv,
|
||||
"true"sv,
|
||||
"false"sv
|
||||
};
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
/// \brief The default flags for a yaml_formatter.
|
||||
static constexpr format_flags default_flags = constants.mandatory_flags //
|
||||
| format_flags::allow_literal_strings //
|
||||
| format_flags::allow_unicode_strings //
|
||||
| format_flags::allow_octal_integers //
|
||||
| format_flags::allow_hexadecimal_integers;
|
||||
|
||||
/// \brief Constructs a YAML formatter and binds it to a TOML object.
|
||||
///
|
||||
/// \param source The source TOML object.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit yaml_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
|
||||
: base{ &source, nullptr, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#if defined(DOXYGEN) || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS)
|
||||
|
||||
/// \brief Constructs a YAML formatter and binds it to a toml::parse_result.
|
||||
///
|
||||
/// \availability This constructor is only available when exceptions are disabled.
|
||||
///
|
||||
/// \attention Formatting a failed parse result will simply dump the error message out as-is.
|
||||
/// This will not be valid YAML, but at least gives you something to log or show up in diagnostics:
|
||||
/// \cpp
|
||||
/// std::cout << toml::yaml_formatter{ toml::parse("a = 'b'"sv) } // ok
|
||||
/// << "\n\n"
|
||||
/// << toml::yaml_formatter{ toml::parse("a = "sv) } // malformed
|
||||
/// << "\n";
|
||||
/// \ecpp
|
||||
/// \out
|
||||
/// a: b
|
||||
///
|
||||
/// Error while parsing key-value pair: encountered end-of-file
|
||||
/// (error occurred at line 1, column 5)
|
||||
/// \eout
|
||||
/// Use the library with exceptions if you want to avoid this scenario.
|
||||
///
|
||||
/// \param result The parse result.
|
||||
/// \param flags Format option flags.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit yaml_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
|
||||
: base{ nullptr, &result, constants, { flags, " "sv } }
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as YAML.
|
||||
friend std::ostream& operator<<(std::ostream& lhs, yaml_formatter& rhs)
|
||||
{
|
||||
rhs.attach(lhs);
|
||||
rhs.print();
|
||||
rhs.detach();
|
||||
return lhs;
|
||||
}
|
||||
|
||||
/// \brief Prints the bound TOML object out to the stream as YAML (rvalue overload).
|
||||
friend std::ostream& operator<<(std::ostream& lhs, yaml_formatter&& rhs)
|
||||
{
|
||||
return lhs << rhs; // as lvalue
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
162
include/toml++/impl/yaml_formatter.inl
Normal file
162
include/toml++/impl/yaml_formatter.inl
Normal file
@ -0,0 +1,162 @@
|
||||
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "preprocessor.h"
|
||||
//# {{
|
||||
#if !TOML_IMPLEMENTATION
|
||||
#error This is an implementation-only header.
|
||||
#endif
|
||||
//# }}
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
|
||||
#include "yaml_formatter.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "table.h"
|
||||
#include "array.h"
|
||||
#include "header_start.h"
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void yaml_formatter::print_yaml_string(const value<std::string>& str)
|
||||
{
|
||||
if (str->empty())
|
||||
{
|
||||
base::print(str);
|
||||
return;
|
||||
}
|
||||
|
||||
bool contains_newline = false;
|
||||
for (auto c = str->c_str(), e = str->c_str() + str->length(); c < e && !contains_newline; c++)
|
||||
contains_newline = *c == '\n';
|
||||
|
||||
if (contains_newline)
|
||||
{
|
||||
print_unformatted("|-"sv);
|
||||
|
||||
increase_indent();
|
||||
|
||||
auto line_end = str->c_str() - 1u;
|
||||
const auto end = str->c_str() + str->length();
|
||||
while (line_end != end)
|
||||
{
|
||||
auto line_start = line_end + 1u;
|
||||
line_end = line_start;
|
||||
for (; line_end != end && *line_end != '\n'; line_end++)
|
||||
;
|
||||
|
||||
if TOML_LIKELY(line_start != line_end || line_end != end)
|
||||
{
|
||||
print_newline();
|
||||
print_indent();
|
||||
print_unformatted(std::string_view{ line_start, static_cast<size_t>(line_end - line_start) });
|
||||
}
|
||||
}
|
||||
|
||||
decrease_indent();
|
||||
}
|
||||
else
|
||||
print_string(*str, false, true);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void yaml_formatter::print(const toml::table& tbl, bool parent_is_array)
|
||||
{
|
||||
if (tbl.empty())
|
||||
{
|
||||
print_unformatted("{}"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
increase_indent();
|
||||
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
if (!parent_is_array)
|
||||
{
|
||||
print_newline();
|
||||
print_indent();
|
||||
}
|
||||
parent_is_array = false;
|
||||
|
||||
print_string(k.str(), false, true);
|
||||
print_unformatted(": "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v)); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v)); break;
|
||||
case node_type::string: print_yaml_string(*reinterpret_cast<const value<std::string>*>(&v)); break;
|
||||
default: print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
decrease_indent();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void yaml_formatter::print(const toml::array& arr, bool parent_is_array)
|
||||
{
|
||||
if (arr.empty())
|
||||
{
|
||||
print_unformatted("[]"sv);
|
||||
return;
|
||||
}
|
||||
|
||||
increase_indent();
|
||||
|
||||
for (auto&& v : arr)
|
||||
{
|
||||
if (!parent_is_array)
|
||||
{
|
||||
print_newline();
|
||||
print_indent();
|
||||
}
|
||||
parent_is_array = false;
|
||||
|
||||
print_unformatted("- "sv);
|
||||
|
||||
const auto type = v.type();
|
||||
TOML_ASSUME(type != node_type::none);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: print(*reinterpret_cast<const table*>(&v), true); break;
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&v), true); break;
|
||||
case node_type::string: print_yaml_string(*reinterpret_cast<const value<std::string>*>(&v)); break;
|
||||
default: print_value(v, type);
|
||||
}
|
||||
}
|
||||
|
||||
decrease_indent();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void yaml_formatter::print()
|
||||
{
|
||||
if (dump_failed_parse_result())
|
||||
return;
|
||||
|
||||
switch (auto source_type = source().type())
|
||||
{
|
||||
case node_type::table:
|
||||
decrease_indent(); // so root kvps and tables have the same indent
|
||||
print(*reinterpret_cast<const table*>(&source()));
|
||||
break;
|
||||
|
||||
case node_type::array: print(*reinterpret_cast<const array*>(&source())); break;
|
||||
|
||||
case node_type::string: print_yaml_string(*reinterpret_cast<const value<std::string>*>(&source())); break;
|
||||
|
||||
default: print_value(source(), source_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
#include "header_end.h"
|
||||
#endif // TOML_ENABLE_FORMATTERS
|
@ -2,153 +2,188 @@
|
||||
//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#ifndef TOMLPLUSPLUS_H
|
||||
#define TOMLPLUSPLUS_H
|
||||
|
||||
#ifndef INCLUDE_TOMLPLUSPLUS_H
|
||||
#define INCLUDE_TOMLPLUSPLUS_H
|
||||
#define INCLUDE_TOMLPLUSPLUS_H // old guard name used pre-v3
|
||||
|
||||
//# Note: most of these would be included transitively but
|
||||
//# they're listed explicitly here because this file
|
||||
//# is used as the source for generate_single_header.py.
|
||||
//# Note: these would be included transitively as with any normal C++ project but
|
||||
//# they're listed explicitly here because this file is used as the source for generate_single_header.py.
|
||||
|
||||
#include "impl/preprocessor.h"
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SPAM_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
TOML_DISABLE_SUGGEST_ATTR_WARNINGS;
|
||||
|
||||
#include "impl/common.h"
|
||||
#include "impl/date_time.h"
|
||||
// misc warning false-positives
|
||||
#if TOML_MSVC
|
||||
#pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch
|
||||
#elif TOML_CLANG
|
||||
#pragma clang diagnostic ignored "-Wheader-hygiene"
|
||||
#if TOML_CLANG >= 12
|
||||
#pragma clang diagnostic ignored "-Wc++20-extensions"
|
||||
#endif
|
||||
#if TOML_CLANG == 13
|
||||
#pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "impl/std_new.h"
|
||||
#include "impl/std_string.h"
|
||||
#include "impl/std_optional.h"
|
||||
#include "impl/forward_declarations.h"
|
||||
#include "impl/print_to_stream.h"
|
||||
#include "impl/source_region.h"
|
||||
#include "impl/date_time.h"
|
||||
#include "impl/at_path.h"
|
||||
#include "impl/node.h"
|
||||
#include "impl/value.h"
|
||||
#include "impl/array.h"
|
||||
#include "impl/table.h"
|
||||
#include "impl/node_view.h"
|
||||
#include "impl/utf8.h"
|
||||
#if TOML_PARSER
|
||||
#include "impl/parse_error.h"
|
||||
#include "impl/parse_result.h"
|
||||
#include "impl/utf8_streams.h"
|
||||
#include "impl/parser.h"
|
||||
#endif // TOML_PARSER
|
||||
#include "impl/value.h"
|
||||
#include "impl/make_node.h"
|
||||
#include "impl/array.h"
|
||||
#include "impl/key.h"
|
||||
#include "impl/table.h"
|
||||
#include "impl/unicode.h"
|
||||
#include "impl/parse_error.h"
|
||||
#include "impl/parse_result.h"
|
||||
#include "impl/parser.h"
|
||||
#include "impl/formatter.h"
|
||||
#include "impl/default_formatter.h"
|
||||
#include "impl/toml_formatter.h"
|
||||
#include "impl/json_formatter.h"
|
||||
#include "impl/yaml_formatter.h"
|
||||
|
||||
#if TOML_IMPLEMENTATION
|
||||
#include "impl/node_impl.h"
|
||||
#include "impl/array_impl.h"
|
||||
#include "impl/table_impl.h"
|
||||
#if TOML_PARSER
|
||||
#include "impl/utf8_streams_impl.h"
|
||||
#include "impl/parser_impl.h"
|
||||
#endif // TOML_PARSER
|
||||
#include "impl/default_formatter_impl.h"
|
||||
#include "impl/json_formatter_impl.h"
|
||||
#if !TOML_HEADER_ONLY
|
||||
#include "impl/template_instantiations.h"
|
||||
#endif // !TOML_HEADER_ONLY
|
||||
#endif // TOML_IMPLEMENTATION
|
||||
|
||||
TOML_POP_WARNINGS; // TOML_DISABLE_SPAM_WARNINGS
|
||||
#include "impl/std_string.inl"
|
||||
#include "impl/print_to_stream.inl"
|
||||
#include "impl/node.inl"
|
||||
#include "impl/node_view.inl"
|
||||
#include "impl/at_path.inl"
|
||||
#include "impl/value.inl"
|
||||
#include "impl/array.inl"
|
||||
#include "impl/table.inl"
|
||||
#include "impl/unicode.inl"
|
||||
#include "impl/parser.inl"
|
||||
#include "impl/formatter.inl"
|
||||
#include "impl/toml_formatter.inl"
|
||||
#include "impl/json_formatter.inl"
|
||||
#include "impl/yaml_formatter.inl"
|
||||
|
||||
#endif // TOML_IMPLEMENTATION
|
||||
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
// macro hygiene
|
||||
#if TOML_UNDEF_MACROS
|
||||
#undef TOML_ABI_NAMESPACE_BOOL
|
||||
#undef TOML_ABI_NAMESPACE_END
|
||||
#undef TOML_ABI_NAMESPACE_START
|
||||
#undef TOML_ABI_NAMESPACES
|
||||
#undef TOML_ABSTRACT_BASE
|
||||
#undef TOML_ALWAYS_INLINE
|
||||
#undef TOML_ANON_NAMESPACE
|
||||
#undef TOML_ANON_NAMESPACE_END
|
||||
#undef TOML_ANON_NAMESPACE_START
|
||||
#undef TOML_ARM
|
||||
#undef TOML_ASSERT
|
||||
#undef TOML_ASSUME
|
||||
#undef TOML_ASYMMETRICAL_EQUALITY_OPS
|
||||
#undef TOML_ATTR
|
||||
#undef TOML_CLANG
|
||||
#undef TOML_COMPILER_EXCEPTIONS
|
||||
#undef TOML_CONCAT
|
||||
#undef TOML_CONCAT_1
|
||||
#undef TOML_CONSTEVAL
|
||||
#undef TOML_CONSTRAINED_TEMPLATE
|
||||
#undef TOML_CPP
|
||||
#undef TOML_DISABLE_ARITHMETIC_WARNINGS
|
||||
#undef TOML_DISABLE_CODE_ANALYSIS_WARNINGS
|
||||
#undef TOML_DISABLE_INIT_WARNINGS
|
||||
#undef TOML_DISABLE_SHADOW_WARNINGS
|
||||
#undef TOML_DISABLE_SPAM_WARNINGS
|
||||
#undef TOML_DISABLE_SUGGEST_WARNINGS
|
||||
#undef TOML_DISABLE_SWITCH_WARNINGS
|
||||
#undef TOML_DISABLE_WARNINGS
|
||||
#undef TOML_EMPTY_BASES
|
||||
#undef TOML_ENABLE_IF
|
||||
#undef TOML_ENABLE_WARNINGS
|
||||
#undef TOML_EVAL_BOOL_0
|
||||
#undef TOML_EVAL_BOOL_1
|
||||
#undef TOML_EXTERNAL_LINKAGE
|
||||
#undef TOML_FLOAT_CHARCONV
|
||||
#undef TOML_FLOAT128
|
||||
#undef TOML_FLOAT16
|
||||
#undef TOML_FP16
|
||||
#undef TOML_GCC
|
||||
#undef TOML_HAS_ATTR
|
||||
#undef TOML_HAS_CHAR8
|
||||
#undef TOML_HAS_CUSTOM_OPTIONAL_TYPE
|
||||
#undef TOML_HAS_INCLUDE
|
||||
#undef TOML_ICC
|
||||
#undef TOML_ICC_CL
|
||||
#undef TOML_IMPL_NAMESPACE_END
|
||||
#undef TOML_IMPL_NAMESPACE_START
|
||||
#undef TOML_IMPLEMENTATION
|
||||
#undef TOML_INCLUDE_WINDOWS_H
|
||||
#undef TOML_INT_CHARCONV
|
||||
#undef TOML_INT128
|
||||
#undef TOML_INTELLISENSE
|
||||
#undef TOML_INTERNAL_LINKAGE
|
||||
#undef TOML_LANG_AT_LEAST
|
||||
#undef TOML_LANG_EFFECTIVE_VERSION
|
||||
#undef TOML_LANG_HIGHER_THAN
|
||||
#undef TOML_LANG_UNRELEASED
|
||||
#undef TOML_LAUNDER
|
||||
#undef TOML_LIFETIME_HOOKS
|
||||
#undef TOML_LIKELY
|
||||
#undef TOML_MAKE_FLAGS
|
||||
#undef TOML_MAKE_FLAGS_
|
||||
#undef TOML_MAKE_VERSION
|
||||
#undef TOML_MAY_THROW
|
||||
#undef TOML_MSVC
|
||||
#undef TOML_NAMESPACE
|
||||
#undef TOML_NAMESPACE_END
|
||||
#undef TOML_NAMESPACE_START
|
||||
#undef TOML_NEVER_INLINE
|
||||
#undef TOML_NODISCARD
|
||||
#undef TOML_NODISCARD_CTOR
|
||||
#undef TOML_PARSER_TYPENAME
|
||||
#undef TOML_POP_WARNINGS
|
||||
#undef TOML_PUSH_WARNINGS
|
||||
#undef TOML_REQUIRES
|
||||
#undef TOML_SA_LIST_BEG
|
||||
#undef TOML_SA_LIST_END
|
||||
#undef TOML_SA_LIST_NEW
|
||||
#undef TOML_SA_LIST_NXT
|
||||
#undef TOML_SA_LIST_SEP
|
||||
#undef TOML_SA_NATIVE_VALUE_TYPE_LIST
|
||||
#undef TOML_SA_NEWLINE
|
||||
#undef TOML_SA_NODE_TYPE_LIST
|
||||
#undef TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
#undef TOML_SA_VALUE_EXACT_FUNC_MESSAGE
|
||||
#undef TOML_SA_VALUE_FUNC_MESSAGE
|
||||
#undef TOML_SA_VALUE_MESSAGE_CONST_CHAR8
|
||||
#undef TOML_SA_VALUE_MESSAGE_U8STRING_VIEW
|
||||
#undef TOML_SA_VALUE_MESSAGE_WSTRING
|
||||
#undef TOML_SIMPLE_STATIC_ASSERT_MESSAGES
|
||||
#undef TOML_TRIVIAL_ABI
|
||||
#undef TOML_UINT128
|
||||
#undef TOML_UNLIKELY
|
||||
#undef TOML_UNREACHABLE
|
||||
#undef TOML_USING_ANON_NAMESPACE
|
||||
#undef TOML_ABI_NAMESPACE_BOOL
|
||||
#undef TOML_ABI_NAMESPACE_END
|
||||
#undef TOML_ABI_NAMESPACE_START
|
||||
#undef TOML_ABI_NAMESPACES
|
||||
#undef TOML_ABSTRACT_BASE
|
||||
#undef TOML_ALWAYS_INLINE
|
||||
#undef TOML_ANON_NAMESPACE
|
||||
#undef TOML_ANON_NAMESPACE_END
|
||||
#undef TOML_ANON_NAMESPACE_START
|
||||
#undef TOML_ARM
|
||||
#undef TOML_ASSERT
|
||||
#undef TOML_ASSERT_ASSUME
|
||||
#undef TOML_ASSUME
|
||||
#undef TOML_ASYMMETRICAL_EQUALITY_OPS
|
||||
#undef TOML_ATTR
|
||||
#undef TOML_CLANG
|
||||
#undef TOML_CLOSED_ENUM
|
||||
#undef TOML_CLOSED_FLAGS_ENUM
|
||||
#undef TOML_COMPILER_EXCEPTIONS
|
||||
#undef TOML_CONST_GETTER
|
||||
#undef TOML_CONST_INLINE_GETTER
|
||||
#undef TOML_CONSTRAINED_TEMPLATE
|
||||
#undef TOML_CPP_VERSION
|
||||
#undef TOML_DELETE_DEFAULTS
|
||||
#undef TOML_DISABLE_ARITHMETIC_WARNINGS
|
||||
#undef TOML_DISABLE_CODE_ANALYSIS_WARNINGS
|
||||
#undef TOML_DISABLE_SPAM_WARNINGS
|
||||
#undef TOML_DISABLE_SPAM_WARNINGS_CLANG_10
|
||||
#undef TOML_DISABLE_SUGGEST_ATTR_WARNINGS
|
||||
#undef TOML_DISABLE_SWITCH_WARNINGS
|
||||
#undef TOML_DISABLE_WARNINGS
|
||||
#undef TOML_EMPTY_BASES
|
||||
#undef TOML_ENABLE_IF
|
||||
#undef TOML_ENABLE_WARNINGS
|
||||
#undef TOML_EVAL_BOOL_0
|
||||
#undef TOML_EVAL_BOOL_1
|
||||
#undef TOML_EXTERN
|
||||
#undef TOML_EXTERN_NOEXCEPT
|
||||
#undef TOML_EXTERNAL_LINKAGE
|
||||
#undef TOML_FLAGS_ENUM
|
||||
#undef TOML_FLOAT_CHARCONV
|
||||
#undef TOML_FLOAT128
|
||||
#undef TOML_FLOAT16
|
||||
#undef TOML_FP16
|
||||
#undef TOML_GCC
|
||||
#undef TOML_HAS_ATTR
|
||||
#undef TOML_HAS_CHAR8
|
||||
#undef TOML_HAS_CUSTOM_OPTIONAL_TYPE
|
||||
#undef TOML_HAS_INCLUDE
|
||||
#undef TOML_HAS_SSE2
|
||||
#undef TOML_HAS_SSE4_1
|
||||
#undef TOML_HIDDEN_CONSTRAINT
|
||||
#undef TOML_ICC
|
||||
#undef TOML_ICC_CL
|
||||
#undef TOML_IMPL_NAMESPACE_END
|
||||
#undef TOML_IMPL_NAMESPACE_START
|
||||
#undef TOML_IMPLEMENTATION
|
||||
#undef TOML_INCLUDE_WINDOWS_H
|
||||
#undef TOML_INT_CHARCONV
|
||||
#undef TOML_INT128
|
||||
#undef TOML_INTELLISENSE
|
||||
#undef TOML_INTERNAL_LINKAGE
|
||||
#undef TOML_LANG_AT_LEAST
|
||||
#undef TOML_LANG_EFFECTIVE_VERSION
|
||||
#undef TOML_LANG_HIGHER_THAN
|
||||
#undef TOML_LANG_UNRELEASED
|
||||
#undef TOML_LAUNDER
|
||||
#undef TOML_LIFETIME_HOOKS
|
||||
#undef TOML_LIKELY
|
||||
#undef TOML_LIKELY_CASE
|
||||
#undef TOML_MAKE_FLAGS
|
||||
#undef TOML_MAKE_FLAGS_
|
||||
#undef TOML_MAKE_VERSION
|
||||
#undef TOML_MSVC
|
||||
#undef TOML_NAMESPACE
|
||||
#undef TOML_NEVER_INLINE
|
||||
#undef TOML_NODISCARD
|
||||
#undef TOML_NODISCARD_CTOR
|
||||
#undef TOML_OPEN_ENUM
|
||||
#undef TOML_OPEN_FLAGS_ENUM
|
||||
#undef TOML_PARSER_TYPENAME
|
||||
#undef TOML_POP_WARNINGS
|
||||
#undef TOML_PURE_GETTER
|
||||
#undef TOML_PURE_INLINE_GETTER
|
||||
#undef TOML_PUSH_WARNINGS
|
||||
#undef TOML_REQUIRES
|
||||
#undef TOML_SA_LIST_BEG
|
||||
#undef TOML_SA_LIST_END
|
||||
#undef TOML_SA_LIST_NEW
|
||||
#undef TOML_SA_LIST_NXT
|
||||
#undef TOML_SA_LIST_SEP
|
||||
#undef TOML_SA_NATIVE_VALUE_TYPE_LIST
|
||||
#undef TOML_SA_NEWLINE
|
||||
#undef TOML_SA_NODE_TYPE_LIST
|
||||
#undef TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
#undef TOML_SA_VALUE_EXACT_FUNC_MESSAGE
|
||||
#undef TOML_SA_VALUE_FUNC_MESSAGE
|
||||
#undef TOML_SA_VALUE_MESSAGE_CONST_CHAR8
|
||||
#undef TOML_SA_VALUE_MESSAGE_U8STRING_VIEW
|
||||
#undef TOML_SA_VALUE_MESSAGE_WSTRING
|
||||
#undef TOML_SIMPLE_STATIC_ASSERT_MESSAGES
|
||||
#undef TOML_TRIVIAL_ABI
|
||||
#undef TOML_UINT128
|
||||
#undef TOML_UNLIKELY
|
||||
#undef TOML_UNLIKELY_CASE
|
||||
#undef TOML_UNREACHABLE
|
||||
#undef TOML_UNUSED
|
||||
#endif
|
||||
|
||||
#endif // INCLUDE_TOMLPLUSPLUS_H
|
||||
#endif // TOMLPLUSPLUS_H
|
||||
|
33
meson.build
33
meson.build
@ -1,8 +1,8 @@
|
||||
project(
|
||||
'tomlplusplus',
|
||||
'cpp',
|
||||
version: '2.6.0',
|
||||
meson_version: '>=0.53.0',
|
||||
version: '3.0.0',
|
||||
meson_version: '>=0.54.0',
|
||||
license: 'MIT',
|
||||
default_options: [ # https://mesonbuild.com/Builtin-options.html
|
||||
# core options
|
||||
@ -122,14 +122,14 @@ if is_gcc
|
||||
'-Wvariadic-macros',
|
||||
'-Wwrite-strings',
|
||||
'-Wmissing-noreturn',
|
||||
'-Wsuggest-attribute=const',
|
||||
'-Wsuggest-attribute=pure',
|
||||
language: 'cpp'
|
||||
)
|
||||
endif
|
||||
if is_release
|
||||
add_project_arguments(
|
||||
'-fmerge-constants',
|
||||
'-Wsuggest-attribute=const',
|
||||
'-Wsuggest-attribute=pure',
|
||||
language: 'cpp'
|
||||
)
|
||||
endif
|
||||
@ -156,12 +156,6 @@ if is_clang
|
||||
if get_option('time_trace')
|
||||
add_project_arguments('-ftime-trace', language: 'cpp')
|
||||
endif
|
||||
if is_release
|
||||
add_project_arguments(
|
||||
'-fmerge-all-constants',
|
||||
language: 'cpp'
|
||||
)
|
||||
endif
|
||||
endif
|
||||
|
||||
# MSVC or icc-cl
|
||||
@ -265,6 +259,16 @@ compiler_supports_cpp20 = compiler_supports_cpp20_args.length() > 0 and compiler
|
||||
#include <version>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <cfloat>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <iosfwd>
|
||||
#include <type_traits>
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -492,6 +496,11 @@ if build_examples
|
||||
subdir('examples')
|
||||
endif
|
||||
|
||||
build_tt = (get_option('build_tt_encoder') or get_option('build_tt_encoder')) and not is_subproject
|
||||
if build_tt
|
||||
subdir('toml-test')
|
||||
endif
|
||||
|
||||
if not is_subproject
|
||||
install_subdir('include'/'toml++',
|
||||
strip_directory: true,
|
||||
@ -508,9 +517,7 @@ tomlplusplus_dep = declare_dependency(
|
||||
version: meson.project_version(),
|
||||
)
|
||||
|
||||
if meson.version().version_compare('>=0.54.0')
|
||||
meson.override_dependency('tomlplusplus', tomlplusplus_dep)
|
||||
endif
|
||||
meson.override_dependency('tomlplusplus', tomlplusplus_dep)
|
||||
|
||||
if not is_subproject
|
||||
import('pkgconfig').generate(
|
||||
|
@ -3,3 +3,8 @@ option('build_examples', type: 'boolean', value: false, description: 'Build exa
|
||||
option('generate_cmake_config', type: 'boolean', value: true, description: 'Generate a cmake package config file (default: true - no effect when included as a subproject)')
|
||||
option('pedantic', type: 'boolean', value: false, description: 'Enable as many compiler warnings as possible (default: false)')
|
||||
option('time_trace', type: 'boolean', value: false, description: 'Enable the -ftime-trace option (Clang only)')
|
||||
option('asan_examples', type: 'boolean', value: false)
|
||||
option('asan_tests', type: 'boolean', value: false)
|
||||
option('build_tt_encoder', type: 'boolean', value: false, description: 'Enable to build the toml-test encoder.')
|
||||
option('build_tt_decoder', type: 'boolean', value: false, description: 'Enable to build the toml-test decoder.')
|
||||
|
||||
|
115
tests/at_path.cpp
Normal file
115
tests/at_path.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
// This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "tests.h"
|
||||
TOML_DISABLE_SPAM_WARNINGS;
|
||||
|
||||
TEST_CASE("at_path")
|
||||
{
|
||||
// clang-format off
|
||||
|
||||
const auto tbl = table
|
||||
{
|
||||
{ ""sv, 0 }, // blank key
|
||||
{ "a"sv, 1 },
|
||||
{
|
||||
"b"sv,
|
||||
array
|
||||
{
|
||||
2,
|
||||
array{ 3 },
|
||||
table { { "c", 4 } }
|
||||
},
|
||||
},
|
||||
{ "d", table{ {"e", 5, }, {""sv, -1 } } }
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
/*
|
||||
|
||||
# equivalent to the following TOML:
|
||||
|
||||
"" = 0
|
||||
a = 1
|
||||
b = [
|
||||
2,
|
||||
[ 3 ],
|
||||
{ "c" = 4 }
|
||||
]
|
||||
d = { "e" = 5, "" = -1 }
|
||||
|
||||
*/
|
||||
|
||||
SECTION("table")
|
||||
{
|
||||
// this section uses the free function version of at_path
|
||||
|
||||
CHECK(tbl[""]);
|
||||
CHECK(tbl[""] == at_path(tbl, ""));
|
||||
|
||||
CHECK(tbl["a"]);
|
||||
CHECK(tbl["a"] == at_path(tbl, "a"));
|
||||
CHECK(tbl["a"] != at_path(tbl, ".a")); // equivalent to ""."a"
|
||||
CHECK(!at_path(tbl, ".a"));
|
||||
|
||||
CHECK(tbl["b"]);
|
||||
CHECK(tbl["b"] == at_path(tbl, "b"));
|
||||
|
||||
CHECK(tbl["b"][0]);
|
||||
CHECK(tbl["b"][0] == at_path(tbl, "b[0]"));
|
||||
CHECK(tbl["b"][0] == at_path(tbl, "b[0] "));
|
||||
CHECK(tbl["b"][0] == at_path(tbl, "b[ 0\t]")); // whitespace is allowed inside array indexer
|
||||
|
||||
CHECK(tbl["b"][1]);
|
||||
CHECK(tbl["b"][1] != tbl["b"][0]);
|
||||
CHECK(tbl["b"][1] == at_path(tbl, "b[1]"));
|
||||
|
||||
CHECK(tbl["b"][1][0]);
|
||||
CHECK(tbl["b"][1][0] == at_path(tbl, "b[1][0]"));
|
||||
CHECK(tbl["b"][1][0] == at_path(tbl, "b[1] \t [0]")); // whitespace is allowed after array
|
||||
// indexers
|
||||
|
||||
CHECK(tbl["b"][2]["c"]);
|
||||
CHECK(tbl["b"][2]["c"] == at_path(tbl, "b[2].c"));
|
||||
CHECK(tbl["b"][2]["c"] == at_path(tbl, "b[2] \t.c")); // whitespace is allowed after array indexers
|
||||
|
||||
CHECK(tbl["d"]);
|
||||
CHECK(tbl["d"] == at_path(tbl, "d"));
|
||||
|
||||
CHECK(tbl["d"]["e"]);
|
||||
CHECK(tbl["d"]["e"] == at_path(tbl, "d.e"));
|
||||
CHECK(tbl["d"]["e"] != at_path(tbl, "d. e")); // equivalent to "d"." e"
|
||||
CHECK(!at_path(tbl, "d. e"));
|
||||
|
||||
CHECK(tbl["d"][""]);
|
||||
CHECK(tbl["d"][""] == at_path(tbl, "d."));
|
||||
}
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
// this section uses the node_view member function version of at_path
|
||||
|
||||
auto arr = tbl["b"];
|
||||
|
||||
CHECK(tbl["b"][0]);
|
||||
CHECK(tbl["b"][0] == arr.at_path("[0]"));
|
||||
CHECK(tbl["b"][0] == arr.at_path("[0] "));
|
||||
CHECK(tbl["b"][0] == arr.at_path("[ 0\t]")); // whitespace is allowed inside array indexer
|
||||
|
||||
CHECK(tbl["b"][1]);
|
||||
CHECK(tbl["b"][1].node() != arr[0].node());
|
||||
CHECK(tbl["b"][1] == arr.at_path("[1]"));
|
||||
|
||||
CHECK(tbl["b"][1][0]);
|
||||
CHECK(tbl["b"][1][0] == arr.at_path("[1][0]"));
|
||||
CHECK(tbl["b"][1][0] == arr.at_path("[1] \t [0]")); // whitespace is allowed after array
|
||||
// indexers
|
||||
|
||||
CHECK(tbl["b"][2]["c"]);
|
||||
CHECK(tbl["b"][2]["c"] == arr.at_path("[2].c"));
|
||||
CHECK(tbl["b"][2]["c"] == arr.at_path("[2] \t.c")); // whitespace is allowed after array indexers
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#include "settings.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Weverything"
|
||||
#elif defined (__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
#pragma GCC diagnostic ignored "-Wpadded"
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(push, 0)
|
||||
#pragma warning(disable : 4365)
|
||||
#pragma warning(disable : 4868)
|
||||
#pragma warning(disable : 5105)
|
||||
#endif
|
||||
|
||||
#if __has_include(<Catch2/single_include/catch2/catch.hpp>)
|
||||
#include <Catch2/single_include/catch2/catch.hpp>
|
||||
#else
|
||||
#error Catch2 is missing! You probably need to fetch submodules ("git submodule update --init --depth 1 external/Catch2")
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@ -6,22 +6,19 @@
|
||||
// this file was generated by generate_conformance_tests.py - do not modify it directly
|
||||
|
||||
#include "tests.h"
|
||||
using namespace toml::impl;
|
||||
|
||||
TOML_DISABLE_WARNINGS; // unused variable spam
|
||||
|
||||
namespace
|
||||
{
|
||||
static constexpr auto array_missing_separator = R"(wrong = [ 1 2 3 ])"sv;
|
||||
static constexpr auto array_no_close_2 = R"(x = [42 #)"sv;
|
||||
static constexpr auto array_no_close_table_2 = R"(x = [{ key = 42 #)"sv;
|
||||
static constexpr auto array_no_close_table = R"(x = [{ key = 42)"sv;
|
||||
static constexpr auto array_no_close = R"(long_array = [ 1, 2, 3)"sv;
|
||||
static constexpr auto array_tables_1 = R"(# INVALID TOML DOC
|
||||
static constexpr auto array_missing_separator = R"(wrong = [ 1 2 3 ])"sv;
|
||||
static constexpr auto array_no_close_2 = R"(x = [42 #)"sv;
|
||||
static constexpr auto array_no_close_table_2 = R"(x = [{ key = 42 #)"sv;
|
||||
static constexpr auto array_no_close_table = R"(x = [{ key = 42)"sv;
|
||||
static constexpr auto array_no_close = R"(long_array = [ 1, 2, 3)"sv;
|
||||
static constexpr auto array_tables_1 = R"(# INVALID TOML DOC
|
||||
fruit = []
|
||||
|
||||
[[fruit]] # Not allowed)"sv;
|
||||
static constexpr auto array_tables_2 = R"(# INVALID TOML DOC
|
||||
static constexpr auto array_tables_2 = R"(# INVALID TOML DOC
|
||||
[[fruit]]
|
||||
name = "apple"
|
||||
|
||||
@ -31,7 +28,7 @@ fruit = []
|
||||
# This table conflicts with the previous table
|
||||
[fruit.variety]
|
||||
name = "granny smith")"sv;
|
||||
static constexpr auto array_text_after_array_entries = R"(array = [
|
||||
static constexpr auto array_text_after_array_entries = R"(array = [
|
||||
"Is there life after an array separator?", No
|
||||
"Entry"
|
||||
])"sv;
|
||||
@ -39,66 +36,160 @@ fruit = []
|
||||
"Is there life before an array separator?" No,
|
||||
"Entry"
|
||||
])"sv;
|
||||
static constexpr auto array_text_in_array = R"(array = [
|
||||
static constexpr auto array_text_in_array = R"(array = [
|
||||
"Entry 1",
|
||||
I don't belong,
|
||||
"Entry 2",
|
||||
])"sv;
|
||||
|
||||
static constexpr auto bool_mixed_case = R"(valid = False)"sv;
|
||||
static constexpr auto bool_mixed_case = R"(valid = False)"sv;
|
||||
static constexpr auto bool_wrong_case_false = R"(b = FALSE)"sv;
|
||||
static constexpr auto bool_wrong_case_true = R"(a = TRUE)"sv;
|
||||
static constexpr auto bool_wrong_case_true = R"(a = TRUE)"sv;
|
||||
|
||||
static constexpr auto datetime_impossible_date = R"(d = 2006-01-50T00:00:00Z)"sv;
|
||||
static constexpr auto datetime_no_leads_with_milli = R"(with-milli = 1987-07-5T17:45:00.12Z)"sv;
|
||||
static constexpr auto datetime_no_leads = R"(no-leads = 1987-7-05T17:45:00Z)"sv;
|
||||
static constexpr auto datetime_no_t = R"(no-t = 1987-07-0517:45:00Z)"sv;
|
||||
static constexpr auto datetime_trailing_t = R"(d = 2006-01-30T)"sv;
|
||||
static constexpr auto control_bare_cr =
|
||||
"# The following line contains a single carriage return control character\r\n"
|
||||
"\r"sv;
|
||||
static constexpr auto control_bare_formfeed = "bare-formfeed = \f"sv;
|
||||
static constexpr auto control_bare_null = "bare-null = \"some value\" \x00"sv;
|
||||
static constexpr auto control_bare_vertical_tab = "bare-vertical-tab = \v"sv;
|
||||
static constexpr auto control_comment_cr = "comment-cr = \"Carriage return in comment\" # \ra=1"sv;
|
||||
static constexpr auto control_comment_del = "comment-del = \"0x7f\" # \x7F"sv;
|
||||
static constexpr auto control_comment_lf = "comment-lf = \"ctrl-P\" # \x10"sv;
|
||||
static constexpr auto control_comment_null = "comment-null = \"null\" # \x00"sv;
|
||||
static constexpr auto control_comment_us = "comment-us = \"ctrl-_\" # \x1F"sv;
|
||||
static constexpr auto control_multi_del = "multi-del = \"\"\"null\x7F\"\"\""sv;
|
||||
static constexpr auto control_multi_lf = "multi-lf = \"\"\"null\x10\"\"\""sv;
|
||||
static constexpr auto control_multi_null = "multi-null = \"\"\"null\x00\"\"\""sv;
|
||||
static constexpr auto control_multi_us = "multi-us = \"\"\"null\x1F\"\"\""sv;
|
||||
static constexpr auto control_rawmulti_del = "rawmulti-del = '''null\x7F'''"sv;
|
||||
static constexpr auto control_rawmulti_lf = "rawmulti-lf = '''null\x10'''"sv;
|
||||
static constexpr auto control_rawmulti_null = "rawmulti-null = '''null\x00'''"sv;
|
||||
static constexpr auto control_rawmulti_us = "rawmulti-us = '''null\x1F'''"sv;
|
||||
static constexpr auto control_rawstring_del = "rawstring-del = 'null\x7F'"sv;
|
||||
static constexpr auto control_rawstring_lf = "rawstring-lf = 'null\x10'"sv;
|
||||
static constexpr auto control_rawstring_null = "rawstring-null = 'null\x00'"sv;
|
||||
static constexpr auto control_rawstring_us = "rawstring-us = 'null\x1F'"sv;
|
||||
static constexpr auto control_string_bs = "string-bs = \"backspace\x08\""sv;
|
||||
static constexpr auto control_string_del = "string-del = \"null\x7F\""sv;
|
||||
static constexpr auto control_string_lf = "string-lf = \"null\x10\""sv;
|
||||
static constexpr auto control_string_null = "string-null = \"null\x00\""sv;
|
||||
static constexpr auto control_string_us = "string-us = \"null\x1F\""sv;
|
||||
|
||||
static constexpr auto datetime_hour_over = R"(# time-hour = 2DIGIT ; 00-23
|
||||
d = 2006-01-01T24:00:00-00:00)"sv;
|
||||
static constexpr auto datetime_mday_over = R"(# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
|
||||
# ; month/year
|
||||
d = 2006-01-32T00:00:00-00:00)"sv;
|
||||
static constexpr auto datetime_mday_under = R"(# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
|
||||
# ; month/year
|
||||
d = 2006-01-00T00:00:00-00:00)"sv;
|
||||
static constexpr auto datetime_minute_over = R"(# time-minute = 2DIGIT ; 00-59
|
||||
d = 2006-01-01T00:60:00-00:00)"sv;
|
||||
static constexpr auto datetime_month_over = R"(# date-month = 2DIGIT ; 01-12
|
||||
d = 2006-13-01T00:00:00-00:00)"sv;
|
||||
static constexpr auto datetime_month_under = R"(# date-month = 2DIGIT ; 01-12
|
||||
d = 2007-00-01T00:00:00-00:00)"sv;
|
||||
static constexpr auto datetime_no_leads_with_milli = R"(# Day "5" instead of "05"; the leading zero is required.
|
||||
with-milli = 1987-07-5T17:45:00.12Z)"sv;
|
||||
static constexpr auto datetime_no_leads = R"(# Month "7" instead of "07"; the leading zero is required.
|
||||
no-leads = 1987-7-05T17:45:00Z)"sv;
|
||||
static constexpr auto datetime_no_t = R"(# No "t" or "T" between the date and time.
|
||||
no-t = 1987-07-0517:45:00Z)"sv;
|
||||
static constexpr auto datetime_second_over =
|
||||
R"(# time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second
|
||||
# ; rules
|
||||
d = 2006-01-01T00:00:61-00:00)"sv;
|
||||
static constexpr auto datetime_time_no_leads_2 = R"(# Leading 0 is always required.
|
||||
d = 01:32:0)"sv;
|
||||
static constexpr auto datetime_time_no_leads = R"(# Leading 0 is always required.
|
||||
d = 1:32:00)"sv;
|
||||
static constexpr auto datetime_trailing_t = R"(# Date cannot end with trailing T
|
||||
d = 2006-01-30T)"sv;
|
||||
|
||||
#if !TOML_LANG_UNRELEASED
|
||||
|
||||
static constexpr auto datetime_no_secs = R"(no-secs = 1987-07-05T17:45Z)"sv;
|
||||
static constexpr auto datetime_no_secs = R"(# No seconds in time.
|
||||
no-secs = 1987-07-05T17:45Z)"sv;
|
||||
|
||||
#endif // !TOML_LANG_UNRELEASED
|
||||
|
||||
static constexpr auto float_double_point_1 = R"(double-point-1 = 0..1)"sv;
|
||||
static constexpr auto float_double_point_2 = R"(double-point-2 = 0.1.2)"sv;
|
||||
static constexpr auto float_exp_double_e_1 = R"(exp-double-e-1 = 1ee2)"sv;
|
||||
static constexpr auto float_exp_double_e_2 = R"(exp-double-e-2 = 1e2e3)"sv;
|
||||
static constexpr auto float_exp_double_us = R"(exp-double-us = 1e__23)"sv;
|
||||
static constexpr auto float_exp_leading_us = R"(exp-leading-us = 1e_23)"sv;
|
||||
static constexpr auto float_exp_point_1 = R"(exp-point-1 = 1e2.3)"sv;
|
||||
static constexpr auto float_exp_point_2 = R"(exp-point-2 = 1.e2)"sv;
|
||||
static constexpr auto float_exp_trailing_us = R"(exp-trailing-us = 1e_23_)"sv;
|
||||
static constexpr auto float_inf_incomplete_1 = R"(inf-incomplete-1 = in)"sv;
|
||||
static constexpr auto float_inf_incomplete_2 = R"(inf-incomplete-2 = +in)"sv;
|
||||
static constexpr auto float_inf_incomplete_3 = R"(inf-incomplete-3 = -in)"sv;
|
||||
static constexpr auto float_inf_underscore = R"(inf_underscore = in_f)"sv;
|
||||
static constexpr auto float_leading_point_neg = R"(leading-point-neg = -.12345)"sv;
|
||||
static constexpr auto float_leading_point_plus = R"(leading-point-plus = +.12345)"sv;
|
||||
static constexpr auto float_leading_point = R"(leading-point = .12345)"sv;
|
||||
static constexpr auto float_leading_us = R"(leading-us = _1.2)"sv;
|
||||
static constexpr auto float_leading_zero_neg = R"(leading-zero-neg = -03.14)"sv;
|
||||
static constexpr auto float_leading_zero_plus = R"(leading-zero-plus = +03.14)"sv;
|
||||
static constexpr auto float_leading_zero = R"(leading-zero = 03.14)"sv;
|
||||
static constexpr auto float_nan_incomplete_1 = R"(nan-incomplete-1 = na)"sv;
|
||||
static constexpr auto float_nan_incomplete_2 = R"(nan-incomplete-2 = +na)"sv;
|
||||
static constexpr auto float_nan_incomplete_3 = R"(nan-incomplete-3 = -na)"sv;
|
||||
static constexpr auto float_nan_underscore = R"(nan_underscore = na_n)"sv;
|
||||
static constexpr auto float_trailing_point_min = R"(trailing-point-min = -1.)"sv;
|
||||
static constexpr auto float_trailing_point_plus = R"(trailing-point-plus = +1.)"sv;
|
||||
static constexpr auto float_trailing_point = R"(trailing-point = 1.)"sv;
|
||||
static constexpr auto float_trailing_us = R"(trailing-us = 1.2_)"sv;
|
||||
static constexpr auto float_us_after_point = R"(us-after-point = 1._2)"sv;
|
||||
static constexpr auto float_us_before_point = R"(us-before-point = 1_.2)"sv;
|
||||
static constexpr auto encoding_bad_utf8_at_end =
|
||||
"\x23\x20\x54\x68\x65\x72\x65\x20\x69\x73\x20\x61\x20\x30\x78\x64\x61\x20\x61\x74\x20\x61\x66\x74\x65"
|
||||
"\x72\x20\x74\x68\x65\x20\x71\x75\x6F\x74\x65\x73\x2C\x20\x61\x6E\x64\x20\x6E\x6F\x20\x45\x4F\x4C\x20"
|
||||
"\x61\x74\x20\x74\x68\x65\x20\x65\x6E\x64\x20\x6F\x66\x20\x74\x68\x65\x20\x66\x69\x6C\x65\x2E\x0A\x23"
|
||||
"\x0A\x23\x20\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x62\x69\x74\x20\x6F\x66\x20\x61\x6E\x20\x65\x64"
|
||||
"\x67\x65\x20\x63\x61\x73\x65\x3A\x20\x54\x68\x69\x73\x20\x69\x6E\x64\x69\x63\x61\x74\x65\x73\x20\x74"
|
||||
"\x68\x65\x72\x65\x20\x73\x68\x6F\x75\x6C\x64\x20\x62\x65\x20\x74\x77\x6F\x20\x62\x79\x74\x65\x73\x0A"
|
||||
"\x23\x20\x28\x30\x62\x31\x31\x30\x31\x5F\x31\x30\x31\x30\x29\x20\x62\x75\x74\x20\x74\x68\x65\x72\x65"
|
||||
"\x20\x69\x73\x20\x6E\x6F\x20\x62\x79\x74\x65\x20\x74\x6F\x20\x66\x6F\x6C\x6C\x6F\x77\x20\x62\x65\x63"
|
||||
"\x61\x75\x73\x65\x20\x69\x74\x27\x73\x20\x74\x68\x65\x20\x65\x6E\x64\x20\x6F\x66\x20\x74\x68\x65\x20"
|
||||
"\x66\x69\x6C\x65\x2E\x0A\x78\x20\x3D\x20\x22\x22\x22\x22\x22\x22\xDA"sv;
|
||||
static constexpr auto encoding_bad_utf8_in_comment = "\x23\x20\xC3\x0A"sv;
|
||||
static constexpr auto encoding_bad_utf8_in_string =
|
||||
"\x23\x20\x54\x68\x65\x20\x66\x6F\x6C\x6C\x6F\x77\x69\x6E\x67\x20\x6C\x69\x6E\x65\x20\x63\x6F\x6E\x74"
|
||||
"\x61\x69\x6E\x73\x20\x61\x6E\x20\x69\x6E\x76\x61\x6C\x69\x64\x20\x55\x54\x46\x2D\x38\x20\x73\x65\x71"
|
||||
"\x75\x65\x6E\x63\x65\x2E\x0A\x62\x61\x64\x20\x3D\x20\x22\xC3\x22\x0A"sv;
|
||||
static constexpr auto encoding_bom_not_at_start_1 =
|
||||
"\x62\x6F\x6D\x2D\x6E\x6F\x74\x2D\x61\x74\x2D\x73\x74\x61\x72\x74\x20\xFF\xFD\x0A"sv;
|
||||
static constexpr auto encoding_bom_not_at_start_2 =
|
||||
"\x62\x6F\x6D\x2D\x6E\x6F\x74\x2D\x61\x74\x2D\x73\x74\x61\x72\x74\x3D\x20\xFF\xFD\x0A"sv;
|
||||
static constexpr auto encoding_utf16_bom =
|
||||
"\xFE\xFF\x00\x23\x00\x20\x00\x55\x00\x54\x00\x46\x00\x2D\x00\x31\x00\x36\x00\x20\x00\x77\x00\x69\x00"
|
||||
"\x74\x00\x68\x00\x20\x00\x42\x00\x4F\x00\x4D\x00\x0A"sv;
|
||||
static constexpr auto encoding_utf16 =
|
||||
"\x00#\x00 \x00U\x00T\x00F\x00-\x001\x006\x00 \x00w\x00i\x00t\x00h\x00o\x00u\x00t\x00 \x00B\x00O\x00M\x00"sv;
|
||||
|
||||
static constexpr auto inline_table_double_comma = R"(t = {x=3,,y=4})"sv;
|
||||
static constexpr auto inline_table_empty = R"(t = {,})"sv;
|
||||
static constexpr auto inline_table_no_comma = R"(t = {x = 3 y = 4})"sv;
|
||||
static constexpr auto float_double_point_1 = R"(double-point-1 = 0..1)"sv;
|
||||
static constexpr auto float_double_point_2 = R"(double-point-2 = 0.1.2)"sv;
|
||||
static constexpr auto float_exp_double_e_1 = R"(exp-double-e-1 = 1ee2)"sv;
|
||||
static constexpr auto float_exp_double_e_2 = R"(exp-double-e-2 = 1e2e3)"sv;
|
||||
static constexpr auto float_exp_double_us = R"(exp-double-us = 1e__23)"sv;
|
||||
static constexpr auto float_exp_leading_us = R"(exp-leading-us = 1e_23)"sv;
|
||||
static constexpr auto float_exp_point_1 = R"(exp-point-1 = 1e2.3)"sv;
|
||||
static constexpr auto float_exp_point_2 = R"(exp-point-2 = 1.e2)"sv;
|
||||
static constexpr auto float_exp_trailing_us = R"(exp-trailing-us = 1e_23_)"sv;
|
||||
static constexpr auto float_inf_incomplete_1 = R"(inf-incomplete-1 = in)"sv;
|
||||
static constexpr auto float_inf_incomplete_2 = R"(inf-incomplete-2 = +in)"sv;
|
||||
static constexpr auto float_inf_incomplete_3 = R"(inf-incomplete-3 = -in)"sv;
|
||||
static constexpr auto float_inf_underscore = R"(inf_underscore = in_f)"sv;
|
||||
static constexpr auto float_leading_point_neg = R"(leading-point-neg = -.12345)"sv;
|
||||
static constexpr auto float_leading_point_plus = R"(leading-point-plus = +.12345)"sv;
|
||||
static constexpr auto float_leading_point = R"(leading-point = .12345)"sv;
|
||||
static constexpr auto float_leading_us = R"(leading-us = _1.2)"sv;
|
||||
static constexpr auto float_leading_zero_neg = R"(leading-zero-neg = -03.14)"sv;
|
||||
static constexpr auto float_leading_zero_plus = R"(leading-zero-plus = +03.14)"sv;
|
||||
static constexpr auto float_leading_zero = R"(leading-zero = 03.14)"sv;
|
||||
static constexpr auto float_nan_incomplete_1 = R"(nan-incomplete-1 = na)"sv;
|
||||
static constexpr auto float_nan_incomplete_2 = R"(nan-incomplete-2 = +na)"sv;
|
||||
static constexpr auto float_nan_incomplete_3 = R"(nan-incomplete-3 = -na)"sv;
|
||||
static constexpr auto float_nan_underscore = R"(nan_underscore = na_n)"sv;
|
||||
static constexpr auto float_trailing_point_min = R"(trailing-point-min = -1.)"sv;
|
||||
static constexpr auto float_trailing_point_plus = R"(trailing-point-plus = +1.)"sv;
|
||||
static constexpr auto float_trailing_point = R"(trailing-point = 1.)"sv;
|
||||
static constexpr auto float_trailing_us_exp = R"(# trailing underscore in integer part is not allowed
|
||||
trailing-us-exp = 1_e2
|
||||
# trailing underscore in float part is not allowed
|
||||
trailing-us-exp2 = 1.2_e2)"sv;
|
||||
static constexpr auto float_trailing_us = R"(trailing-us = 1.2_)"sv;
|
||||
static constexpr auto float_us_after_point = R"(us-after-point = 1._2)"sv;
|
||||
static constexpr auto float_us_before_point = R"(us-before-point = 1_.2)"sv;
|
||||
|
||||
static constexpr auto inline_table_add = R"(a={}
|
||||
# Inline tables are immutable and can't be extended
|
||||
[a.b])"sv;
|
||||
static constexpr auto inline_table_double_comma = R"(t = {x=3,,y=4})"sv;
|
||||
static constexpr auto inline_table_duplicate_key = R"(# Duplicate keys within an inline table are invalid
|
||||
a={b=1, b=2})"sv;
|
||||
static constexpr auto inline_table_empty = R"(t = {,})"sv;
|
||||
static constexpr auto inline_table_no_comma = R"(t = {x = 3 y = 4})"sv;
|
||||
static constexpr auto inline_table_overwrite = R"(a.b=0
|
||||
# Since table "a" is already defined, it can't be replaced by an inline table.
|
||||
a={})"sv;
|
||||
|
||||
#if !TOML_LANG_UNRELEASED
|
||||
|
||||
static constexpr auto inline_table_linebreak_1 = R"(# No newlines are allowed between the curly braces unless they are valid within
|
||||
static constexpr auto inline_table_linebreak_1 =
|
||||
R"(# No newlines are allowed between the curly braces unless they are valid within
|
||||
# a value.
|
||||
simple = { a = 1
|
||||
})"sv;
|
||||
@ -110,77 +201,83 @@ b=2})"sv;
|
||||
first = "Tom",
|
||||
last = "Preston-Werner"
|
||||
})"sv;
|
||||
static constexpr auto inline_table_trailing_comma = R"(# A terminating comma (also called trailing comma) is not permitted after the
|
||||
static constexpr auto inline_table_trailing_comma =
|
||||
R"(# A terminating comma (also called trailing comma) is not permitted after the
|
||||
# last key/value pair in an inline table
|
||||
abc = { abc = 123, })"sv;
|
||||
|
||||
#endif // !TOML_LANG_UNRELEASED
|
||||
|
||||
static constexpr auto integer_capital_bin = R"(capital-bin = 0B0)"sv;
|
||||
static constexpr auto integer_capital_hex = R"(capital-hex = 0X1)"sv;
|
||||
static constexpr auto integer_capital_oct = R"(capital-oct = 0O0)"sv;
|
||||
static constexpr auto integer_double_sign_nex = R"(double-sign-nex = --99)"sv;
|
||||
static constexpr auto integer_double_sign_plus = R"(double-sign-plus = ++99)"sv;
|
||||
static constexpr auto integer_double_us = R"(double-us = 1__23)"sv;
|
||||
static constexpr auto integer_invalid_bin = R"(invalid-bin = 0b0012)"sv;
|
||||
static constexpr auto integer_invalid_hex = R"(invalid-hex = 0xaafz)"sv;
|
||||
static constexpr auto integer_invalid_oct = R"(invalid-oct = 0o778)"sv;
|
||||
static constexpr auto integer_leading_us_bin = R"(leading-us-bin = _0o1)"sv;
|
||||
static constexpr auto integer_leading_us_hex = R"(leading-us-hex = _0o1)"sv;
|
||||
static constexpr auto integer_leading_us_oct = R"(leading-us-oct = _0o1)"sv;
|
||||
static constexpr auto integer_leading_us = R"(leading-us = _123)"sv;
|
||||
static constexpr auto integer_leading_zero_1 = R"(leading-zero-1 = 01)"sv;
|
||||
static constexpr auto integer_leading_zero_2 = R"(leading-zero-2 = 00)"sv;
|
||||
static constexpr auto integer_capital_bin = R"(capital-bin = 0B0)"sv;
|
||||
static constexpr auto integer_capital_hex = R"(capital-hex = 0X1)"sv;
|
||||
static constexpr auto integer_capital_oct = R"(capital-oct = 0O0)"sv;
|
||||
static constexpr auto integer_double_sign_nex = R"(double-sign-nex = --99)"sv;
|
||||
static constexpr auto integer_double_sign_plus = R"(double-sign-plus = ++99)"sv;
|
||||
static constexpr auto integer_double_us = R"(double-us = 1__23)"sv;
|
||||
static constexpr auto integer_incomplete_bin = R"(incomplete-bin = 0b)"sv;
|
||||
static constexpr auto integer_incomplete_hex = R"(incomplete-hex = 0x)"sv;
|
||||
static constexpr auto integer_incomplete_oct = R"(incomplete-oct = 0o)"sv;
|
||||
static constexpr auto integer_invalid_bin = R"(invalid-bin = 0b0012)"sv;
|
||||
static constexpr auto integer_invalid_hex = R"(invalid-hex = 0xaafz)"sv;
|
||||
static constexpr auto integer_invalid_oct = R"(invalid-oct = 0o778)"sv;
|
||||
static constexpr auto integer_leading_us_bin = R"(leading-us-bin = _0o1)"sv;
|
||||
static constexpr auto integer_leading_us_hex = R"(leading-us-hex = _0o1)"sv;
|
||||
static constexpr auto integer_leading_us_oct = R"(leading-us-oct = _0o1)"sv;
|
||||
static constexpr auto integer_leading_us = R"(leading-us = _123)"sv;
|
||||
static constexpr auto integer_leading_zero_1 = R"(leading-zero-1 = 01)"sv;
|
||||
static constexpr auto integer_leading_zero_2 = R"(leading-zero-2 = 00)"sv;
|
||||
static constexpr auto integer_leading_zero_3 = R"(leading-zero-3 = 0_0)"sv;
|
||||
static constexpr auto integer_leading_zero_sign_1 = R"(leading-zero-sign-1 = -01)"sv;
|
||||
static constexpr auto integer_leading_zero_sign_2 = R"(leading-zero-sign-2 = +01)"sv;
|
||||
static constexpr auto integer_negative_bin = R"(negative-bin = -0b11010110)"sv;
|
||||
static constexpr auto integer_negative_hex = R"(negative-hex = -0xff)"sv;
|
||||
static constexpr auto integer_negative_oct = R"(negative-oct = -0o99)"sv;
|
||||
static constexpr auto integer_positive_bin = R"(positive-bin = +0b11010110)"sv;
|
||||
static constexpr auto integer_positive_hex = R"(positive-hex = +0xff)"sv;
|
||||
static constexpr auto integer_positive_oct = R"(positive-oct = +0o99)"sv;
|
||||
static constexpr auto integer_text_after_integer = R"(answer = 42 the ultimate answer?)"sv;
|
||||
static constexpr auto integer_trailing_us_bin = R"(trailing-us-bin = 0b1_)"sv;
|
||||
static constexpr auto integer_trailing_us_hex = R"(trailing-us-hex = 0x1_)"sv;
|
||||
static constexpr auto integer_trailing_us_oct = R"(trailing-us-oct = 0o1_)"sv;
|
||||
static constexpr auto integer_trailing_us = R"(trailing-us = 123_)"sv;
|
||||
static constexpr auto integer_us_after_bin = R"(us-after-bin = 0b_1)"sv;
|
||||
static constexpr auto integer_us_after_hex = R"(us-after-hex = 0x_1)"sv;
|
||||
static constexpr auto integer_us_after_oct = R"(us-after-oct = 0o_1)"sv;
|
||||
static constexpr auto integer_leading_zero_sign_3 = R"(leading-zero-sign-3 = +0_1)"sv;
|
||||
static constexpr auto integer_negative_bin = R"(negative-bin = -0b11010110)"sv;
|
||||
static constexpr auto integer_negative_hex = R"(negative-hex = -0xff)"sv;
|
||||
static constexpr auto integer_negative_oct = R"(negative-oct = -0o99)"sv;
|
||||
static constexpr auto integer_positive_bin = R"(positive-bin = +0b11010110)"sv;
|
||||
static constexpr auto integer_positive_hex = R"(positive-hex = +0xff)"sv;
|
||||
static constexpr auto integer_positive_oct = R"(positive-oct = +0o99)"sv;
|
||||
static constexpr auto integer_text_after_integer = R"(answer = 42 the ultimate answer?)"sv;
|
||||
static constexpr auto integer_trailing_us_bin = R"(trailing-us-bin = 0b1_)"sv;
|
||||
static constexpr auto integer_trailing_us_hex = R"(trailing-us-hex = 0x1_)"sv;
|
||||
static constexpr auto integer_trailing_us_oct = R"(trailing-us-oct = 0o1_)"sv;
|
||||
static constexpr auto integer_trailing_us = R"(trailing-us = 123_)"sv;
|
||||
static constexpr auto integer_us_after_bin = R"(us-after-bin = 0b_1)"sv;
|
||||
static constexpr auto integer_us_after_hex = R"(us-after-hex = 0x_1)"sv;
|
||||
static constexpr auto integer_us_after_oct = R"(us-after-oct = 0o_1)"sv;
|
||||
|
||||
static constexpr auto key_after_array = R"([[agencies]] owner = "S Cjelli")"sv;
|
||||
static constexpr auto key_after_table = R"([error] this = "should not be here")"sv;
|
||||
static constexpr auto key_after_value = R"(first = "Tom" last = "Preston-Werner" # INVALID)"sv;
|
||||
static constexpr auto key_after_array = R"([[agencies]] owner = "S Cjelli")"sv;
|
||||
static constexpr auto key_after_table = R"([error] this = "should not be here")"sv;
|
||||
static constexpr auto key_after_value = R"(first = "Tom" last = "Preston-Werner" # INVALID)"sv;
|
||||
static constexpr auto key_bare_invalid_character = R"(bare!key = 123)"sv;
|
||||
static constexpr auto key_dotted_redefine_table = R"(# Defined a.b as int
|
||||
static constexpr auto key_dotted_redefine_table = R"(# Defined a.b as int
|
||||
a.b = 1
|
||||
# Tries to access it as table: error
|
||||
a.b.c = 2)"sv;
|
||||
static constexpr auto key_duplicate_keys = R"(dupe = false
|
||||
static constexpr auto key_duplicate_keys = R"(dupe = false
|
||||
dupe = true)"sv;
|
||||
static constexpr auto key_duplicate = R"(# DO NOT DO THIS
|
||||
static constexpr auto key_duplicate = R"(# DO NOT DO THIS
|
||||
name = "Tom"
|
||||
name = "Pradyun")"sv;
|
||||
static constexpr auto key_empty = R"(= 1)"sv;
|
||||
static constexpr auto key_escape = R"(\u00c0 = "latin capital letter A with grave")"sv;
|
||||
static constexpr auto key_hash = R"(a# = 1)"sv;
|
||||
static constexpr auto key_multiline = R"("""long
|
||||
static constexpr auto key_empty = R"( = 1)"sv;
|
||||
static constexpr auto key_escape = R"(\u00c0 = "latin capital letter A with grave")"sv;
|
||||
static constexpr auto key_hash = R"(a# = 1)"sv;
|
||||
static constexpr auto key_multiline = R"("""long
|
||||
key""" = 1)"sv;
|
||||
static constexpr auto key_newline = R"(barekey
|
||||
static constexpr auto key_newline = R"(barekey
|
||||
= 123)"sv;
|
||||
static constexpr auto key_no_eol = R"(a = 1 b = 2)"sv;
|
||||
static constexpr auto key_open_bracket = R"([abc = 1)"sv;
|
||||
static constexpr auto key_partial_quoted = R"(partial"quoted" = 5)"sv;
|
||||
static constexpr auto key_single_open_bracket = R"([)"sv;
|
||||
static constexpr auto key_space = R"(a b = 1)"sv;
|
||||
static constexpr auto key_start_bracket = R"([a]
|
||||
static constexpr auto key_no_eol = R"(a = 1 b = 2)"sv;
|
||||
static constexpr auto key_open_bracket = R"([abc = 1)"sv;
|
||||
static constexpr auto key_partial_quoted = R"(partial"quoted" = 5)"sv;
|
||||
static constexpr auto key_single_open_bracket = R"([)"sv;
|
||||
static constexpr auto key_space = R"(a b = 1)"sv;
|
||||
static constexpr auto key_start_bracket = R"([a]
|
||||
[xyz = 5
|
||||
[b])"sv;
|
||||
static constexpr auto key_two_equals = R"(key= = 1)"sv;
|
||||
static constexpr auto key_two_equals2 = R"(a==1)"sv;
|
||||
static constexpr auto key_two_equals3 = R"(a=b=1)"sv;
|
||||
static constexpr auto key_without_value_1 = R"(key)"sv;
|
||||
static constexpr auto key_without_value_2 = R"(key =)"sv;
|
||||
static constexpr auto key_two_equals = R"(key= = 1)"sv;
|
||||
static constexpr auto key_two_equals2 = R"(a==1)"sv;
|
||||
static constexpr auto key_two_equals3 = R"(a=b=1)"sv;
|
||||
static constexpr auto key_without_value_1 = R"(key)"sv;
|
||||
static constexpr auto key_without_value_2 = R"(key = )"sv;
|
||||
|
||||
#if !TOML_LANG_UNRELEASED && UNICODE_LITERALS_OK
|
||||
|
||||
@ -189,34 +286,42 @@ key""" = 1)"sv;
|
||||
#endif // !TOML_LANG_UNRELEASED && UNICODE_LITERALS_OK
|
||||
|
||||
static constexpr auto string_bad_byte_escape = R"(naughty = "\xAg")"sv;
|
||||
static constexpr auto string_bad_codepoint = R"(invalid-codepoint = "This string contains a non scalar unicode codepoint \uD801")"sv;
|
||||
static constexpr auto string_bad_concat = R"(no_concat = "first" "second")"sv;
|
||||
static constexpr auto string_bad_escape = R"(invalid-escape = "This string has a bad \a escape character.")"sv;
|
||||
static constexpr auto string_bad_codepoint =
|
||||
R"(invalid-codepoint = "This string contains a non scalar unicode codepoint \uD801")"sv;
|
||||
static constexpr auto string_bad_concat = R"(no_concat = "first" "second")"sv;
|
||||
static constexpr auto string_bad_escape_1 = R"(invalid-escape = "This string has a bad \a escape character.")"sv;
|
||||
static constexpr auto string_bad_escape_2 = R"(invalid-escape = "This string has a bad \ escape character.")"sv;
|
||||
static constexpr auto string_bad_multiline = R"(multi = "first line
|
||||
second line")"sv;
|
||||
static constexpr auto string_bad_slash_escape = R"(invalid-escape = "This string has a bad \/ escape character.")"sv;
|
||||
static constexpr auto string_bad_uni_esc = R"(str = "val\ue")"sv;
|
||||
static constexpr auto string_bad_slash_escape =
|
||||
R"(invalid-escape = "This string has a bad \/ escape character.")"sv;
|
||||
static constexpr auto string_bad_uni_esc = R"(str = "val\ue")"sv;
|
||||
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_1 = R"(a = """\UFFFFFFFF""")"sv;
|
||||
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_2 = R"(a = """\U00D80000""")"sv;
|
||||
static constexpr auto string_basic_multiline_quotes = R"(str5 = """Here are three quotation marks: """.""")"sv;
|
||||
static constexpr auto string_basic_multiline_unknown_escape = R"(a = """\@""")"sv;
|
||||
static constexpr auto string_basic_multiline_unknown_escape = R"(a = """\@""")"sv;
|
||||
static constexpr auto string_basic_out_of_range_unicode_escape_1 = R"(a = "\UFFFFFFFF")"sv;
|
||||
static constexpr auto string_basic_out_of_range_unicode_escape_2 = R"(a = "\U00D80000")"sv;
|
||||
static constexpr auto string_basic_unknown_escape = R"(a = "\@")"sv;
|
||||
static constexpr auto string_literal_multiline_quotes_1 = R"(a = '''6 apostrophes: '''''')"sv;
|
||||
static constexpr auto string_literal_multiline_quotes_2 = R"(a = '''15 apostrophes: '''''''''''''''''')"sv;
|
||||
static constexpr auto string_missing_quotes = R"(name = value)"sv;
|
||||
static constexpr auto string_multiline_escape_space = R"(a = """
|
||||
static constexpr auto string_basic_unknown_escape = R"(a = "\@")"sv;
|
||||
static constexpr auto string_literal_multiline_quotes_1 = R"(a = '''6 apostrophes: '''''')"sv;
|
||||
static constexpr auto string_literal_multiline_quotes_2 = R"(a = '''15 apostrophes: '''''''''''''''''')"sv;
|
||||
static constexpr auto string_missing_quotes = R"(name = value)"sv;
|
||||
static constexpr auto string_multiline_bad_escape_1 = R"(k = """t\a""")"sv;
|
||||
static constexpr auto string_multiline_bad_escape_2 = R"(# \<Space> is not a valid escape.
|
||||
k = """t\ t""")"sv;
|
||||
static constexpr auto string_multiline_bad_escape_3 = R"(# \<Space> is not a valid escape.
|
||||
k = """t\ """)"sv;
|
||||
static constexpr auto string_multiline_escape_space = R"(a = """
|
||||
foo \ \n
|
||||
bar""")"sv;
|
||||
static constexpr auto string_multiline_no_close_2 = R"(x=""")"sv;
|
||||
static constexpr auto string_multiline_no_close = R"(invalid = """
|
||||
static constexpr auto string_multiline_no_close_2 = R"(x=""")"sv;
|
||||
static constexpr auto string_multiline_no_close = R"(invalid = """
|
||||
this will fail)"sv;
|
||||
static constexpr auto string_multiline_quotes_1 = R"(a = """6 quotes: """""")"sv;
|
||||
static constexpr auto string_multiline_quotes_2 = R"(a = """6 quotes: """""")"sv;
|
||||
static constexpr auto string_no_close = R"(no-ending-quote = "One time, at band camp)"sv;
|
||||
static constexpr auto string_multiline_quotes_1 = R"(a = """6 quotes: """""")"sv;
|
||||
static constexpr auto string_multiline_quotes_2 = R"(a = """6 quotes: """""")"sv;
|
||||
static constexpr auto string_no_close = R"(no-ending-quote = "One time, at band camp)"sv;
|
||||
static constexpr auto string_text_after_string = R"(string = "Is there life after strings?" No.)"sv;
|
||||
static constexpr auto string_wrong_close = R"(bad-ending-quote = "double and single')"sv;
|
||||
static constexpr auto string_wrong_close = R"(bad-ending-quote = "double and single')"sv;
|
||||
|
||||
#if !TOML_LANG_UNRELEASED
|
||||
|
||||
@ -224,9 +329,36 @@ second line")"sv;
|
||||
|
||||
#endif // !TOML_LANG_UNRELEASED
|
||||
|
||||
static constexpr auto table_append_with_dotted_keys_1 = R"(# First a.b.c defines a table: a.b.c = {z=9}
|
||||
#
|
||||
# Then we define a.b.c.t = "str" to add a str to the above table, making it:
|
||||
#
|
||||
# a.b.c = {z=9, t="..."}
|
||||
#
|
||||
# While this makes sense, logically, it was decided this is not valid TOML as
|
||||
# it's too confusing/convoluted.
|
||||
#
|
||||
# See: https://github.com/toml-lang/toml/issues/846
|
||||
# https://github.com/toml-lang/toml/pull/859
|
||||
|
||||
[a.b.c]
|
||||
z = 9
|
||||
|
||||
[a]
|
||||
b.c.t = "Using dotted keys to add to [a.b.c] after explicitly defining it above is not allowed")"sv;
|
||||
static constexpr auto table_append_with_dotted_keys_2 =
|
||||
R"(# This is the same issue as in injection-1.toml, except that nests one level
|
||||
# deeper. See that file for a more complete description.
|
||||
|
||||
[a.b.c.d]
|
||||
z = 9
|
||||
|
||||
[a]
|
||||
b.c.d.k.t = "Using dotted keys to add to [a.b.c.d] after explicitly defining it above is not allowed")"sv;
|
||||
static constexpr auto table_array_empty = R"([[]]
|
||||
name = "Born to Run")"sv;
|
||||
static constexpr auto table_array_implicit = R"(# This test is a bit tricky. It should fail because the first use of
|
||||
static constexpr auto table_array_implicit =
|
||||
R"(# This test is a bit tricky. It should fail because the first use of
|
||||
# `[[albums.songs]]` without first declaring `albums` implies that `albums`
|
||||
# must be a table. The alternative would be quite weird. Namely, it wouldn't
|
||||
# comply with the TOML spec: "Each double-bracketed sub-table will belong to
|
||||
@ -240,59 +372,53 @@ name = "Glory Days"
|
||||
|
||||
[[albums]]
|
||||
name = "Born in the USA")"sv;
|
||||
static constexpr auto table_array_missing_bracket = R"([[albums]
|
||||
static constexpr auto table_array_missing_bracket = R"([[albums]
|
||||
name = "Born to Run")"sv;
|
||||
static constexpr auto table_duplicate_key_table = R"([fruit]
|
||||
static constexpr auto table_duplicate_key_dotted_table = R"([fruit]
|
||||
apple.color = "red"
|
||||
|
||||
[fruit.apple] # INVALID)"sv;
|
||||
static constexpr auto table_duplicate_key_dotted_table2 = R"([fruit]
|
||||
apple.taste.sweet = true
|
||||
|
||||
[fruit.apple.taste] # INVALID)"sv;
|
||||
static constexpr auto table_duplicate_key_table = R"([fruit]
|
||||
type = "apple"
|
||||
|
||||
[fruit.type]
|
||||
apple = "yes")"sv;
|
||||
static constexpr auto table_duplicate_table_array = R"([tbl]
|
||||
static constexpr auto table_duplicate_table_array = R"([tbl]
|
||||
[[tbl]])"sv;
|
||||
static constexpr auto table_duplicate_table_array2 = R"([[tbl]]
|
||||
static constexpr auto table_duplicate_table_array2 = R"([[tbl]]
|
||||
[tbl])"sv;
|
||||
static constexpr auto table_duplicate = R"([a]
|
||||
static constexpr auto table_duplicate = R"([a]
|
||||
b = 1
|
||||
|
||||
[a]
|
||||
c = 2)"sv;
|
||||
static constexpr auto table_empty_implicit_table = R"([naughty..naughty])"sv;
|
||||
static constexpr auto table_empty = R"([])"sv;
|
||||
static constexpr auto table_equals_sign = R"([name=bad])"sv;
|
||||
static constexpr auto table_injection_1 = R"([a.b.c]
|
||||
z = 9
|
||||
[a]
|
||||
b.c.t = "Using dotted keys to add to [a.b.c] after explicitly defining it above is not allowed"
|
||||
|
||||
# see https://github.com/toml-lang/toml/issues/846)"sv;
|
||||
static constexpr auto table_injection_2 = R"([a.b.c.d]
|
||||
z = 9
|
||||
[a]
|
||||
b.c.d.k.t = "Using dotted keys to add to [a.b.c.d] after explicitly defining it above is not allowed"
|
||||
|
||||
# see https://github.com/toml-lang/toml/issues/846)"sv;
|
||||
static constexpr auto table_llbrace = R"([ [table]])"sv;
|
||||
static constexpr auto table_nested_brackets_close = R"([a]b]
|
||||
static constexpr auto table_empty_implicit_table = R"([naughty..naughty])"sv;
|
||||
static constexpr auto table_empty = R"([])"sv;
|
||||
static constexpr auto table_equals_sign = R"([name=bad])"sv;
|
||||
static constexpr auto table_llbrace = R"([ [table]])"sv;
|
||||
static constexpr auto table_nested_brackets_close = R"([a]b]
|
||||
zyx = 42)"sv;
|
||||
static constexpr auto table_nested_brackets_open = R"([a[b]
|
||||
static constexpr auto table_nested_brackets_open = R"([a[b]
|
||||
zyx = 42)"sv;
|
||||
static constexpr auto table_quoted_no_close = R"(["where will it end]
|
||||
static constexpr auto table_quoted_no_close = R"(["where will it end]
|
||||
name = value)"sv;
|
||||
static constexpr auto table_redefine = R"(# Define b as int, and try to use it as a table: error
|
||||
static constexpr auto table_redefine = R"(# Define b as int, and try to use it as a table: error
|
||||
[a]
|
||||
b = 1
|
||||
|
||||
[a.b]
|
||||
c = 2)"sv;
|
||||
static constexpr auto table_rrbrace = R"([[table] ])"sv;
|
||||
static constexpr auto table_text_after_table = R"([error] this shouldn't be here)"sv;
|
||||
static constexpr auto table_whitespace = R"([invalid key])"sv;
|
||||
static constexpr auto table_with_pound = R"([key#group]
|
||||
static constexpr auto table_rrbrace = R"([[table] ])"sv;
|
||||
static constexpr auto table_text_after_table = R"([error] this shouldn't be here)"sv;
|
||||
static constexpr auto table_whitespace = R"([invalid key])"sv;
|
||||
static constexpr auto table_with_pound = R"([key#group]
|
||||
answer = 42)"sv;
|
||||
}
|
||||
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
TEST_CASE("conformance - burntsushi/invalid")
|
||||
{
|
||||
parsing_should_fail(FILE_LINE_ARGS, array_missing_separator); // array-missing-separator
|
||||
@ -321,7 +447,69 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, bool_wrong_case_true); // bool-wrong-case-true
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_impossible_date); // datetime-impossible-date
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_bare_cr); // control-bare-cr
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_bare_formfeed); // control-bare-formfeed
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_bare_null); // control-bare-null
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_bare_vertical_tab); // control-bare-vertical-tab
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_comment_cr); // control-comment-cr
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_comment_del); // control-comment-del
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_comment_lf); // control-comment-lf
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_comment_null); // control-comment-null
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_comment_us); // control-comment-us
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_multi_del); // control-multi-del
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_multi_lf); // control-multi-lf
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_multi_null); // control-multi-null
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_multi_us); // control-multi-us
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_rawmulti_del); // control-rawmulti-del
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_rawmulti_lf); // control-rawmulti-lf
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_rawmulti_null); // control-rawmulti-null
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_rawmulti_us); // control-rawmulti-us
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_rawstring_del); // control-rawstring-del
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_rawstring_lf); // control-rawstring-lf
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_rawstring_null); // control-rawstring-null
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_rawstring_us); // control-rawstring-us
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_string_bs); // control-string-bs
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_string_del); // control-string-del
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_string_lf); // control-string-lf
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_string_null); // control-string-null
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, control_string_us); // control-string-us
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_hour_over); // datetime-hour-over
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_mday_over); // datetime-mday-over
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_mday_under); // datetime-mday-under
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_minute_over); // datetime-minute-over
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_month_over); // datetime-month-over
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_month_under); // datetime-month-under
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_no_leads_with_milli); // datetime-no-leads-with-milli
|
||||
|
||||
@ -329,6 +517,12 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_no_t); // datetime-no-t
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_second_over); // datetime-second-over
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_time_no_leads_2); // datetime-time-no-leads-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_time_no_leads); // datetime-time-no-leads
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, datetime_trailing_t); // datetime-trailing-t
|
||||
|
||||
#if !TOML_LANG_UNRELEASED
|
||||
@ -337,6 +531,20 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
#endif // !TOML_LANG_UNRELEASED
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, encoding_bad_utf8_at_end); // encoding-bad-utf8-at-end
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, encoding_bad_utf8_in_comment); // encoding-bad-utf8-in-comment
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, encoding_bad_utf8_in_string); // encoding-bad-utf8-in-string
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, encoding_bom_not_at_start_1); // encoding-bom-not-at-start-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, encoding_bom_not_at_start_2); // encoding-bom-not-at-start-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, encoding_utf16_bom); // encoding-utf16-bom
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, encoding_utf16); // encoding-utf16
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, float_double_point_1); // float-double-point-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, float_double_point_2); // float-double-point-2
|
||||
@ -391,18 +599,26 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, float_trailing_point); // float-trailing-point
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, float_trailing_us_exp); // float-trailing-us-exp
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, float_trailing_us); // float-trailing-us
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, float_us_after_point); // float-us-after-point
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, float_us_before_point); // float-us-before-point
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_add); // inline-table-add
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_double_comma); // inline-table-double-comma
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_duplicate_key); // inline-table-duplicate-key
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_empty); // inline-table-empty
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_no_comma); // inline-table-no-comma
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_overwrite); // inline-table-overwrite
|
||||
|
||||
#if !TOML_LANG_UNRELEASED
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_linebreak_1); // inline-table-linebreak-1
|
||||
@ -429,6 +645,12 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_double_us); // integer-double-us
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_incomplete_bin); // integer-incomplete-bin
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_incomplete_hex); // integer-incomplete-hex
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_incomplete_oct); // integer-incomplete-oct
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_invalid_bin); // integer-invalid-bin
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_invalid_hex); // integer-invalid-hex
|
||||
@ -447,10 +669,14 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_leading_zero_2); // integer-leading-zero-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_leading_zero_3); // integer-leading-zero-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_leading_zero_sign_1); // integer-leading-zero-sign-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_leading_zero_sign_2); // integer-leading-zero-sign-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_leading_zero_sign_3); // integer-leading-zero-sign-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_negative_bin); // integer-negative-bin
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, integer_negative_hex); // integer-negative-hex
|
||||
@ -537,7 +763,9 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_bad_concat); // string-bad-concat
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_bad_escape); // string-bad-escape
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_bad_escape_1); // string-bad-escape-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_bad_escape_2); // string-bad-escape-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_bad_multiline); // string-bad-multiline
|
||||
|
||||
@ -545,17 +773,23 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_bad_uni_esc); // string-bad-uni-esc
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_out_of_range_unicode_escape_1); // string-basic-multiline-out-of-range-unicode-escape-1
|
||||
parsing_should_fail(
|
||||
FILE_LINE_ARGS,
|
||||
string_basic_multiline_out_of_range_unicode_escape_1); // string-basic-multiline-out-of-range-unicode-escape-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_out_of_range_unicode_escape_2); // string-basic-multiline-out-of-range-unicode-escape-2
|
||||
parsing_should_fail(
|
||||
FILE_LINE_ARGS,
|
||||
string_basic_multiline_out_of_range_unicode_escape_2); // string-basic-multiline-out-of-range-unicode-escape-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_quotes); // string-basic-multiline-quotes
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_unknown_escape); // string-basic-multiline-unknown-escape
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_out_of_range_unicode_escape_1); // string-basic-out-of-range-unicode-escape-1
|
||||
parsing_should_fail(FILE_LINE_ARGS,
|
||||
string_basic_out_of_range_unicode_escape_1); // string-basic-out-of-range-unicode-escape-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_out_of_range_unicode_escape_2); // string-basic-out-of-range-unicode-escape-2
|
||||
parsing_should_fail(FILE_LINE_ARGS,
|
||||
string_basic_out_of_range_unicode_escape_2); // string-basic-out-of-range-unicode-escape-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_unknown_escape); // string-basic-unknown-escape
|
||||
|
||||
@ -565,6 +799,12 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_missing_quotes); // string-missing-quotes
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_multiline_bad_escape_1); // string-multiline-bad-escape-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_multiline_bad_escape_2); // string-multiline-bad-escape-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_multiline_bad_escape_3); // string-multiline-bad-escape-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_multiline_escape_space); // string-multiline-escape-space
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_multiline_no_close_2); // string-multiline-no-close-2
|
||||
@ -587,12 +827,20 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
#endif // !TOML_LANG_UNRELEASED
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_append_with_dotted_keys_1); // table-append-with-dotted-keys-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_append_with_dotted_keys_2); // table-append-with-dotted-keys-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_array_empty); // table-array-empty
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_array_implicit); // table-array-implicit
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_array_missing_bracket); // table-array-missing-bracket
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_duplicate_key_dotted_table); // table-duplicate-key-dotted-table
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_duplicate_key_dotted_table2); // table-duplicate-key-dotted-table2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_duplicate_key_table); // table-duplicate-key-table
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_duplicate_table_array); // table-duplicate-table-array
|
||||
@ -607,10 +855,6 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_equals_sign); // table-equals-sign
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_injection_1); // table-injection-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_injection_2); // table-injection-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_llbrace); // table-llbrace
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_nested_brackets_close); // table-nested-brackets-close
|
||||
@ -629,4 +873,3 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_with_pound); // table-with-pound
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,146 +6,165 @@
|
||||
// this file was generated by generate_conformance_tests.py - do not modify it directly
|
||||
|
||||
#include "tests.h"
|
||||
using namespace toml::impl;
|
||||
|
||||
TOML_DISABLE_WARNINGS; // unused variable spam
|
||||
|
||||
namespace
|
||||
{
|
||||
static constexpr auto array_of_tables_1 = R"(# INVALID TOML DOC
|
||||
fruit = []
|
||||
static constexpr auto array_of_tables_1 = "# INVALID TOML DOC\r\n"
|
||||
"fruit = []\r\n"
|
||||
"\r\n"
|
||||
"[[fruit]] # Not allowed"sv;
|
||||
static constexpr auto array_of_tables_2 = "# INVALID TOML DOC\r\n"
|
||||
"[[fruit]]\r\n"
|
||||
" name = \"apple\"\r\n"
|
||||
"\r\n"
|
||||
" [[fruit.variety]]\r\n"
|
||||
" name = \"red delicious\"\r\n"
|
||||
"\r\n"
|
||||
" # This table conflicts with the previous table\r\n"
|
||||
" [fruit.variety]\r\n"
|
||||
" name = \"granny smith\""sv;
|
||||
|
||||
[[fruit]] # Not allowed)"sv;
|
||||
static constexpr auto array_of_tables_2 = R"(# INVALID TOML DOC
|
||||
[[fruit]]
|
||||
name = "apple"
|
||||
|
||||
[[fruit.variety]]
|
||||
name = "red delicious"
|
||||
|
||||
# This table conflicts with the previous table
|
||||
[fruit.variety]
|
||||
name = "granny smith")"sv;
|
||||
|
||||
static constexpr auto bare_key_1 = R"(bare!key = 123)"sv;
|
||||
static constexpr auto bare_key_2 = R"(barekey
|
||||
= 123)"sv;
|
||||
static constexpr auto bare_key_1 = "bare!key = 123"sv;
|
||||
static constexpr auto bare_key_2 = "barekey\r\n"
|
||||
" = 123"sv;
|
||||
static constexpr auto bare_key_3 = R"(barekey =)"sv;
|
||||
|
||||
static constexpr auto inline_table_imutable_1 = R"([product]
|
||||
type = { name = "Nail" }
|
||||
type.edible = false # INVALID)"sv;
|
||||
static constexpr auto inline_table_imutable_2 = R"([product]
|
||||
type.name = "Nail"
|
||||
type = { edible = false } # INVALID)"sv;
|
||||
static constexpr auto comment_control_1 = "a = \"null\" # \x00"sv;
|
||||
static constexpr auto comment_control_2 = "a = \"ctrl-P\" # \x10"sv;
|
||||
static constexpr auto comment_control_3 = "a = \"ctrl-_\" # \x1F"sv;
|
||||
static constexpr auto comment_control_4 = "a = \"0x7f\" # \x7F"sv;
|
||||
|
||||
static constexpr auto inline_table_imutable_1 = "[product]\r\n"
|
||||
"type = { name = \"Nail\" }\r\n"
|
||||
"type.edible = false # INVALID"sv;
|
||||
static constexpr auto inline_table_imutable_2 = "[product]\r\n"
|
||||
"type.name = \"Nail\"\r\n"
|
||||
"type = { edible = false } # INVALID"sv;
|
||||
|
||||
#if !TOML_LANG_UNRELEASED
|
||||
|
||||
static constexpr auto inline_table_trailing_comma = R"(abc = { abc = 123, })"sv;
|
||||
static constexpr auto inline_table_trailing_comma = "abc = { abc = 123, }"sv;
|
||||
|
||||
#endif // !TOML_LANG_UNRELEASED
|
||||
|
||||
static constexpr auto int_0_padded = R"(int = 0123)"sv;
|
||||
static constexpr auto int_signed_bin = R"(bin = +0b10)"sv;
|
||||
static constexpr auto int_signed_hex = R"(hex = +0xab)"sv;
|
||||
static constexpr auto int_signed_oct = R"(oct = +0o23)"sv;
|
||||
static constexpr auto int_0_padded = "int = 0123"sv;
|
||||
static constexpr auto int_signed_bin = "bin = +0b10"sv;
|
||||
static constexpr auto int_signed_hex = "hex = +0xab"sv;
|
||||
static constexpr auto int_signed_oct = "oct = +0o23"sv;
|
||||
|
||||
static constexpr auto key_value_pair_1 = R"(key = # INVALID)"sv;
|
||||
static constexpr auto key_value_pair_2 = R"(first = "Tom" last = "Preston-Werner" # INVALID)"sv;
|
||||
static constexpr auto key_value_pair_1 = "key = # INVALID"sv;
|
||||
static constexpr auto key_value_pair_2 = "first = \"Tom\" last = \"Preston-Werner\" # INVALID"sv;
|
||||
|
||||
static constexpr auto multiple_dot_key = R"(# THE FOLLOWING IS INVALID
|
||||
static constexpr auto multiple_dot_key = "# THE FOLLOWING IS INVALID\r\n"
|
||||
"\r\n"
|
||||
"# This defines the value of fruit.apple to be an integer.\r\n"
|
||||
"fruit.apple = 1\r\n"
|
||||
"\r\n"
|
||||
"# But then this treats fruit.apple like it's a table.\r\n"
|
||||
"# You can't turn an integer into a table.\r\n"
|
||||
"fruit.apple.smooth = true"sv;
|
||||
static constexpr auto multiple_key = "# DO NOT DO THIS\r\n"
|
||||
"name = \"Tom\"\r\n"
|
||||
"name = \"Pradyun\""sv;
|
||||
|
||||
# This defines the value of fruit.apple to be an integer.
|
||||
fruit.apple = 1
|
||||
static constexpr auto no_key_name = "= \"no key name\" # INVALID"sv;
|
||||
|
||||
# But then this treats fruit.apple like it's a table.
|
||||
# You can't turn an integer into a table.
|
||||
fruit.apple.smooth = true)"sv;
|
||||
static constexpr auto multiple_key = R"(# DO NOT DO THIS
|
||||
name = "Tom"
|
||||
name = "Pradyun")"sv;
|
||||
static constexpr auto string_basic_control_1 = "a = \"null\x00\""sv;
|
||||
static constexpr auto string_basic_control_2 = "a = \"ctrl-P\x10\""sv;
|
||||
static constexpr auto string_basic_control_3 = "a = \"ctrl-_\x1F\""sv;
|
||||
static constexpr auto string_basic_control_4 = "a = \"0x7f\x7F\""sv;
|
||||
static constexpr auto string_basic_multiline_control_1 = "a = \"\"\"null\x00\"\"\""sv;
|
||||
static constexpr auto string_basic_multiline_control_2 = "a = \"\"\"null\x10\"\"\""sv;
|
||||
static constexpr auto string_basic_multiline_control_3 = "a = \"\"\"null\x1F\"\"\""sv;
|
||||
static constexpr auto string_basic_multiline_control_4 = "a = \"\"\"null\x7F\"\"\""sv;
|
||||
static constexpr auto string_basic_multiline_invalid_backslash = "a = \"\"\"\r\n"
|
||||
" foo \\ \\n\r\n"
|
||||
" bar\"\"\""sv;
|
||||
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_1 = "a = \"\"\"\\UFFFFFFFF\"\"\""sv;
|
||||
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_2 = "a = \"\"\"\\U00D80000\"\"\""sv;
|
||||
static constexpr auto string_basic_multiline_quotes =
|
||||
"str5 = \"\"\"Here are three quotation marks: \"\"\".\"\"\""sv;
|
||||
static constexpr auto string_basic_multiline_unknown_escape = "a = \"\"\"\\@\"\"\""sv;
|
||||
static constexpr auto string_basic_out_of_range_unicode_escape_1 = "a = \"\\UFFFFFFFF\""sv;
|
||||
static constexpr auto string_basic_out_of_range_unicode_escape_2 = "a = \"\\U00D80000\""sv;
|
||||
static constexpr auto string_basic_unknown_escape = "a = \"\\@\""sv;
|
||||
static constexpr auto string_literal_control_1 = "a = 'null\x00'"sv;
|
||||
static constexpr auto string_literal_control_2 = "a = 'null\x10'"sv;
|
||||
static constexpr auto string_literal_control_3 = "a = 'null\x1F'"sv;
|
||||
static constexpr auto string_literal_control_4 = "a = 'null\x7F'"sv;
|
||||
static constexpr auto string_literal_multiline_control_1 = "a = '''null\x00'''"sv;
|
||||
static constexpr auto string_literal_multiline_control_2 = "a = '''null\x10'''"sv;
|
||||
static constexpr auto string_literal_multiline_control_3 = "a = '''null\x1F'''"sv;
|
||||
static constexpr auto string_literal_multiline_control_4 = "a = '''null\x7F'''"sv;
|
||||
static constexpr auto string_literal_multiline_quotes =
|
||||
"apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID"sv;
|
||||
|
||||
static constexpr auto no_key_name = R"(= "no key name" # INVALID)"sv;
|
||||
|
||||
static constexpr auto string_basic_multiline_invalid_backslash = R"(a = """
|
||||
foo \ \n
|
||||
bar""")"sv;
|
||||
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_1 = R"(a = """\UFFFFFFFF""")"sv;
|
||||
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_2 = R"(a = """\U00D80000""")"sv;
|
||||
static constexpr auto string_basic_multiline_quotes = R"(str5 = """Here are three quotation marks: """.""")"sv;
|
||||
static constexpr auto string_basic_multiline_unknown_escape = R"(a = """\@""")"sv;
|
||||
static constexpr auto string_basic_out_of_range_unicode_escape_1 = R"(a = "\UFFFFFFFF")"sv;
|
||||
static constexpr auto string_basic_out_of_range_unicode_escape_2 = R"(a = "\U00D80000")"sv;
|
||||
static constexpr auto string_basic_unknown_escape = R"(a = "\@")"sv;
|
||||
static constexpr auto string_literal_multiline_quotes = R"(apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID)"sv;
|
||||
|
||||
static constexpr auto table_1 = R"(# DO NOT DO THIS
|
||||
|
||||
[fruit]
|
||||
apple = "red"
|
||||
|
||||
[fruit]
|
||||
orange = "orange")"sv;
|
||||
static constexpr auto table_2 = R"(# DO NOT DO THIS EITHER
|
||||
|
||||
[fruit]
|
||||
apple = "red"
|
||||
|
||||
[fruit.apple]
|
||||
texture = "smooth")"sv;
|
||||
static constexpr auto table_3 = R"([fruit]
|
||||
apple.color = "red"
|
||||
apple.taste.sweet = true
|
||||
|
||||
[fruit.apple] # INVALID)"sv;
|
||||
static constexpr auto table_4 = R"([fruit]
|
||||
apple.color = "red"
|
||||
apple.taste.sweet = true
|
||||
|
||||
[fruit.apple.taste] # INVALID)"sv;
|
||||
static constexpr auto table_invalid_1 = R"([fruit.physical] # subtable, but to which parent element should it belong?
|
||||
color = "red"
|
||||
shape = "round"
|
||||
|
||||
[[fruit]] # parser must throw an error upon discovering that "fruit" is
|
||||
# an array rather than a table
|
||||
name = "apple")"sv;
|
||||
static constexpr auto table_invalid_2 = R"(# INVALID TOML DOC
|
||||
fruit = []
|
||||
|
||||
[[fruit]] # Not allowed)"sv;
|
||||
static constexpr auto table_invalid_3 = R"(# INVALID TOML DOC
|
||||
[[fruit]]
|
||||
name = "apple"
|
||||
|
||||
[[fruit.variety]]
|
||||
name = "red delicious"
|
||||
|
||||
# INVALID: This table conflicts with the previous array of tables
|
||||
[fruit.variety]
|
||||
name = "granny smith"
|
||||
|
||||
[fruit.physical]
|
||||
color = "red"
|
||||
shape = "round")"sv;
|
||||
static constexpr auto table_invalid_4 = R"(# INVALID TOML DOC
|
||||
[[fruit]]
|
||||
name = "apple"
|
||||
|
||||
[[fruit.variety]]
|
||||
name = "red delicious"
|
||||
|
||||
[fruit.physical]
|
||||
color = "red"
|
||||
shape = "round"
|
||||
|
||||
# INVALID: This array of tables conflicts with the previous table
|
||||
[[fruit.physical]]
|
||||
color = "green")"sv;
|
||||
static constexpr auto table_1 = "# DO NOT DO THIS\r\n"
|
||||
"\r\n"
|
||||
"[fruit]\r\n"
|
||||
"apple = \"red\"\r\n"
|
||||
"\r\n"
|
||||
"[fruit]\r\n"
|
||||
"orange = \"orange\""sv;
|
||||
static constexpr auto table_2 = "# DO NOT DO THIS EITHER\r\n"
|
||||
"\r\n"
|
||||
"[fruit]\r\n"
|
||||
"apple = \"red\"\r\n"
|
||||
"\r\n"
|
||||
"[fruit.apple]\r\n"
|
||||
"texture = \"smooth\""sv;
|
||||
static constexpr auto table_3 = "[fruit]\r\n"
|
||||
"apple.color = \"red\"\r\n"
|
||||
"apple.taste.sweet = true\r\n"
|
||||
"\r\n"
|
||||
"[fruit.apple] # INVALID"sv;
|
||||
static constexpr auto table_4 = "[fruit]\r\n"
|
||||
"apple.color = \"red\"\r\n"
|
||||
"apple.taste.sweet = true\r\n"
|
||||
"\r\n"
|
||||
"[fruit.apple.taste] # INVALID"sv;
|
||||
static constexpr auto table_invalid_1 =
|
||||
"[fruit.physical] # subtable, but to which parent element should it belong?\r\n"
|
||||
" color = \"red\"\r\n"
|
||||
" shape = \"round\"\r\n"
|
||||
"\r\n"
|
||||
"[[fruit]] # parser must throw an error upon discovering that \"fruit\" is\r\n"
|
||||
" # an array rather than a table\r\n"
|
||||
" name = \"apple\""sv;
|
||||
static constexpr auto table_invalid_2 = "# INVALID TOML DOC\r\n"
|
||||
"fruit = []\r\n"
|
||||
"\r\n"
|
||||
"[[fruit]] # Not allowed"sv;
|
||||
static constexpr auto table_invalid_3 = "# INVALID TOML DOC\r\n"
|
||||
"[[fruit]]\r\n"
|
||||
" name = \"apple\"\r\n"
|
||||
"\r\n"
|
||||
" [[fruit.variety]]\r\n"
|
||||
" name = \"red delicious\"\r\n"
|
||||
"\r\n"
|
||||
" # INVALID: This table conflicts with the previous array of tables\r\n"
|
||||
" [fruit.variety]\r\n"
|
||||
" name = \"granny smith\"\r\n"
|
||||
"\r\n"
|
||||
" [fruit.physical]\r\n"
|
||||
" color = \"red\"\r\n"
|
||||
" shape = \"round\""sv;
|
||||
static constexpr auto table_invalid_4 = "# INVALID TOML DOC\r\n"
|
||||
"[[fruit]]\r\n"
|
||||
" name = \"apple\"\r\n"
|
||||
"\r\n"
|
||||
" [[fruit.variety]]\r\n"
|
||||
" name = \"red delicious\"\r\n"
|
||||
"\r\n"
|
||||
" [fruit.physical]\r\n"
|
||||
" color = \"red\"\r\n"
|
||||
" shape = \"round\"\r\n"
|
||||
"\r\n"
|
||||
" # INVALID: This array of tables conflicts with the previous table\r\n"
|
||||
" [[fruit.physical]]\r\n"
|
||||
" color = \"green\""sv;
|
||||
}
|
||||
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
TEST_CASE("conformance - iarna/invalid")
|
||||
{
|
||||
parsing_should_fail(FILE_LINE_ARGS, array_of_tables_1); // array-of-tables-1
|
||||
@ -158,6 +177,14 @@ TEST_CASE("conformance - iarna/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, bare_key_3); // bare-key-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, comment_control_1); // comment-control-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, comment_control_2); // comment-control-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, comment_control_3); // comment-control-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, comment_control_4); // comment-control-4
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_imutable_1); // inline-table-imutable-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, inline_table_imutable_2); // inline-table-imutable-2
|
||||
@ -186,22 +213,61 @@ TEST_CASE("conformance - iarna/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, no_key_name); // no-key-name
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_invalid_backslash); // string-basic-multiline-invalid-backslash
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_control_1); // string-basic-control-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_out_of_range_unicode_escape_1); // string-basic-multiline-out-of-range-unicode-escape-1
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_control_2); // string-basic-control-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_out_of_range_unicode_escape_2); // string-basic-multiline-out-of-range-unicode-escape-2
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_control_3); // string-basic-control-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_control_4); // string-basic-control-4
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_control_1); // string-basic-multiline-control-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_control_2); // string-basic-multiline-control-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_control_3); // string-basic-multiline-control-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_control_4); // string-basic-multiline-control-4
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS,
|
||||
string_basic_multiline_invalid_backslash); // string-basic-multiline-invalid-backslash
|
||||
|
||||
parsing_should_fail(
|
||||
FILE_LINE_ARGS,
|
||||
string_basic_multiline_out_of_range_unicode_escape_1); // string-basic-multiline-out-of-range-unicode-escape-1
|
||||
|
||||
parsing_should_fail(
|
||||
FILE_LINE_ARGS,
|
||||
string_basic_multiline_out_of_range_unicode_escape_2); // string-basic-multiline-out-of-range-unicode-escape-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_quotes); // string-basic-multiline-quotes
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_unknown_escape); // string-basic-multiline-unknown-escape
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_out_of_range_unicode_escape_1); // string-basic-out-of-range-unicode-escape-1
|
||||
parsing_should_fail(FILE_LINE_ARGS,
|
||||
string_basic_out_of_range_unicode_escape_1); // string-basic-out-of-range-unicode-escape-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_out_of_range_unicode_escape_2); // string-basic-out-of-range-unicode-escape-2
|
||||
parsing_should_fail(FILE_LINE_ARGS,
|
||||
string_basic_out_of_range_unicode_escape_2); // string-basic-out-of-range-unicode-escape-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_basic_unknown_escape); // string-basic-unknown-escape
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_control_1); // string-literal-control-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_control_2); // string-literal-control-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_control_3); // string-literal-control-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_control_4); // string-literal-control-4
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_multiline_control_1); // string-literal-multiline-control-1
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_multiline_control_2); // string-literal-multiline-control-2
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_multiline_control_3); // string-literal-multiline-control-3
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_multiline_control_4); // string-literal-multiline-control-4
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, string_literal_multiline_quotes); // string-literal-multiline-quotes
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_1); // table-1
|
||||
@ -220,4 +286,3 @@ TEST_CASE("conformance - iarna/invalid")
|
||||
|
||||
parsing_should_fail(FILE_LINE_ARGS, table_invalid_4); // table-invalid-4
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
332
tests/formatters.cpp
Normal file
332
tests/formatters.cpp
Normal file
@ -0,0 +1,332 @@
|
||||
// This file is a part of toml++ and is subject to the the terms of the MIT license.
|
||||
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Formatter, typename T>
|
||||
static auto format_to_string(const T& obj,
|
||||
format_flags flags = Formatter::default_flags,
|
||||
format_flags exclude_flags = format_flags::none)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "*****\n" << Formatter{ obj, flags & ~(exclude_flags) } << "\n*****";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
struct char32_printer
|
||||
{
|
||||
char32_t value;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const char32_printer& p)
|
||||
{
|
||||
if (p.value <= U'\x1F')
|
||||
return os << '\'' << impl::control_char_escapes[static_cast<size_t>(p.value)] << '\'';
|
||||
else if (p.value == U'\x7F')
|
||||
return os << "'\\u007F'"sv;
|
||||
else if (p.value < 127u)
|
||||
return os << '\'' << static_cast<char>(static_cast<uint8_t>(p.value)) << '\'';
|
||||
else
|
||||
return os << static_cast<uint_least32_t>(p.value);
|
||||
}
|
||||
};
|
||||
|
||||
struct string_difference
|
||||
{
|
||||
source_position position;
|
||||
size_t index;
|
||||
char32_t a, b;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const string_difference& diff)
|
||||
{
|
||||
if (diff.a && diff.b && diff.a != diff.b)
|
||||
os << char32_printer{ diff.a } << " vs "sv << char32_printer{ diff.b } << " at "sv;
|
||||
return os << diff.position << ", index "sv << diff.index;
|
||||
}
|
||||
};
|
||||
|
||||
static optional<string_difference> find_first_difference(std::string_view str_a, std::string_view str_b) noexcept
|
||||
{
|
||||
string_difference diff{ { 1u, 1u } };
|
||||
impl::utf8_decoder a, b;
|
||||
|
||||
for (size_t i = 0, e = std::min(str_a.length(), str_b.length()); i < e; i++, diff.index++)
|
||||
{
|
||||
a(static_cast<uint8_t>(str_a[i]));
|
||||
b(static_cast<uint8_t>(str_b[i]));
|
||||
if (a.has_code_point() != b.has_code_point() || a.error() != b.error())
|
||||
return diff;
|
||||
|
||||
if (a.error())
|
||||
{
|
||||
a.reset();
|
||||
b.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!a.has_code_point())
|
||||
continue;
|
||||
|
||||
if (a.codepoint != b.codepoint)
|
||||
{
|
||||
diff.a = a.codepoint;
|
||||
diff.b = b.codepoint;
|
||||
return diff;
|
||||
}
|
||||
|
||||
if (a.codepoint == U'\n')
|
||||
{
|
||||
diff.position.line++;
|
||||
diff.position.column = 1u;
|
||||
}
|
||||
else
|
||||
diff.position.column++;
|
||||
}
|
||||
if (str_a.length() != str_b.length())
|
||||
return diff;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK_FORMATTER(formatter, data, expected) \
|
||||
do \
|
||||
{ \
|
||||
const auto str = format_to_string<formatter>(data); \
|
||||
const auto diff = find_first_difference(str, expected); \
|
||||
if (diff) \
|
||||
FORCE_FAIL("string mismatch: "sv << *diff); \
|
||||
} \
|
||||
while (false)
|
||||
|
||||
TEST_CASE("formatters")
|
||||
{
|
||||
const auto data_date = toml::date{ 2021, 11, 2 };
|
||||
const auto data_time = toml::time{ 20, 33, 0 };
|
||||
const auto data = toml::table{
|
||||
{ "integers"sv,
|
||||
toml::table{ { "zero"sv, 0 },
|
||||
{ "one"sv, 1 },
|
||||
{ "dec"sv, 10 },
|
||||
{ "bin"sv, 10, toml::value_flags::format_as_binary },
|
||||
{ "oct"sv, 10, toml::value_flags::format_as_octal },
|
||||
{ "hex"sv, 10, toml::value_flags::format_as_hexadecimal } } },
|
||||
{ "floats"sv,
|
||||
toml::table{ { "pos_zero"sv, +0.0 },
|
||||
{ "neg_zero"sv, -0.0 },
|
||||
{ "one"sv, 1.0 },
|
||||
{ "pos_inf"sv, +std::numeric_limits<double>::infinity() },
|
||||
{ "neg_inf"sv, -std::numeric_limits<double>::infinity() },
|
||||
{ "pos_nan"sv, +std::numeric_limits<double>::quiet_NaN() },
|
||||
{ "neg_nan"sv, -std::numeric_limits<double>::quiet_NaN() }
|
||||
|
||||
} },
|
||||
|
||||
{ "dates and times"sv,
|
||||
toml::table{
|
||||
|
||||
{ "dates"sv, toml::table{ { "val"sv, data_date } } },
|
||||
|
||||
{ "times"sv, toml::table{ { "val"sv, data_time } } },
|
||||
|
||||
{ "date-times"sv,
|
||||
toml::table{
|
||||
|
||||
{ "local"sv, toml::table{ { "val"sv, toml::date_time{ data_date, data_time } } } },
|
||||
{ "offset"sv,
|
||||
toml::table{
|
||||
{ "val"sv, toml::date_time{ data_date, data_time, toml::time_offset{} } } } } } } } },
|
||||
|
||||
{ "bools"sv,
|
||||
toml::table{ { "true"sv, true }, //
|
||||
{ "false"sv, false } } },
|
||||
|
||||
{
|
||||
"strings"sv,
|
||||
toml::array{ R"()"sv,
|
||||
R"(string)"sv,
|
||||
R"(string with a single quote in it: ')"sv,
|
||||
R"(string with a double quote in it: ")"sv,
|
||||
"string with a tab: \t"sv,
|
||||
R"(a long string to force the array over multiple lines)"sv },
|
||||
},
|
||||
|
||||
{ "a"sv,
|
||||
toml::table{ { "val", true },
|
||||
{ "b"sv, toml::table{ { "val", true }, { "c"sv, toml::table{ { "val", true } } } } } } }
|
||||
|
||||
};
|
||||
|
||||
SECTION("toml_formatter")
|
||||
{
|
||||
static constexpr auto expected = R"(*****
|
||||
strings = [
|
||||
'',
|
||||
'string',
|
||||
"string with a single quote in it: '",
|
||||
'string with a double quote in it: "',
|
||||
'string with a tab: ',
|
||||
'a long string to force the array over multiple lines'
|
||||
]
|
||||
|
||||
[a]
|
||||
val = true
|
||||
|
||||
[a.b]
|
||||
val = true
|
||||
|
||||
[a.b.c]
|
||||
val = true
|
||||
|
||||
[bools]
|
||||
false = false
|
||||
true = true
|
||||
|
||||
['dates and times'.date-times.local]
|
||||
val = 2021-11-02T20:33:00
|
||||
|
||||
['dates and times'.date-times.offset]
|
||||
val = 2021-11-02T20:33:00Z
|
||||
|
||||
['dates and times'.dates]
|
||||
val = 2021-11-02
|
||||
|
||||
['dates and times'.times]
|
||||
val = 20:33:00
|
||||
|
||||
[floats]
|
||||
neg_inf = -inf
|
||||
neg_nan = nan
|
||||
neg_zero = -0.0
|
||||
one = 1.0
|
||||
pos_inf = inf
|
||||
pos_nan = nan
|
||||
pos_zero = 0.0
|
||||
|
||||
[integers]
|
||||
bin = 0b1010
|
||||
dec = 10
|
||||
hex = 0xA
|
||||
oct = 0o12
|
||||
one = 1
|
||||
zero = 0
|
||||
*****)"sv;
|
||||
|
||||
CHECK_FORMATTER(toml_formatter, data, expected);
|
||||
}
|
||||
|
||||
SECTION("json_formatter")
|
||||
{
|
||||
static constexpr auto expected = R"(*****
|
||||
{
|
||||
"a" : {
|
||||
"b" : {
|
||||
"c" : {
|
||||
"val" : true
|
||||
},
|
||||
"val" : true
|
||||
},
|
||||
"val" : true
|
||||
},
|
||||
"bools" : {
|
||||
"false" : false,
|
||||
"true" : true
|
||||
},
|
||||
"dates and times" : {
|
||||
"date-times" : {
|
||||
"local" : {
|
||||
"val" : "2021-11-02T20:33:00"
|
||||
},
|
||||
"offset" : {
|
||||
"val" : "2021-11-02T20:33:00Z"
|
||||
}
|
||||
},
|
||||
"dates" : {
|
||||
"val" : "2021-11-02"
|
||||
},
|
||||
"times" : {
|
||||
"val" : "20:33:00"
|
||||
}
|
||||
},
|
||||
"floats" : {
|
||||
"neg_inf" : "-Infinity",
|
||||
"neg_nan" : "NaN",
|
||||
"neg_zero" : -0.0,
|
||||
"one" : 1.0,
|
||||
"pos_inf" : "Infinity",
|
||||
"pos_nan" : "NaN",
|
||||
"pos_zero" : 0.0
|
||||
},
|
||||
"integers" : {
|
||||
"bin" : 10,
|
||||
"dec" : 10,
|
||||
"hex" : 10,
|
||||
"oct" : 10,
|
||||
"one" : 1,
|
||||
"zero" : 0
|
||||
},
|
||||
"strings" : [
|
||||
"",
|
||||
"string",
|
||||
"string with a single quote in it: '",
|
||||
"string with a double quote in it: \"",
|
||||
"string with a tab: \t",
|
||||
"a long string to force the array over multiple lines"
|
||||
]
|
||||
}
|
||||
*****)"sv;
|
||||
|
||||
CHECK_FORMATTER(json_formatter, data, expected);
|
||||
}
|
||||
|
||||
SECTION("yaml_formatter")
|
||||
{
|
||||
static constexpr auto expected = R"(*****
|
||||
a:
|
||||
b:
|
||||
c:
|
||||
val: true
|
||||
val: true
|
||||
val: true
|
||||
bools:
|
||||
false: false
|
||||
true: true
|
||||
'dates and times':
|
||||
date-times:
|
||||
local:
|
||||
val: '2021-11-02T20:33:00'
|
||||
offset:
|
||||
val: '2021-11-02T20:33:00Z'
|
||||
dates:
|
||||
val: '2021-11-02'
|
||||
times:
|
||||
val: '20:33:00'
|
||||
floats:
|
||||
neg_inf: -.inf
|
||||
neg_nan: .NAN
|
||||
neg_zero: -0.0
|
||||
one: 1.0
|
||||
pos_inf: .inf
|
||||
pos_nan: .NAN
|
||||
pos_zero: 0.0
|
||||
integers:
|
||||
bin: 10
|
||||
dec: 10
|
||||
hex: 0xA
|
||||
oct: 0o12
|
||||
one: 1
|
||||
zero: 0
|
||||
strings:
|
||||
- ''
|
||||
- string
|
||||
- "string with a single quote in it: '"
|
||||
- 'string with a double quote in it: "'
|
||||
- "string with a tab: \t"
|
||||
- 'a long string to force the array over multiple lines'
|
||||
*****)"sv;
|
||||
|
||||
CHECK_FORMATTER(yaml_formatter, data, expected);
|
||||
}
|
||||
}
|
@ -5,17 +5,17 @@
|
||||
|
||||
#include "settings.h"
|
||||
#if !TOML_HEADER_ONLY
|
||||
#define TOML_IMPLEMENTATION
|
||||
#define TOML_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#if USE_TARTANLLAMA_OPTIONAL
|
||||
#include "tloptional.h"
|
||||
#include "lib_tloptional.h"
|
||||
#endif
|
||||
|
||||
#if USE_SINGLE_HEADER
|
||||
#include "../toml.hpp"
|
||||
#include "../toml.hpp"
|
||||
#else
|
||||
#include "../include/toml++/toml.h"
|
||||
#include "../include/toml++/toml.h"
|
||||
#endif
|
||||
|
||||
namespace toml
|
||||
@ -23,306 +23,395 @@ namespace toml
|
||||
using std::declval;
|
||||
using std::is_same_v;
|
||||
|
||||
#define CHECK_NODE_TYPE_MAPPING(T, expected) \
|
||||
static_assert(impl::node_type_of<T> == expected); \
|
||||
static_assert(impl::node_type_of<T&> == expected); \
|
||||
static_assert(impl::node_type_of<T&&> == expected); \
|
||||
static_assert(impl::node_type_of<const T> == expected); \
|
||||
static_assert(impl::node_type_of<const T&> == expected); \
|
||||
static_assert(impl::node_type_of<const T&&> == expected); \
|
||||
static_assert(impl::node_type_of<volatile T> == expected); \
|
||||
static_assert(impl::node_type_of<volatile T&> == expected); \
|
||||
static_assert(impl::node_type_of<volatile T&&> == expected); \
|
||||
static_assert(impl::node_type_of<const volatile T> == expected); \
|
||||
static_assert(impl::node_type_of<const volatile T&> == expected); \
|
||||
static_assert(impl::node_type_of<const volatile T&&> == expected)
|
||||
#define CHECK_NODE_TYPE_MAPPING(T, expected) \
|
||||
static_assert(impl::node_type_of<T> == expected); \
|
||||
static_assert(impl::node_type_of<T&> == expected); \
|
||||
static_assert(impl::node_type_of<T&&> == expected); \
|
||||
static_assert(impl::node_type_of<const T> == expected); \
|
||||
static_assert(impl::node_type_of<const T&> == expected); \
|
||||
static_assert(impl::node_type_of<const T&&> == expected); \
|
||||
static_assert(impl::node_type_of<volatile T> == expected); \
|
||||
static_assert(impl::node_type_of<volatile T&> == expected); \
|
||||
static_assert(impl::node_type_of<volatile T&&> == expected); \
|
||||
static_assert(impl::node_type_of<const volatile T> == expected); \
|
||||
static_assert(impl::node_type_of<const volatile T&> == expected); \
|
||||
static_assert(impl::node_type_of<const volatile T&&> == expected)
|
||||
|
||||
CHECK_NODE_TYPE_MAPPING(int64_t, node_type::integer);
|
||||
CHECK_NODE_TYPE_MAPPING(double, node_type::floating_point);
|
||||
CHECK_NODE_TYPE_MAPPING(std::string, node_type::string);
|
||||
CHECK_NODE_TYPE_MAPPING(bool, node_type::boolean);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::date, node_type::date);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::time, node_type::time);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::date_time, node_type::date_time);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::array, node_type::array);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::table, node_type::table);
|
||||
CHECK_NODE_TYPE_MAPPING(int64_t, node_type::integer);
|
||||
CHECK_NODE_TYPE_MAPPING(double, node_type::floating_point);
|
||||
CHECK_NODE_TYPE_MAPPING(std::string, node_type::string);
|
||||
CHECK_NODE_TYPE_MAPPING(bool, node_type::boolean);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::date, node_type::date);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::time, node_type::time);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::date_time, node_type::date_time);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::array, node_type::array);
|
||||
CHECK_NODE_TYPE_MAPPING(toml::table, node_type::table);
|
||||
|
||||
#define CHECK_CAN_REPRESENT_NATIVE(T, expected) \
|
||||
static_assert((impl::value_traits<T>::is_native || impl::value_traits<T>::can_represent_native) == expected)
|
||||
|
||||
#define CHECK_CAN_REPRESENT_NATIVE(T, expected) \
|
||||
static_assert((impl::value_traits<T>::is_native || impl::value_traits<T>::can_represent_native) == expected)
|
||||
|
||||
CHECK_CAN_REPRESENT_NATIVE(time, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(date, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(date_time, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(bool, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(int8_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(int16_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(int32_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(int64_t, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(uint8_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(uint16_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(uint32_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(uint64_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(float, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(double, true);
|
||||
#ifdef TOML_INT128
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_INT128, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_UINT128, false);
|
||||
#endif
|
||||
#ifdef TOML_FP16
|
||||
CHECK_CAN_REPRESENT_NATIVE(time, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(date, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(date_time, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(bool, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(int8_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(int16_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(int32_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(int64_t, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(uint8_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(uint16_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(uint32_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(uint64_t, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(float, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(double, true);
|
||||
#ifdef TOML_INT128
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_INT128, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_UINT128, false);
|
||||
#endif
|
||||
#ifdef TOML_FP16
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_FP16, false);
|
||||
#endif
|
||||
#ifdef TOML_FLOAT16
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT16, false);
|
||||
#endif
|
||||
#ifdef TOML_FLOAT128
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT128, true);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef TOML_FLOAT16
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT16, false);
|
||||
#endif
|
||||
#ifdef TOML_FLOAT128
|
||||
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT128, true);
|
||||
#endif
|
||||
|
||||
CHECK_CAN_REPRESENT_NATIVE(char*, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char*const, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char(&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char(&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char*, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char*const, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::string, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::string_view, true);
|
||||
#if TOML_HAS_CHAR8
|
||||
CHECK_CAN_REPRESENT_NATIVE(char8_t*, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char8_t*const, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char8_t[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char8_t(&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t(&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t*, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t*const, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::u8string, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::u8string_view, true);
|
||||
#endif
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t*, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t*const, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t(&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t(&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t*, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t*const, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::wstring, !!TOML_WINDOWS_COMPAT);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::wstring_view, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char*, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char* const, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char (&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char (&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char*, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char* const, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::string, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::string_view, true);
|
||||
#if TOML_HAS_CHAR8
|
||||
CHECK_CAN_REPRESENT_NATIVE(char8_t*, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char8_t* const, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char8_t[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char8_t (&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t (&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t*, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const char8_t* const, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::u8string, true);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::u8string_view, true);
|
||||
#endif
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t*, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t* const, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t (&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t (&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(wchar_t(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t(&&)[2], false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t*, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(const wchar_t* const, false);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::wstring, !!TOML_ENABLE_WINDOWS_COMPAT);
|
||||
CHECK_CAN_REPRESENT_NATIVE(std::wstring_view, false);
|
||||
|
||||
#define CHECK_VALUE_EXACT(T, expected) \
|
||||
static_assert(is_same_v<decltype(declval<node>().value_exact<T>()), optional<expected>>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().value_exact<T>()), optional<expected>>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().value_exact<T>()), optional<expected>>)
|
||||
#define CHECK_VALUE_EXACT(T, expected) \
|
||||
static_assert(is_same_v<decltype(declval<node>().value_exact<T>()), optional<expected>>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().value_exact<T>()), optional<expected>>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().value_exact<T>()), optional<expected>>)
|
||||
|
||||
#define CHECK_VALUE_OR(T, expected) \
|
||||
static_assert(is_same_v<decltype(declval<node>().value_or(declval<T>())), expected>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().value_or(declval<T>())), expected>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().value_or(declval<T>())), expected>)
|
||||
#define CHECK_VALUE_OR(T, expected) \
|
||||
static_assert(is_same_v<decltype(declval<node>().value_or(declval<T>())), expected>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().value_or(declval<T>())), expected>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().value_or(declval<T>())), expected>)
|
||||
|
||||
CHECK_VALUE_EXACT( time, time);
|
||||
CHECK_VALUE_EXACT( date, date);
|
||||
CHECK_VALUE_EXACT( date_time, date_time);
|
||||
CHECK_VALUE_EXACT( bool, bool);
|
||||
CHECK_VALUE_EXACT( double, double);
|
||||
CHECK_VALUE_EXACT( int64_t, int64_t);
|
||||
CHECK_VALUE_EXACT( const char*, const char*);
|
||||
CHECK_VALUE_EXACT( std::string_view, std::string_view);
|
||||
CHECK_VALUE_EXACT( std::string, std::string);
|
||||
#if TOML_HAS_CHAR8
|
||||
CHECK_VALUE_EXACT( const char8_t*, const char8_t*);
|
||||
CHECK_VALUE_EXACT( std::u8string_view, std::u8string_view);
|
||||
CHECK_VALUE_EXACT( std::u8string, std::u8string);
|
||||
#endif
|
||||
CHECK_VALUE_EXACT(time, time);
|
||||
CHECK_VALUE_EXACT(date, date);
|
||||
CHECK_VALUE_EXACT(date_time, date_time);
|
||||
CHECK_VALUE_EXACT(bool, bool);
|
||||
CHECK_VALUE_EXACT(double, double);
|
||||
CHECK_VALUE_EXACT(int64_t, int64_t);
|
||||
CHECK_VALUE_EXACT(const char*, const char*);
|
||||
CHECK_VALUE_EXACT(std::string_view, std::string_view);
|
||||
CHECK_VALUE_EXACT(std::string, std::string);
|
||||
#if TOML_HAS_CHAR8
|
||||
CHECK_VALUE_EXACT(const char8_t*, const char8_t*);
|
||||
CHECK_VALUE_EXACT(std::u8string_view, std::u8string_view);
|
||||
CHECK_VALUE_EXACT(std::u8string, std::u8string);
|
||||
#endif
|
||||
|
||||
CHECK_VALUE_OR( time, time);
|
||||
CHECK_VALUE_OR( time&, time);
|
||||
CHECK_VALUE_OR( time&&, time);
|
||||
CHECK_VALUE_OR( time const, time);
|
||||
CHECK_VALUE_OR( date, date);
|
||||
CHECK_VALUE_OR( date&, date);
|
||||
CHECK_VALUE_OR( date&&, date);
|
||||
CHECK_VALUE_OR( date const, date);
|
||||
CHECK_VALUE_OR( date_time, date_time);
|
||||
CHECK_VALUE_OR( date_time&, date_time);
|
||||
CHECK_VALUE_OR( date_time&&, date_time);
|
||||
CHECK_VALUE_OR( date_time const, date_time);
|
||||
CHECK_VALUE_OR( bool, bool);
|
||||
CHECK_VALUE_OR( bool&, bool);
|
||||
CHECK_VALUE_OR( bool&&, bool);
|
||||
CHECK_VALUE_OR( bool const, bool);
|
||||
CHECK_VALUE_OR( int32_t, int32_t);
|
||||
CHECK_VALUE_OR( int32_t&, int32_t);
|
||||
CHECK_VALUE_OR( int32_t&&, int32_t);
|
||||
CHECK_VALUE_OR( int32_t const, int32_t);
|
||||
CHECK_VALUE_OR( int64_t, int64_t);
|
||||
CHECK_VALUE_OR( int64_t&, int64_t);
|
||||
CHECK_VALUE_OR( int64_t&&, int64_t);
|
||||
CHECK_VALUE_OR( int64_t const, int64_t);
|
||||
#ifdef TOML_INT128
|
||||
CHECK_VALUE_OR( TOML_INT128, TOML_INT128);
|
||||
CHECK_VALUE_OR( TOML_INT128&, TOML_INT128);
|
||||
CHECK_VALUE_OR( TOML_INT128&&, TOML_INT128);
|
||||
CHECK_VALUE_OR( TOML_INT128 const, TOML_INT128);
|
||||
CHECK_VALUE_OR( TOML_UINT128, TOML_UINT128);
|
||||
CHECK_VALUE_OR( TOML_UINT128&, TOML_UINT128);
|
||||
CHECK_VALUE_OR( TOML_UINT128&&, TOML_UINT128);
|
||||
CHECK_VALUE_OR( TOML_UINT128 const, TOML_UINT128);
|
||||
#endif
|
||||
CHECK_VALUE_OR( float, float);
|
||||
CHECK_VALUE_OR( float&, float);
|
||||
CHECK_VALUE_OR( float&&, float);
|
||||
CHECK_VALUE_OR( float const, float);
|
||||
CHECK_VALUE_OR( double, double);
|
||||
CHECK_VALUE_OR( double&, double);
|
||||
CHECK_VALUE_OR( double&&, double);
|
||||
CHECK_VALUE_OR( double const, double);
|
||||
#ifdef TOML_FLOAT128
|
||||
CHECK_VALUE_OR( TOML_FLOAT128, TOML_FLOAT128);
|
||||
CHECK_VALUE_OR( TOML_FLOAT128&, TOML_FLOAT128);
|
||||
CHECK_VALUE_OR( TOML_FLOAT128&&, TOML_FLOAT128);
|
||||
CHECK_VALUE_OR( TOML_FLOAT128 const, TOML_FLOAT128);
|
||||
#endif
|
||||
CHECK_VALUE_OR( char*, const char*);
|
||||
CHECK_VALUE_OR( char*&, const char*);
|
||||
CHECK_VALUE_OR( char*&&, const char*);
|
||||
CHECK_VALUE_OR( char*const, const char*);
|
||||
CHECK_VALUE_OR( char[2], const char*);
|
||||
CHECK_VALUE_OR( char(&)[2], const char*);
|
||||
CHECK_VALUE_OR( char(&&)[2], const char*);
|
||||
CHECK_VALUE_OR( const char*, const char*);
|
||||
CHECK_VALUE_OR( const char*&, const char*);
|
||||
CHECK_VALUE_OR( const char*&&, const char*);
|
||||
CHECK_VALUE_OR( const char*const, const char*);
|
||||
CHECK_VALUE_OR( const char[2], const char*);
|
||||
CHECK_VALUE_OR( const char(&)[2], const char*);
|
||||
CHECK_VALUE_OR( const char(&&)[2], const char*);
|
||||
CHECK_VALUE_OR( std::string_view, std::string_view);
|
||||
CHECK_VALUE_OR( std::string_view&, std::string_view);
|
||||
CHECK_VALUE_OR( std::string_view&&, std::string_view);
|
||||
CHECK_VALUE_OR( const std::string_view, std::string_view);
|
||||
CHECK_VALUE_OR( const std::string_view&, std::string_view);
|
||||
CHECK_VALUE_OR( const std::string_view&&, std::string_view);
|
||||
CHECK_VALUE_OR( std::string, std::string);
|
||||
CHECK_VALUE_OR( std::string&, std::string);
|
||||
CHECK_VALUE_OR( std::string&&, std::string);
|
||||
CHECK_VALUE_OR( const std::string, std::string);
|
||||
CHECK_VALUE_OR( const std::string&, std::string);
|
||||
CHECK_VALUE_OR( const std::string&&, std::string);
|
||||
#if TOML_HAS_CHAR8
|
||||
CHECK_VALUE_OR( char8_t*, const char8_t*);
|
||||
CHECK_VALUE_OR( char8_t*&, const char8_t*);
|
||||
CHECK_VALUE_OR( char8_t*&&, const char8_t*);
|
||||
CHECK_VALUE_OR( char8_t*const, const char8_t*);
|
||||
CHECK_VALUE_OR( char8_t[2], const char8_t*);
|
||||
CHECK_VALUE_OR( char8_t(&)[2], const char8_t*);
|
||||
CHECK_VALUE_OR( char8_t(&&)[2], const char8_t*);
|
||||
CHECK_VALUE_OR( const char8_t*, const char8_t*);
|
||||
CHECK_VALUE_OR( const char8_t*&, const char8_t*);
|
||||
CHECK_VALUE_OR( const char8_t*&&, const char8_t*);
|
||||
CHECK_VALUE_OR( const char8_t*const, const char8_t*);
|
||||
CHECK_VALUE_OR( const char8_t[2], const char8_t*);
|
||||
CHECK_VALUE_OR( const char8_t(&)[2], const char8_t*);
|
||||
CHECK_VALUE_OR( const char8_t(&&)[2], const char8_t*);
|
||||
CHECK_VALUE_OR( std::u8string_view, std::u8string_view);
|
||||
CHECK_VALUE_OR( std::u8string_view&, std::u8string_view);
|
||||
CHECK_VALUE_OR( std::u8string_view&&, std::u8string_view);
|
||||
CHECK_VALUE_OR( const std::u8string_view, std::u8string_view);
|
||||
CHECK_VALUE_OR( const std::u8string_view&, std::u8string_view);
|
||||
CHECK_VALUE_OR( const std::u8string_view&&, std::u8string_view);
|
||||
CHECK_VALUE_OR( std::u8string, std::u8string);
|
||||
CHECK_VALUE_OR( std::u8string&, std::u8string);
|
||||
CHECK_VALUE_OR( std::u8string&&, std::u8string);
|
||||
CHECK_VALUE_OR( const std::u8string, std::u8string);
|
||||
CHECK_VALUE_OR( const std::u8string&, std::u8string);
|
||||
CHECK_VALUE_OR( const std::u8string&&, std::u8string);
|
||||
#endif
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
CHECK_VALUE_OR( wchar_t*, std::wstring);
|
||||
CHECK_VALUE_OR( wchar_t*&, std::wstring);
|
||||
CHECK_VALUE_OR( wchar_t*&&, std::wstring);
|
||||
CHECK_VALUE_OR( wchar_t*const, std::wstring);
|
||||
CHECK_VALUE_OR( wchar_t[2], std::wstring);
|
||||
CHECK_VALUE_OR( wchar_t(&)[2], std::wstring);
|
||||
CHECK_VALUE_OR( wchar_t(&&)[2], std::wstring);
|
||||
CHECK_VALUE_OR( const wchar_t*, std::wstring);
|
||||
CHECK_VALUE_OR( const wchar_t*&, std::wstring);
|
||||
CHECK_VALUE_OR( const wchar_t*&&, std::wstring);
|
||||
CHECK_VALUE_OR( const wchar_t*const, std::wstring);
|
||||
CHECK_VALUE_OR( const wchar_t[2], std::wstring);
|
||||
CHECK_VALUE_OR( const wchar_t(&)[2], std::wstring);
|
||||
CHECK_VALUE_OR( const wchar_t(&&)[2], std::wstring);
|
||||
CHECK_VALUE_OR( std::wstring_view, std::wstring);
|
||||
CHECK_VALUE_OR( std::wstring_view&, std::wstring);
|
||||
CHECK_VALUE_OR( std::wstring_view&&, std::wstring);
|
||||
CHECK_VALUE_OR( const std::wstring_view, std::wstring);
|
||||
CHECK_VALUE_OR( const std::wstring_view&, std::wstring);
|
||||
CHECK_VALUE_OR( const std::wstring_view&&, std::wstring);
|
||||
CHECK_VALUE_OR( std::wstring, std::wstring);
|
||||
CHECK_VALUE_OR( std::wstring&, std::wstring);
|
||||
CHECK_VALUE_OR( std::wstring&&, std::wstring);
|
||||
CHECK_VALUE_OR( const std::wstring, std::wstring);
|
||||
CHECK_VALUE_OR( const std::wstring&, std::wstring);
|
||||
CHECK_VALUE_OR( const std::wstring&&, std::wstring);
|
||||
#endif
|
||||
CHECK_VALUE_OR(time, time);
|
||||
CHECK_VALUE_OR(time&, time);
|
||||
CHECK_VALUE_OR(time&&, time);
|
||||
CHECK_VALUE_OR(time const, time);
|
||||
CHECK_VALUE_OR(date, date);
|
||||
CHECK_VALUE_OR(date&, date);
|
||||
CHECK_VALUE_OR(date&&, date);
|
||||
CHECK_VALUE_OR(date const, date);
|
||||
CHECK_VALUE_OR(date_time, date_time);
|
||||
CHECK_VALUE_OR(date_time&, date_time);
|
||||
CHECK_VALUE_OR(date_time&&, date_time);
|
||||
CHECK_VALUE_OR(date_time const, date_time);
|
||||
CHECK_VALUE_OR(bool, bool);
|
||||
CHECK_VALUE_OR(bool&, bool);
|
||||
CHECK_VALUE_OR(bool&&, bool);
|
||||
CHECK_VALUE_OR(bool const, bool);
|
||||
CHECK_VALUE_OR(int32_t, int32_t);
|
||||
CHECK_VALUE_OR(int32_t&, int32_t);
|
||||
CHECK_VALUE_OR(int32_t&&, int32_t);
|
||||
CHECK_VALUE_OR(int32_t const, int32_t);
|
||||
CHECK_VALUE_OR(int64_t, int64_t);
|
||||
CHECK_VALUE_OR(int64_t&, int64_t);
|
||||
CHECK_VALUE_OR(int64_t&&, int64_t);
|
||||
CHECK_VALUE_OR(int64_t const, int64_t);
|
||||
#ifdef TOML_INT128
|
||||
CHECK_VALUE_OR(TOML_INT128, TOML_INT128);
|
||||
CHECK_VALUE_OR(TOML_INT128&, TOML_INT128);
|
||||
CHECK_VALUE_OR(TOML_INT128&&, TOML_INT128);
|
||||
CHECK_VALUE_OR(TOML_INT128 const, TOML_INT128);
|
||||
CHECK_VALUE_OR(TOML_UINT128, TOML_UINT128);
|
||||
CHECK_VALUE_OR(TOML_UINT128&, TOML_UINT128);
|
||||
CHECK_VALUE_OR(TOML_UINT128&&, TOML_UINT128);
|
||||
CHECK_VALUE_OR(TOML_UINT128 const, TOML_UINT128);
|
||||
#endif
|
||||
CHECK_VALUE_OR(float, float);
|
||||
CHECK_VALUE_OR(float&, float);
|
||||
CHECK_VALUE_OR(float&&, float);
|
||||
CHECK_VALUE_OR(float const, float);
|
||||
CHECK_VALUE_OR(double, double);
|
||||
CHECK_VALUE_OR(double&, double);
|
||||
CHECK_VALUE_OR(double&&, double);
|
||||
CHECK_VALUE_OR(double const, double);
|
||||
#ifdef TOML_FLOAT128
|
||||
CHECK_VALUE_OR(TOML_FLOAT128, TOML_FLOAT128);
|
||||
CHECK_VALUE_OR(TOML_FLOAT128&, TOML_FLOAT128);
|
||||
CHECK_VALUE_OR(TOML_FLOAT128&&, TOML_FLOAT128);
|
||||
CHECK_VALUE_OR(TOML_FLOAT128 const, TOML_FLOAT128);
|
||||
#endif
|
||||
CHECK_VALUE_OR(char*, const char*);
|
||||
CHECK_VALUE_OR(char*&, const char*);
|
||||
CHECK_VALUE_OR(char*&&, const char*);
|
||||
CHECK_VALUE_OR(char* const, const char*);
|
||||
CHECK_VALUE_OR(char[2], const char*);
|
||||
CHECK_VALUE_OR(char (&)[2], const char*);
|
||||
CHECK_VALUE_OR(char(&&)[2], const char*);
|
||||
CHECK_VALUE_OR(const char*, const char*);
|
||||
CHECK_VALUE_OR(const char*&, const char*);
|
||||
CHECK_VALUE_OR(const char*&&, const char*);
|
||||
CHECK_VALUE_OR(const char* const, const char*);
|
||||
CHECK_VALUE_OR(const char[2], const char*);
|
||||
CHECK_VALUE_OR(const char (&)[2], const char*);
|
||||
CHECK_VALUE_OR(const char(&&)[2], const char*);
|
||||
CHECK_VALUE_OR(std::string_view, std::string_view);
|
||||
CHECK_VALUE_OR(std::string_view&, std::string_view);
|
||||
CHECK_VALUE_OR(std::string_view&&, std::string_view);
|
||||
CHECK_VALUE_OR(const std::string_view, std::string_view);
|
||||
CHECK_VALUE_OR(const std::string_view&, std::string_view);
|
||||
CHECK_VALUE_OR(const std::string_view&&, std::string_view);
|
||||
CHECK_VALUE_OR(std::string, std::string);
|
||||
CHECK_VALUE_OR(std::string&, std::string);
|
||||
CHECK_VALUE_OR(std::string&&, std::string);
|
||||
CHECK_VALUE_OR(const std::string, std::string);
|
||||
CHECK_VALUE_OR(const std::string&, std::string);
|
||||
CHECK_VALUE_OR(const std::string&&, std::string);
|
||||
#if TOML_HAS_CHAR8
|
||||
CHECK_VALUE_OR(char8_t*, const char8_t*);
|
||||
CHECK_VALUE_OR(char8_t*&, const char8_t*);
|
||||
CHECK_VALUE_OR(char8_t*&&, const char8_t*);
|
||||
CHECK_VALUE_OR(char8_t* const, const char8_t*);
|
||||
CHECK_VALUE_OR(char8_t[2], const char8_t*);
|
||||
CHECK_VALUE_OR(char8_t (&)[2], const char8_t*);
|
||||
CHECK_VALUE_OR(char8_t(&&)[2], const char8_t*);
|
||||
CHECK_VALUE_OR(const char8_t*, const char8_t*);
|
||||
CHECK_VALUE_OR(const char8_t*&, const char8_t*);
|
||||
CHECK_VALUE_OR(const char8_t*&&, const char8_t*);
|
||||
CHECK_VALUE_OR(const char8_t* const, const char8_t*);
|
||||
CHECK_VALUE_OR(const char8_t[2], const char8_t*);
|
||||
CHECK_VALUE_OR(const char8_t (&)[2], const char8_t*);
|
||||
CHECK_VALUE_OR(const char8_t(&&)[2], const char8_t*);
|
||||
CHECK_VALUE_OR(std::u8string_view, std::u8string_view);
|
||||
CHECK_VALUE_OR(std::u8string_view&, std::u8string_view);
|
||||
CHECK_VALUE_OR(std::u8string_view&&, std::u8string_view);
|
||||
CHECK_VALUE_OR(const std::u8string_view, std::u8string_view);
|
||||
CHECK_VALUE_OR(const std::u8string_view&, std::u8string_view);
|
||||
CHECK_VALUE_OR(const std::u8string_view&&, std::u8string_view);
|
||||
CHECK_VALUE_OR(std::u8string, std::u8string);
|
||||
CHECK_VALUE_OR(std::u8string&, std::u8string);
|
||||
CHECK_VALUE_OR(std::u8string&&, std::u8string);
|
||||
CHECK_VALUE_OR(const std::u8string, std::u8string);
|
||||
CHECK_VALUE_OR(const std::u8string&, std::u8string);
|
||||
CHECK_VALUE_OR(const std::u8string&&, std::u8string);
|
||||
#endif
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
CHECK_VALUE_OR(wchar_t*, std::wstring);
|
||||
CHECK_VALUE_OR(wchar_t*&, std::wstring);
|
||||
CHECK_VALUE_OR(wchar_t*&&, std::wstring);
|
||||
CHECK_VALUE_OR(wchar_t* const, std::wstring);
|
||||
CHECK_VALUE_OR(wchar_t[2], std::wstring);
|
||||
CHECK_VALUE_OR(wchar_t (&)[2], std::wstring);
|
||||
CHECK_VALUE_OR(wchar_t(&&)[2], std::wstring);
|
||||
CHECK_VALUE_OR(const wchar_t*, std::wstring);
|
||||
CHECK_VALUE_OR(const wchar_t*&, std::wstring);
|
||||
CHECK_VALUE_OR(const wchar_t*&&, std::wstring);
|
||||
CHECK_VALUE_OR(const wchar_t* const, std::wstring);
|
||||
CHECK_VALUE_OR(const wchar_t[2], std::wstring);
|
||||
CHECK_VALUE_OR(const wchar_t (&)[2], std::wstring);
|
||||
CHECK_VALUE_OR(const wchar_t(&&)[2], std::wstring);
|
||||
CHECK_VALUE_OR(std::wstring_view, std::wstring);
|
||||
CHECK_VALUE_OR(std::wstring_view&, std::wstring);
|
||||
CHECK_VALUE_OR(std::wstring_view&&, std::wstring);
|
||||
CHECK_VALUE_OR(const std::wstring_view, std::wstring);
|
||||
CHECK_VALUE_OR(const std::wstring_view&, std::wstring);
|
||||
CHECK_VALUE_OR(const std::wstring_view&&, std::wstring);
|
||||
CHECK_VALUE_OR(std::wstring, std::wstring);
|
||||
CHECK_VALUE_OR(std::wstring&, std::wstring);
|
||||
CHECK_VALUE_OR(std::wstring&&, std::wstring);
|
||||
CHECK_VALUE_OR(const std::wstring, std::wstring);
|
||||
CHECK_VALUE_OR(const std::wstring&, std::wstring);
|
||||
CHECK_VALUE_OR(const std::wstring&&, std::wstring);
|
||||
#endif
|
||||
|
||||
#define CHECK_INSERTED_AS(T, expected) \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<T>>); \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<const T>>); \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<T&>>); \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<const T&>>); \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<T&&>>)
|
||||
#define CHECK_INSERTED_AS(T, expected) \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<T>>); \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<const T>>); \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<T&>>); \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<const T&>>); \
|
||||
static_assert(std::is_same_v<expected, toml::inserted_type_of<T&&>>)
|
||||
|
||||
CHECK_INSERTED_AS(table, table);
|
||||
CHECK_INSERTED_AS(array, array);
|
||||
CHECK_INSERTED_AS(node, node);
|
||||
CHECK_INSERTED_AS(time, value<time>);
|
||||
CHECK_INSERTED_AS(date, value<date>);
|
||||
CHECK_INSERTED_AS(date_time, value<date_time>);
|
||||
CHECK_INSERTED_AS(bool, value<bool>);
|
||||
CHECK_INSERTED_AS(int8_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(int16_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(int32_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(int64_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(uint8_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(uint16_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(uint32_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(float, value<double>);
|
||||
CHECK_INSERTED_AS(double, value<double>);
|
||||
#ifdef TOML_FP16
|
||||
CHECK_INSERTED_AS(TOML_FP16, value<double>);
|
||||
#endif
|
||||
#ifdef TOML_FLOAT16
|
||||
CHECK_INSERTED_AS(TOML_FLOAT16, value<double>);
|
||||
#endif
|
||||
CHECK_INSERTED_AS(table, table);
|
||||
CHECK_INSERTED_AS(array, array);
|
||||
CHECK_INSERTED_AS(node, node);
|
||||
CHECK_INSERTED_AS(time, value<time>);
|
||||
CHECK_INSERTED_AS(date, value<date>);
|
||||
CHECK_INSERTED_AS(date_time, value<date_time>);
|
||||
CHECK_INSERTED_AS(bool, value<bool>);
|
||||
CHECK_INSERTED_AS(int8_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(int16_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(int32_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(int64_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(uint8_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(uint16_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(uint32_t, value<int64_t>);
|
||||
CHECK_INSERTED_AS(float, value<double>);
|
||||
CHECK_INSERTED_AS(double, value<double>);
|
||||
#ifdef TOML_FP16
|
||||
CHECK_INSERTED_AS(TOML_FP16, value<double>);
|
||||
#endif
|
||||
#ifdef TOML_FLOAT16
|
||||
CHECK_INSERTED_AS(TOML_FLOAT16, value<double>);
|
||||
#endif
|
||||
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<double>()), double&>);
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<double>()), double&&>);
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<double>()), const double&>);
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<value<double>>()), double&>);
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<value<double>>()), double&&>);
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<value<double>>()), const double&>);
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<table>()), table&>);
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<table>()), table&&>);
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<table>()), const table&>);
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<array>()), array&>);
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<array>()), array&&>);
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<array>()), const array&>);
|
||||
#define CHECK_NODE_REF_TYPE(T) \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<T>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<volatile T>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<T&>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<volatile T&>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<T&&>()), T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<volatile T&&>()), volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const volatile T&&>()), const volatile T&&>); \
|
||||
\
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<T>()), T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const T>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<volatile T>()), volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const volatile T>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<T&>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<volatile T&>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<T&&>()), T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<volatile T&&>()), volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const volatile T&&>()), const volatile T&&>); \
|
||||
\
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<volatile T&&>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const volatile T&&>()), const volatile T&&>); \
|
||||
\
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<T>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const T>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<volatile T>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const volatile T>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<volatile T&&>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const volatile T&&>()), const volatile T&&>)
|
||||
|
||||
CHECK_NODE_REF_TYPE(table);
|
||||
CHECK_NODE_REF_TYPE(array);
|
||||
CHECK_NODE_REF_TYPE(std::string);
|
||||
CHECK_NODE_REF_TYPE(int64_t);
|
||||
CHECK_NODE_REF_TYPE(double);
|
||||
CHECK_NODE_REF_TYPE(bool);
|
||||
CHECK_NODE_REF_TYPE(date);
|
||||
CHECK_NODE_REF_TYPE(time);
|
||||
CHECK_NODE_REF_TYPE(date_time);
|
||||
|
||||
#define CHECK_NODE_VIEW_REF_TYPE(T) \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<T>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<volatile T>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<T&>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<volatile T&>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<T&&>()), T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<volatile T&&>()), volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const volatile T&&>()), const volatile T&&>)
|
||||
|
||||
CHECK_NODE_VIEW_REF_TYPE(table);
|
||||
CHECK_NODE_VIEW_REF_TYPE(array);
|
||||
CHECK_NODE_VIEW_REF_TYPE(std::string);
|
||||
CHECK_NODE_VIEW_REF_TYPE(int64_t);
|
||||
CHECK_NODE_VIEW_REF_TYPE(double);
|
||||
CHECK_NODE_VIEW_REF_TYPE(bool);
|
||||
CHECK_NODE_VIEW_REF_TYPE(date);
|
||||
CHECK_NODE_VIEW_REF_TYPE(time);
|
||||
CHECK_NODE_VIEW_REF_TYPE(date_time);
|
||||
|
||||
#define CHECK_CONST_NODE_VIEW_REF_TYPE(T) \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<volatile T&&>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const volatile T&&>()), const volatile T&&>)
|
||||
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(table);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(array);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(std::string);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(int64_t);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(double);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(bool);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(date);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(time);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(date_time);
|
||||
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<double>()), double&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<double>()), const double&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<value<double>>()), double&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<value<double>>()), const double&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<table>()), table&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<table>()), const table&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<array>()), array&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<array>()), const array&>);
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ namespace leakproof
|
||||
void value_destroyed() noexcept;
|
||||
}
|
||||
|
||||
#define TOML_LIFETIME_HOOKS 1
|
||||
#define TOML_TABLE_CREATED ::leakproof::table_created()
|
||||
#define TOML_TABLE_DESTROYED ::leakproof::table_destroyed()
|
||||
#define TOML_ARRAY_CREATED ::leakproof::array_created()
|
||||
#define TOML_ARRAY_DESTROYED ::leakproof::array_destroyed()
|
||||
#define TOML_VALUE_CREATED ::leakproof::value_created()
|
||||
#define TOML_VALUE_DESTROYED ::leakproof::value_destroyed()
|
||||
#define TOML_LIFETIME_HOOKS 1
|
||||
#define TOML_TABLE_CREATED ::leakproof::table_created()
|
||||
#define TOML_TABLE_DESTROYED ::leakproof::table_destroyed()
|
||||
#define TOML_ARRAY_CREATED ::leakproof::array_created()
|
||||
#define TOML_ARRAY_DESTROYED ::leakproof::array_destroyed()
|
||||
#define TOML_VALUE_CREATED ::leakproof::value_created()
|
||||
#define TOML_VALUE_DESTROYED ::leakproof::value_destroyed()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user